That's pretty slick, this article explains it pretty well: http://spin.atomicobject.com/2013/02/08/bit-banding/
IMO that article just confuses me.
the link on the ARM website doesn't help much either.
Then the example? I should submit this code to www.thedailywtf.com Why the mailbox analogy?? for something supposedly atomic. Is it like an example of a single bit mailbox between processes?
#define BITBAND_SRAM_REF 0x20000000#define BITBAND_SRAM_BASE 0x22000000#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 \ + (b*4))) // Convert SRAM address#define BITBAND_PERI_REF 0x40000000#define BITBAND_PERI_BASE 0x42000000#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 \ + (b*4))) // Convert PERI address
#define MAILBOX 0x20004000#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}
"// Convert PERI address" what a useless comment, it only makes sense if you know what they are doing.
Is it implemented in hardware? I guess you have to set up the bit banding to work in certain memory areas and by default they are normally turned off.
If you set it up for an area then you reduce the memory available drastically.
Is it only for peripherals? It seems not, the mailbox is in RAM.
Can anyone explain it a bit more clearly? Or have another link?
I am going to try and explain my understanding of it. Let's first explain what issue it's trying to solve.
Suppose you have a register in memory that is of value 01001001. And suppose the first bit of that byte (currently 0) determines the GPIO pin mode and you want to flip it. You would have to load the entire byte 01001001 just to manipulate that one bit.
Why is this bad, you might ask? Well depending on how you manipulate it your manipulation might take multiple clock cycles to flip just that one bit, because you're dealing with a much bigger chunk of data. If your flipping of that bit takes multiple CPU cycles chances are something else might try to manipulate that byte and cause a race condition. It's basically equivalent of multiple people editing their local copies of the same spreadsheet, you get a mess, you don't know which one is the correct one.
For example, let's call your main program flow, program A, and some piece of code that runs on an interrupt, interrupt B.
Your program A is trying to flip the first bit, it reads the register. So far so good, but before it gets a chance to write the modified version of it, interrupt B piece of code flips a different bit in that byte. And since your program A is unaware it tries to save a stale version of the register byte into the memory, overwriting the change interrupt B was trying to accomplish. Very bad.
So to help developers avoid race condition Bit-banding was implemented. Bit-banding is a pseudo memory location with an interesting property. It's basically a mirror of all the registers but instead of storing 8 bits per byte it only stores one significant bit per byte.
So our little 01001001 becomes 8 distinct bytes in the bit-banding space: 00000000 (only holding the our first bit), 0100000 (only holding the 2nd bit)...etc The bytes in the bit-banding space are interconnected behind the scenes, and flipping a bit in one space, alters it in the other.
So now you can safely take a byte from the bit-banding location to only modify one bit without the fear of accidentally overwriting other bits with stale state. There is also a mention that manipulation bit-banding bytes is a single clock cycle operation making it fully atomic (impervious to race conditions, even on the same bit).
ps. bit-banding sounds terribly memory inefficient, you know "exploding" a byte into 8 bytes each containing 1 bit, but most likely it's all done logically so no memory is actually wasted, it's just wired like that behind the scenes.