The Cortex-M3 processor has a feature called Bit Banding that allows each individual bit in a word of memory to be referenced and manipulated as if it were a byte in memory. This provides faster read and write access to individual bits compared to using regular bitwise operations. The Bit Band regions map each bit in the SRAM and Peripheral memory regions to a unique alias address in two dedicated Bit Band areas of the memory map. This article will explain what Bit Banding is, how it works, and how to use it effectively in Cortex-M3 based applications.
What is Bit Banding?
Bit Banding provides atomic read-modify-write access to individual bits in the SRAM and Peripheral memory regions of a Cortex-M3 processor. This means you can directly read, set, clear or toggle bits at single bit addresses without having to perform a read-modify-write sequence with bitwise operators. Bit Banding maps each bit in the SRAM and peripheral memory regions to a unique alias address in the Bit Band memory regions. Writes to these Bit Band alias addresses will set or clear the corresponding bit in the target memory. Reads from the alias addresses will return the value of the mapped bit. This provides faster access compared to regular bitwise operations which require multiple instructions to read, modify and write back a bit value.
Cortex-M3 Memory Map with Bit Band Regions
The Cortex-M3 memory map includes two dedicated Bit Band regions – one for the SRAM memory and one for the Peripheral memory regions. These sit in the upper part of the 4GB memory map, but are each only 1MB in size.
The SRAM Bit Band region covers addresses 0x20000000 to 0x200FFFFF. This maps each bit in the lower 1MB SRAM region at 0x200000xx to a byte address in the Bit Band area. For example, bit 3 of the SRAM word at 0x20000010 is mapped to 0x2002802C.
The Peripheral Bit Band region covers 0x40000000 to 0x400FFFFF. This maps each bit in the Peripheral memory region 0x40000000 to 0x5FFFFFFF. So bit 5 of the peripheral register at 0x40002020 would be mapped to 0x4200A05C.
How Bit Band Address Mapping Works
The mapping between a bit in the SRAM/Peripheral regions and the alias address in the Bit Band region works as follows:
- Take the byte address of the SRAM/Peripheral target location (e.g. 0x20000010)
- Subtract the base address of the region (0x20000000 for SRAM, 0x40000000 for Peripheral)
- Multiply this offset by 32 to get the number of bits from the start of the region
- Add this to the base address of the Bit Band region (0x20000000 or 0x40000000)
- Add the target bit number * 4 to get the final alias address
So for example, to find the alias address for bit 3 of 0x20000010:
- 0x20000010 – 0x20000000 = 0x00000010
- 0x00000010 * 32 = 0x00000800
- 0x20000000 + 0x00000800 = 0x20020800
- 0x20020800 + (3 * 4) = 0x2002802C
This maps bit 3 of SRAM address 0x20000010 to Bit Band alias address 0x2002802C.
Reading Bits with Bit Banding
To read the value of a bit using Bit Banding, you simply read from the mapped alias address. For example: int bit = *((volatile unsigned int*)0x2002802C);
This will load the value of bit 3 of 0x20000010 into the bit variable. The volatile pointer indicates that this should always perform a read rather than caching the value.
Writing Bits with Bit Banding
Writing to a Bit Band alias address will set or clear the corresponding bit in the target memory location. For example: *((volatile unsigned int*)0x2002802C) = 1; // Sets bit 3 of 0x20000010 to 1 *((volatile unsigned int*)0x2002802C) = 0; // Clears bit 3 of 0x20000010 to 0
Note that the entire word at the alias address is set to 1 or 0. But this just affects the mapped bit in the target SRAM location.
Toggling Bits
You can toggle bits using a read-modify-write approach: int bit = *((volatile unsigned int*)0x2002802C); bit = !bit; *((volatile unsigned int*)0x2002802C) = bit;
This reads the bit value, inverts it, and writes it back to toggle the bit.
Atomic Bit Manipulation
The key benefit of Bit Banding is that bit manipulation via the alias addresses is atomic. This means the read-modify-write happens without any risk of interruption. With regular bitwise operators, you would need to disable interrupts while reading, modifying and writing back the bit value to ensure atomic access. Bit Banding removes this need.
Using Bit Banding Efficiently
There are some best practices to follow when using Bit Banding:
- Use volatile pointers for any alias address access
- Try to group Bit Banded variables together to minimize alias address lookups
- Use inline functions to abstract Bit Band access and hide address lookups
- Consider memory alignment to maximize use of single word alias addresses
For example, you could define a header with inline functions like: static inline void set_bit(int bit_number) { *((volatile unsigned int*)BIT_BAND_ALIAS[bit_number]) = 1; } static inline void clear_bit(int bit_number) { *((volatile unsigned int*)BIT_BAND_ALIAS[bit_number]) = 0; } static inline int get_bit(int bit_number) { return *((volatile unsigned int* )BIT_BAND_ALIAS[bit_number]); } static inline void toggle_bit(int bit_number) { int bit = get_bit(bit_number); bit = !bit; *((volatile unsigned int*)BIT_BAND_ALIAS[bit_number]) = bit; }
This hides the mapping lookups and bit manipulation details behind simple function calls.
When to Avoid Bit Banding
There are a few cases where Bit Banding may not be the best approach:
- If you need to manipulate multiple bits simultaneously, regular bitwise operations may be faster
- In code size constrained applications, the function call overhead may outweigh the benefits
- If memory regions are not aligned, you may not be able to fully utilize word alias addresses
- When atomicity is not required, regular bitwise operations will suffice
So in performance critical scenarios, or when code size is limited, regular bit manipulation may make more sense than using Bit Banding.
Conclusion
The Cortex-M3 Bit Banding feature provides atomic read-modify-write access to individual bits in memory without locking interrupts. This can make bit manipulation more efficient compared to regular bitwise operators. To use this feature, you reference bit alias addresses that map to each bit in the SRAM and Peripheral memory regions. Reads and writes to these addresses will access the corresponding bit. This enables fast set, clear and toggle operations on target bits. With some care taken in abstracting the address mapping, Bit Banding can produce cleaner and more maintainable bit manipulation code.
While there are cases when regular bitwise operations may be preferred, Bit Banding is a useful tool for any Cortex-M3 developer to have in their kit. Understanding how to best utilize this hardware feature can lead to more robust and efficient microcontroller firmware.