7

I was trying to change the value of DDRB by its memory address with the following code:

*(volatile byte*) 0x04 = 0b00100000;

It did not work.

I got the value 0x04 from a post on the Arduino forum, and they claim to have gotten it from the datasheet that looks like this:

enter image description here

It says 0x04 next to it, but my code only started working when I switched to 0x24, the value inside the parentheses. This is the same for PORTB and I assume all the other port related registers.

What does 0x04 point to, how does it relate to DDRB, and why is 0x24 in parenthesis if that is the actual address?

ocrdu
  • 8,705
  • 21
  • 30
  • 42
luek baja
  • 259
  • 1
  • 6

2 Answers2

8

For the lower 64 IO registers, there are two addresses. The first (0x04 in this example) is used for access using certain I/O instructions such as out (write to IO register) and sbi (set bit in register). The larger value address (0x24 here) address, or only address for higher registers is used for memory access instructions such as sts (store to SRAM).

The latter address is higher because the AVR uses a unified memory address range, where the lower 0x00-0x1F are the 32 registers in the register map (r0-r31), so for memory access (your pointer dereference) you have to use the true address of the register.

For example, this is the address map for the ATMega328p taken from its datasheet:

Atmega328p Address Map

This is noted in the device datasheet in the register map section:

Notes from datasheet about address usage

Better yet, if using avr-gcc, #include <avr/io.h> and use the defines for each register (e.g. PORTB) which already take care of working out which is the correct address to use. These defines will properly optimise to use the in/out instructions where possible.

Tom Carpenter
  • 63,168
  • 3
  • 139
  • 196
5

AVR has a Harvard architecture. The I/O registers of these devices are mapped into two of the memory spaces.

In I/O addressing (e.g. IN and OUT opcodes), use the addresses 0x00 - 0x3F.

When using the data address space (e.g. LD/ST opcodes, which is what C generates), you must add 0x20 to access these I/O registers.

See section 8.5 I/O Memory of the datasheet for more information.

Jacob Krall
  • 153
  • 1
  • 6