Welcome to the second installment of the “Programming embedded systems” series. Today’s subject, covered in lesson 7, is arrays and pointer arithmetic, but obviously, with an embedded twist.
Lesson 7 – Arrays and pointer arithmetic
The motivating example for this lesson is the GPIO (General-Purpose Input/Output) peripheral in the TivaC microcontroller, which you need to program in order to control the composite LED on the LaunchPad board. The TivaC GPIO design is rather unusual because it allows independent addressing of every possible combination of the 8-bits in the GPIO group. This elaborate design, called “bit masking through address lines” in the TivaC Datasheet, requires 256 separate addresses (and offers an excellent case for applying arrays in C).
What Is the Problem?
The first obvious question is why would the hardware designers of the TivaC GPIO go into such trouble. After all, they could simply treat the 8-bits in a GPIO group like a byte in RAM, which you could then manipulate in the usual way. In fact, they already provide it. For example, here is the code from the previous lesson 6 that sets the bit corresponding to the red LED, leaving all other bits in the GPIO_PORTF group unchanged:
GPIO_PORTF_DATA_R |= LED_RED;
I suppose this is how most of us are used to doing this. But it turns out that such a “usual” code represents a read-modify-write sequence. The sequence can be problematic, especially in the load-store CPU architecture like ARM, where the code compiles into three instructions:
A sequence like that can be trouble if it is interrupted, and the interrupt (or a separate RTOS task) also modifies the same GPIO_PORTF group, although perhaps other bits in it.
The TivaC hardware designers were clearly aware of such concurrency hazards, and therefore they devised a way to update the individual GPIO bits without the dreadful read-modify-write sequence. Instead, not only every GPIO bit, but even every combination of the 8 GPIO bits, can be updated with one STR instruction. A single instruction is naturally atomic and eliminates concurrency hazards.
Some YouTube viewers commented that the TivaC GPIO design is just another example of “bit-banding” of the peripheral memory region in the Cortex-M4. Bit-banding is based on a similar idea of memory aliasing, where each bit in the primary region has a separate address in the secondary, aliased region. But for bit-banding of the 8 GPIO bits, you would need only 8 addresses. TivaC GPIO goes beyond that by providing 256 addresses, which allow you to atomically set any combination of the 8 GPIO bits.
An important takeaway from this lesson is that peripheral registers are not memory, even though the CPU accesses them using the same load and store instructions for accessing memory. For example, writing to most of the 256 GPIO registers does not read back as the same value. Some peripheral registers cannot be read at all (write-only registers), which never happens with “real” memory!
In the next lesson, you will learn about functions and see how they work at the low level. Stay tuned!
For more Embedded, subscribe to Embedded’s weekly email newsletter.
You must Sign in or Register to post a comment.
This site uses Akismet to reduce spam. Learn how your comment data is processed.
Programming embedded systems: Arrays and pointer arithmetic – Embedded