bit banding


Bit Banding is a method of performing atomic bitwise modifictions to memory. If you have used small PIC micros before these are like BSF and BCF (Bit Set and Bit Clear)


Usually changing a word in memory requires a read-modify-write cycle. If this operation is interrupted there can be data loss.


Read (0xaa) from A to register
Write (0x33) to A
Modify (0xaa to 0xab)
Write (0xab) to A

(0x33) data has been lost!
The is avoided by disabling interrupts/using a supervisor mode or by using bit-banding as shown here.


Two 1MB 'bit-band' regions, one in the peripheral memory area and one in the SRAM memory areas are each mapped to a 32MB virtual 'alias' region. Each bit in the bit-band region is mapped to a 32bit word in the alias region.

The first bit in the 'bit-band' peripheral memory is mapped to the first word in the alias region, the second bit to the second word etc.

/media/uploads/rod_vdb/arm_bit-band.png Image: UM1360 NXP LPC17XX User Manual, Accessed 12/1/2011

Writing a value to the alias region with Least Significant Bit i.e. bit[0] set to 1 will write a value of 1 to the bit-band bit. Conversely writing a value of 0 will clear the bit-band bit. The value of the bits[31:1] in the alias region for any word are unmapped and will have no effect on the bit-band value.

Calculating addresses


alias_word_address = alias_region_base + (bit_band_byte_offset x 32) + (bit_number x 4) 

alias_word_address => Where to write to in order to change bit-band value
alias_region_base => Starting memory location of alias
bit_band_byte_offset => Difference between target bit-band byte address and base of bit-band memory location
bit_number => 0-7 the number of the bit in the bit-band you would like to change.

0x20000000 ==> Base address of SRAM
0x22000000 ==> Base address of SRAM alias region

0x40000000 ==> Base address of peripheral region
0x42000000 ==> Base address of peripheral alias region

How it is done

// Define base address of bit-band
#define BITBAND_SRAM_BASE 0x20000000
// Define base address of alias band
#define ALIAS_SRAM_BASE 0x22000000
// Convert SRAM address to alias region
#define BITBAND_SRAM(a,b) ((ALIAS_SRAM_BASE + (a-BITBAND_SRAM_BASE)*32 \    + (b*4)))

// Define base address of peripheral bit-band
#define BITBAND_PERI_BASE 0x40000000
// Define base address of peripheral alias band
#define ALIAS_PERI_BASE 0x42000000
// Convert PERI address to alias region
#define BITBAND_PERI(a,b) ((ALIAS_PERI_BASE + (a-BITBAND_PERI_BASE)*32 \    + (b*4)))

//Define some memory address
#define MAILBOX 0x20004000
//Define a hardware register
#define TIMER 0x40004000

// Mailbox bit 0
#define MBX_B0 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,0))) 
// Mailbox bit 7
#define MBX_B7 *((volatile unsigned int *)(BITBAND_SRAM(MAILBOX,7))) 
// Timer bit 0
#define TIMER_B0 *((volatile unsigned char *)(BITBAND_PERI(TIMER,0))) 
// Timer bit 7
#define TIMER_B7 *((volatile unsigned char *)(BITBAND_PERI(TIMER,7)))

int main(void){    
    unsigned int temp = 0;
    MBX_B0 = 1; // Word write    
    temp = MBX_B7; // Word read    
    TIMER_B0 = temp; // Byte write    
    return TIMER_B7; // Byte read

Code: modified for naming used in text

More Code:

There is some nicer written code: it does the same thing but it a bit prettier.


Use this method when you need atomic (non interruptible) changes to a bit in SRAM or peripheral mapped memory.

If you don't need atomic changes then this process is slower as you can only change one bit at a time.

In certain circumstances (changing lots of bits) it may be quicker to disable interrupts, make the changes and re-enable interrupts.

Hope this helps