Thursday, June 18, 2015

Understanding Bit Banding in ARM Cortex-M

Bit Banding is a method of performing atomic bit manipulation. Usually, manipulating a bit in a word requires read-modify-write cycle which is interruptible, potentially causing data coherency issue. To avoid this, interrupts should be disabled before bit manipulation to overcome data coherency issues. This will result in unnecessary usage of CPU cycles. So ARM introduced "Bit Banding" in Cortex-M3 and Cortex-M4.

This allows every bit in bit banding region to be directly accessible from a word aligned address using simple LDR instruction. The memory map of Cortex-M3 has two 32MB alias region that map to two 1MB of bit banding region. One is for SRAM bit banding and other is for peripheral bit banding. Each bit in bit banding region is accessible from a word aligned address. It is the responsibility of system bus to map alias address to appropriate bit in bit banding region.

SRAM bit banding region is from 0x20000000 to 0x200FFFFF and its respective alias is from 0x22000000 to 0x23FFFFFC. Peripheral bit banding region is from 0x40000000 to 0x400FFFFF and its respective alias is from 0x42000000 to 0x43FFFFFC.

LPC1768 has two 16kB SRAM and GPIO block available for bit banding within the address region of SRAM. SRAM bit banding region on LPC1768 is from 0x2007C000 to 0x20083FFF(32kB). GPIO bit banding region on LPC1768 is from 0x2009C000 to 0x2009FFFF. APB0 and APB1 peripheral are available on peripheral bit banding region.

Calculating alias address for bit banding region is pretty simple,

alias_addr = alias_base_addr + ((bit_banding_addr - bit_banding_base_addr) * 32) + (bit * 4)

where,


  • alias_base_address is base address of alias which is 0x22000000 for SRAM bit banding region.
  • bit_banding_addr  is actual bit banding address.
  • bit_banding_base_addr is base address of bit banding region which for SRAM bit banding region is 0x20000000.
  • bit is the bit in bit_banding_addr.
Lets consider that I want to set bit 0 at 0x2007C000. So the alias address would be,

0x22000000 + ((0x2007C000 - 0x20000000) * 32) + (0 * 4) which would result in 0x22F80000.

So, *((volatile unsigned int *)0x22F80000) = 1; would set 0th bit of SRAM memory at 0x2007C000 and *((volatile unsigned int *)0x22F80004) = 1; would set first bit of SRAM memory at 0x2007C000.

Happy bit banding....