ARM Cortex-M Bit Banding
Bit banding is a feature of ARM Cortex-M processors that maps up-to 1Mb each of on-chip SRAM and peripheral registers to a larger region where each 32 bit address corresponds to a single bit of the physical memory. Setting the bitband address to zero or non-zero directly and atomically sets the corresponding physical memory bit to zero or one respectively, without the need for read-modify-write operations or critical sections.
This allows for efficient implementation of bit arrays and bitmaps in SRAM, but allows fast atomic manipulation od single-bit fileds in peripheral registers for enabling/disabling interrupts, testing status flags etc.
The function in this example returns the bitband address of the single bit specified by a physical address and a bit offset. The returned address can be used to access that single bit or as the start address of a bit array (which you should note need not be word or even byte aligned).
Usage examples are provided.
#include <stdint.h>
//! @brief Convert word address + bit position to bitband address.
//!
//! @param address Word address containing of bit
//! @param bit Bit offset (0 = LSB, 31 = MSB)
//! @return Address of bit in bitband region.
volatile uint32_t* getBitBandAddress( volatile void* address, int bit )
{
uint32_t addr = (uint32_t)address ;
uint32_t word_band_base = addr & 0xf0000000 ;
uint32_t bit_band_base = word_band_base | 0x02000000 ;
uint32_t offset = addr - word_band_base ;
return (volatile uint32_t*)(bit_band_base + (offset * 32) + (bit * 4)) ;
}
--- EXAMPLES ---
// Example usage 1: 160 bit array
uint32_t physical_memory[5] = {0} ;
uint32_t* bit_array = getBitBandAddress( physical_memory, 0 ) ;
int bit_array_length = sizeof(physical_memory) * CHAR_BIT ;
for( i = 0; i < bit_array_len; i++ )
{
bit_array[i] = rand() % 2;
}
// Example usage 2: STM32 USART1 Tx Int Enable/Disable
uint32_t* tx_intr_enable_bit_addr = getBitBandAddress( (&(USART1->CR1)), 7 ) ;
*tx_intr_enable_bit_addr = 0 ; // Disable Tx
*tx_intr_enable_bit_addr = 1 ; // Enable Tx
// Example usage 3: C++ reference version of example 2
uint32_t& tx_intr_enable_bit = *getBitBandAddress( (&(USART1->CR1)), 7 ) ;
tx_intr_enable_bit = 0 ; // Disable Tx
tx_intr_enable_bit = 1 ; // Enable Tx