When working with peripherals, we need to be able to read and write to the device’s internal registers. How we achieve this in C depends on whether we’re working with memory-mapped IO or port-mapped IO. Port-mapped IO typically requires compiler/language extensions, whereas memory-mapped IO can be accommodated with the standard C syntax.
Embedded “Hello, World!”
We all know the embedded equivalent of the “Hello, world!” program is flashing the LED, so true to form I’m going to use that as an example.
The examples are based on a STM32F407 chip using the GNU Arm Embedded Toolchain .
The STM32F4 uses a port-based GPIO (General Purpose Input Output) model, where each port can manage 16 physical pins. The LEDS are mapped to external pins 55-58 which maps internally onto GPIO Port D pins 8-11.
Flashing the LEDs
Flashing the LEDs is fairly straightforward, at the port level there are only two registers we are interested in.
- Mode Register – this defines, on a pin-by-pin basis what its function is, e.g. we want this pin to behave as an output pin.
- Output Data Register – Writing a ‘
1‘ to the appropriate pin will generate voltage and writing a ‘
0‘ will ground the pin.
Mode Register (MODER)
Each port pin has four modes of operation, thus requiring two configuration bits per pin (pin 0 is configured using mode bits 0-1, pin 2 uses mode bits 2-3, and so on):
10 Alternative function (details configured via other registers)
So, for example, to configure pin 8 for output, we must write the value 01 into bits 16 and 17 in the MODER register (that is, bit 16 => 1, bit 17 => 0).
Output Data Register (ODR)
In the Output Data Register (ODR) each bit represents an I/O pin on the port. The bit number matches the pin number.
If a pin is set to output (in the MODER register) then writing a 1 into the appropriate bit will drive the I/O pin high. Writing 0 into the appropriate bit will drive the I/O pin low.
There are 16 IO pins, but the register is 32bits wide. Reserved bits are read as ‘0’.
Port D Addresses
The absolute addresses for the MODER and ODR of Port D are:
- MODER –
- ODR –
Pointer access to registers
Typically when we access registers in C based on memory-mapped IO we use a pointer notation to ‘trick’ the compiler into generating the correct load/store operations at the absolute address needed. Continue reading