Bit Banding
WHAT?
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)
WHY?
Usually changing a word in memory requires a read-modify-write cycle. If this operation is interrupted there can be data loss.
<<info>>
Read (0xaa) from A to register
Interrupt!
Write (0x33) to A
Return!
Modify (0xaa to 0xab)
Write (0xab) to A
<</info>>
(0x33) data has been lost!
The is avoided by disabling interrupts/using a supervisor mode or by using bit-banding as shown here.
HARDWARE
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.
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
<<code>> alias_word_address = alias_region_base + (bit_band_byte_offset x 32) + (bit_number x 4) <</code>>
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
<<code>> 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>> Code: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/CHDJHIDF.html modified for naming used in text
More Code:
There is some nicer written code: http://www.micromouseonline.com/blog/2010/07/13/bit-banding-in-the-stm32 it does the same thing but it a bit prettier.
Recap
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
Sources
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/Babgcaie.html
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4203.html
http://www.micromouseonline.com/blog/2010/07/13/bit-banding-in-the-stm32
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/CHDJHIDF.html
3 comments on Bit Banding:
Please log in to post comments.
FYI, LPC1700 does not implement bit banding. For atomic updates you can use
__strex
intrinsic. For GPIOs you have set and clear registers using which you can set or clear any set of pins for a port at once, not changing the rest.