2022-01-31

1. Register review

The word “register” is an overloaded term (think of operator overloading in C++, Python, or other languages).

From the bottom-up perspective[1], any register is a group of N-DFFs that are treated as an N-bit entity.

1.1. The cast of characters

On the AVR architecture, there are “registers” of several slightly different flavors:

  • PC Program Counter. It’s own separate set of DFFs that is accessible only by a few instructions. Increments by +1 otherwise. Not typically called a “register” in a sentence, but truly is one. All CPUs have a Program Counter because it keeps track of the next instruction to execute.

  • R0 .. R31 General Purpose Working Registers. These are in the Register File, a term that simply means they are a special block of logic+FFs where several can be read and updated in a single clock cycle. Think of these like variables.

    • On AVR, the upper six can be paired up and operate as 16-bit entities. When used as such, they get new (human) names:

      • X (R27 : R26) (MSB : LSB)

      • Y (R29 : R28)

      • Z (R31 : R30)

      • Several instructions use X / Y / Z, so the 8-bit registers R26 : R31 are rarely used for general 8-bit variables.

  • SREG (or SR in other architectures). Special bits which:

    • Hold status and control bits that are critical to the behavior of the CPU (bit I, Global Interrupt Enable)>

    • Get updated with the result of an ALU operation. (C, Z, N, V, H).

    • Handy utility functionality (T and N ⨁ V = S).

    • On AVR, this register is in the I/O Memory address space.

  • I/O Registers. These are the locations whose bits configure various peripherals or extra features of the MCU. Timer, ADC, or GPIO configuration registers, etc.

  • SP (SPH:SPL) Stack Pointer. Holds the data memory (SRAM) address of the “top of (the) stack” (TOS).

    • Like the SREG, the SPH and SPL registers are in the I/O Memory address space.

    • Special instructions put the PC value onto the stack (RCALL) or take the value on the top of the stack and updates the PC (RET or RETI).

    • Another pair of instructions puts a register’s value onto the stack (PUSH) or takes the value on the top of the stack and places into a register (POP).

1.2. Q: PC bit width

How many bits wide is the Program Counter on the following MCUs? (What is required of the PC on a particular platform?)

  • ATtiny85

  • ATmega328P

  • MSP430FR6989

Don’t click this until you have your own answers!

8, 8, and 16 bits


Seems legit, but none of these are correct. Time to bust out some datasheets, review again what the PC is all about, and try again.

1.3. I/O Registers

Where can you find a compact listing of all the I/O Registers on the ATtiny85?

What is the I/O memory address of SREG, SPH, and SPL?

Be specific.

ATtiny85 Datasheet, Section 23 "Register Summary," page 200.

  • SREG 0x3F

  • SPH 0x3E

  • SPL 0x3D

Using Hypothesis: ATtiny85_Datasheet.pdf, or in the GDrive docs / AVR folder.

2. IF (branch) instructions

When you come to a fork in the road, take it.
— Yogi Berra

You may be suprised to find out that there are only two branch instructions that can jump to an arbitrary place:

BRBC s, k

Jump to (PC + 1 + k) if bit s in the Status Register (SREG) is clear (zero), otherwise continue to the next instruction.

BRBS s, k

Jump to (PC + 1 + k) if bit s in the Status Register (SREG) is set (one), otherwise continue to the next instruction.

Since there are 8 bits in SREG and two clear/set possibilities for each:

How many possible BR__ instructions are there (not counting BRBC and BRBS) in the ATtiny85?

Did you look up §24 Instruction Set Summary in the Datasheet?

There are NOT 16 listed!

¿¿ why ??

2.1. Q: Why instruction aliases?

Why does the Assembly Instruction Set list all of these extra branch instructions when they are simply BRB{C,S} machine codes with specific values of s.

2.2. Q: Skip instructions vs. branch?

Study the following pairs of instructions in the AVR-InstructionSet-Manual-DS40002198_2021.pdf:

  • SBI{C,S}

  • SBR{C,S}

How would you program this behavior without these instructions?

Why are there two pairs instead of just one pair?

Describe a practical situation where you would use one of these instructions.

3. Bit instructions

Similar to the Status Register branching instructions BRB{C,S}, the 16-member family of SREG bit setting and bit clearing instructions are covered by the pair

  • BSET s and BCLR s

Having assembly mnemonics that directly describe the intended operation make it easier for the programmer to describe the intent of the code in a more human-friendly way. For example, consider SEI versus BSET 7 to set the Global Interrupt Enable bit.

The BST and BLD instructions are interesting because they allow using the SREG’s T bit as a mini, 1-bit register.

Copying a single bit between registers, or even within a register without this feature requires a bunch of shifting and masking. See the following example in C, perhaps there is a better way?

// copy bit 3 of A to bit 1 of B
// A = 0b10001000
//           │
//           ╰─╮
//             │
// B = 0b11001011

uint8_t A = 0b10001000;  // setup
uint8_t B = 0b11001001;
uint8_t temp;

temp = A >> (3-1);  // shift bit 3 into position 1
temp &= (1 << 1);   // clear all other bits from the shifted a
B &= ~(1 << 1);     // zero the destination position
B |= temp;          // place bit in destination position

Translated to assembly:

.def r16 = rA
.def r17 = rB
.def r20 = rTmp

    ldi  A, 0b10001000      ; setup
    ldi  B, 0b11001001

    mov  rTmp, rA            ; copy A
    andi rTmp, 0b00001000    ; mask bit 3
    lsr  rTmp, 2             ; move to position
    andi rB,   0b11111101    ; mask destination bit 1
    or   rB,   tmp           ; put bit into destination
; 1 cycle each ==> 5 cycles

Finally, using the BLD and BST instructions:

    bld rA, 3   ; copy rA[3] bit into T
    bst rB, 1   ; copy T to rB[1]

; 1 cycle each ==> 2 cycles

These sorts of features have more advantages that just the obvious ones of less code and faster execution.

These special instructions allow atomic operations that can’t be messed up.

  • An interrupt can happen at any point in a program’s execution, including at locations that would potentially cause a problem. (which is guaranteed to happen in a real system → so program defensively to ensure by design that it can’t cause a problem).

To make this real, this report details using electro-magnetic field injection to cause bad behavior in a microcontroller. It demonstrates that a Toyota ECU (engine control unit, the engine’s main computer) can sometimes command wide-open throttle under certain conditions.

Background: Wikipedia: Sudden unintended acceleration - Sudden acceleration in Toyota vehicles. Pay attention to the links in paragraph 5 of this section.

The Toyota case had many problems, but the technical cause was probably traceable to glitches that O’Flynn demonstrates.

Other earlier engineering failure analysis reports:


1. So we ensure we have a solid footing 🤣.