What is ARM Cortex-M4 Bit Banding-Embedded C Course Online

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

Example 07 — Source Code Deep-Dive

ARM Cortex-M4 Bit Banding

How a single memory write can atomically set or clear an individual bit — without read-modify-write — using the bit-band alias region and a simple address formula.

1. Overview — What This Example Does

The 007_bit_banding project demonstrates bit banding on the STM32F407 SRAM region. It:

  1. Writes 0xFF to SRAM address 0x20000200
  2. Clears bit 7 using the normal method: read → AND with mask → write (3-instruction sequence, not atomic)
  3. Resets to 0xFF
  4. Clears bit 7 using the bit-band method: single write to the alias address (1 instruction, atomic)

2. Source Code — Annotated

#include <stdint.h>

/* Bit-band alias base address for SRAM region */
#define ALIAS_BASE   0x22000000U   /* SRAM alias start */
#define BITBAND_BASE 0x20000000U   /* SRAM bit-band region start */

int main(void)
{
    /* Point to SRAM address 0x20000200 */
    uint8_t *ptr = (uint8_t*)0x20000200;

    /* Set all bits: ptr = 0xFF = 1111 1111 */
    *ptr = 0xff;

    /* ---- METHOD 1: Normal read-modify-write (NOT atomic) ----
     * Three separate bus transactions:
     *   1. Read: reg = *ptr       → reg = 0xFF
     *   2. Modify: reg &= ~(1<<7) → reg = 0x7F (clear bit7)
     *   3. Write: *ptr = reg      → *ptr = 0x7F
     * Problem: an interrupt between steps 1 and 3 could modify
     * *ptr and lose the ISR's change on the final write. */
    *ptr &= ~(1 << 7);

    /* Reset */
    *ptr = 0xff;

    /* ---- METHOD 2: Bit-band (ATOMIC) ----
     *
     * Formula:
     *   alias_addr = ALIAS_BASE + 32*(target_addr - BITBAND_BASE) + bit_number*4
     *
     * For clearing bit 7 of 0x20000200:
     *   alias_addr = 0x22000000 + 32*(0x20000200 - 0x20000000) + 7*4
     *             = 0x22000000 + 32*(0x200) + 28
     *             = 0x22000000 + 0x4000 + 28
     *             = 0x22000000 + 0x4000 + 0x1C
     *             = 0x2200401C
     *
     * Writing 0 to this alias address atomically clears bit7 of 0x20000200.
     * Writing 1 to this alias address atomically sets bit7 of 0x20000200.
     *
     * The hardware performs this as a single indivisible RMW cycle
     * on the memory bus — no interrupt can split it. */
    uint8_t *alias_addr = (uint8_t*)(ALIAS_BASE + (32*(0x20000200 - BITBAND_BASE)) + 7*4);

    /* Single write — atomically clears bit7 of 0x20000200 */
    *alias_addr = 0;   /* clear bit7 */

    for(;;);
}

3. Bit-Band Regions — Memory Map

Diagram: 3. Bit-Band Regions — Memory Map
0x20000000
SRAM Bit-Band Region (1MB) — contains the actual data bits
0x20100000
Normal SRAM (above bit-band region)
0x22000000
SRAM Bit-Band ALIAS Region (32MB) — 1 word per bit in bit-band region
0x23FFFFFF
End of SRAM alias
0x40000000
Peripheral Bit-Band Region (1MB) — APB1/APB2/AHB peripheral registers
0x42000000
Peripheral Bit-Band ALIAS Region (32MB) — 1 word per bit
0x43FFFFFF
End of peripheral alias
RegionStartEndSizeNotes
SRAM bit-band0x200000000x200FFFFF1 MBActual data; each byte has 8 alias words
SRAM alias0x220000000x23FFFFFF32 MB1 word (4 bytes) per bit of the 1MB region = 8M words = 32MB
Peripheral bit-band0x400000000x400FFFFF1 MBGPIO, UART, SPI, I2C, TIM registers
Peripheral alias0x420000000x43FFFFFF32 MBSame expansion: 1 word per bit

4. The Alias Address Formula

Universal formula:
alias_addr = ALIAS_BASE + 32 × (byte_addr − BAND_BASE) + bit_number × 4

For SRAM: ALIAS_BASE = 0x22000000, BAND_BASE = 0x20000000
For Peripheral: ALIAS_BASE = 0x42000000, BAND_BASE = 0x40000000

Formula Derivation

The bit-band alias region maps every individual bit of the bit-band region to a separate 32-bit word in the alias region:

  • The bit-band region has 1MB = 1,048,576 bytes = 8,388,608 bits
  • Each bit maps to one 32-bit word (4 bytes) in the alias region
  • 8,388,608 × 4 bytes = 33,554,432 bytes = 32MB alias region

To find which alias word corresponds to bit N of byte at address A:

  1. Byte offset from start of bit-band region: offset = A − BAND_BASE
  2. Bit 0 alias word for this byte: ALIAS_BASE + offset × 32 (= offset × 8 bits × 4 bytes per bit)
  3. Specific bit N’s alias word: add N × 4 (N words of 4 bytes each)
  4. Combined: alias = ALIAS_BASE + 32×offset + N×4

Worked Example from the Code

/* Target: bit 7 of address 0x20000200 */
/* SRAM ALIAS_BASE = 0x22000000 */
/* SRAM BITBAND_BASE = 0x20000000 */

byte_offset = 0x20000200 - 0x20000000 = 0x200 = 512

alias_addr = 0x22000000 + 32 * 512 + 7 * 4
           = 0x22000000 + 16384 + 28
           = 0x22000000 + 0x4000 + 0x1C
           = 0x2200401C

/* Writing 0 to 0x2200401C → clears bit7 of 0x20000200 */
/* Writing 1 to 0x2200401C → sets   bit7 of 0x20000200 */

/* The hardware translates this write into:
 * 1. Read the byte at 0x20000200
 * 2. Modify bit7 according to the written value
 * 3. Write back to 0x20000200
 * All as a single ATOMIC bus transaction */

Interactive Alias Calculator

Bit-Band Alias Address Calculator

SRAM (0x20000000)
0x20000200
7
Alias Address = 0x22000000 + 32×0x200 + 7×4 = 0x2200401C To SET bit 7 of 0x20000200: *(volatile uint32_t*)0x2200401C = 1; To CLR bit 7 of 0x20000200: *(volatile uint32_t*)0x2200401C = 0;

5. Why Bit Banding is Atomic

The ARM Cortex-M4 bit-band implementation performs the read-modify-write as a single locked bus transaction. The AHB (Advanced High-performance Bus) bus controller ensures that no other bus master (DMA, another processor core in multi-core systems) can access the bit-band address between the read and the write.

Normal RMW vs Bit-Band (Interrupt Safety)

/* SCENARIO: Main code and ISR both modify different bits of *ptr */

/* --- NORMAL METHOD (NOT interrupt-safe) --- */
/* Main: clearing bit 7 */
/* ISR fires between steps 2 and 3: modifies bit 0 */

/* Time 1: reg = *ptr = 0xFF (read) */
/* [IRQ fires here] */
/* ISR: *ptr &= ~(1<<0) → *ptr = 0xFE */
/* ISR returns */
/* Time 2: reg &= ~(1<<7) = 0x7F (still has old read value 0xFF) */
/* Time 3: *ptr = 0x7F ← ISR's change to bit0 is LOST! */

/* --- BIT-BAND METHOD (interrupt-safe) --- */
/* Writing 0 to bit7 alias = single atomic hardware RMW */
/* ISR writing to bit0 alias = separate atomic hardware RMW */
/* Both are safe: hardware arbitrates the bus transactions */

volatile uint8_t *reg = (uint8_t*)0x20000200;
#define BIT_BAND(addr, bit) \
    (*(volatile uint32_t*)(0x22000000 + 32*((uint32_t)(addr) - 0x20000000) + (bit)*4))

/* Atomic clear of bit 7 — ISR-safe */
BIT_BAND(reg, 7) = 0;

/* Atomic set of bit 0 — ISR-safe */
BIT_BAND(reg, 0) = 1;

6. Peripheral Bit Banding

The peripheral bit-band region covers 0x40000000–0x400FFFFF, encompassing all APB1, APB2, and AHB1 peripheral registers on the STM32F407. This allows atomic bit manipulation of peripheral registers — essential for GPIO and status bit operations.

GPIO Example — Toggle Single Pin Atomically

/* GPIOD ODR = 0x40020C14 (in the peripheral bit-band region) */
/* LED_GREEN = PD12 = bit 12 of GPIOD_ODR */

#define PERIPH_ALIAS_BASE 0x42000000U
#define PERIPH_BAND_BASE  0x40000000U

/* Calculate alias for bit 12 of GPIOD_ODR */
#define GPIOD_ODR       0x40020C14
#define GPIOD_ODR_BIT12_ALIAS \
    (PERIPH_ALIAS_BASE + 32*(GPIOD_ODR - PERIPH_BAND_BASE) + 12*4)

volatile uint32_t *led_bit = (uint32_t*)GPIOD_ODR_BIT12_ALIAS;

/* LED operations using bit-banding */
*led_bit = 1;    /* Set PD12 HIGH → LED on (atomic) */
*led_bit = 0;    /* Set PD12 LOW  → LED off (atomic) */
*led_bit ^= 1;   /* Toggle PD12 (read alias → XOR → write — still 2 ops internally) */

/* Generic macro for any peripheral bit */
#define PERIPH_BIT(addr, bit) \
    (*(volatile uint32_t*)(0x42000000 + 32*((uint32_t)(addr) - 0x40000000) + (bit)*4))

7. Bit Banding Limitations

LimitationDetails
Only 1MB covered per regionSRAM above 0x200FFFFF and peripherals above 0x400FFFFF have no bit-band alias. STM32F407’s SRAM1 (112KB starting 0x20000000) is fully covered; CCM RAM (0x10000000) is NOT.
Only Cortex-M3/M4/M7Cortex-M0/M0+/M23 do not support bit banding. Cortex-M33 does not include it. Not on modern Cortex-M55/M85.
Byte vs word widthBit-band alias is always a 32-bit word but only bit0 is significant. Writing a non-zero value sets the bit; writing 0 clears it. Any non-zero write (not just 1) sets the bit.
Cache coherencyIf a D-cache is used (Cortex-M7), bit-band alias and direct access may not be coherent. Must disable cache for affected regions or use proper cache maintenance.
Not for arbitrarily large bitsOnly individual bit positions 0–31 within a byte/halfword/word at 1-byte granularity. Cannot access bits of a 64-bit value atomically through bit banding.

8. Interview Questions & Answers

Q1. What is bit banding and which ARM cores support it?
Bit banding is a feature of certain ARM Cortex-M processors that maps individual bits of SRAM and peripheral registers to separate 32-bit words in an “alias” address region. Writing 0 or 1 to an alias word atomically clears or sets the corresponding bit in the actual memory/register.

Supported by: Cortex-M3, Cortex-M4 (including STM32F407), Cortex-M7.
NOT supported: Cortex-M0, Cortex-M0+, Cortex-M23, Cortex-M33, Cortex-M55.

The key advantage is atomicity — the hardware implements the read-modify-write as a single locked bus cycle, making it safe for use in interrupt-driven code without disabling interrupts.
Q2. What is the formula for calculating the bit-band alias address?
For SRAM bit-band region (0x20000000–0x200FFFFF):
alias = 0x22000000 + 32 × (addr − 0x20000000) + bit × 4

For Peripheral bit-band region (0x40000000–0x400FFFFF):
alias = 0x42000000 + 32 × (addr − 0x40000000) + bit × 4

As a C macro:
#define SRAM_BITBAND(addr, bit) \
  (*(volatile uint32_t*)(0x22000000 + 32*((addr)-0x20000000) + (bit)*4))
#define PERI_BITBAND(addr, bit) \
  (*(volatile uint32_t*)(0x42000000 + 32*((addr)-0x40000000) + (bit)*4))
Q3. How is bit banding different from the normal read-modify-write method?
Normal Read-Modify-Write:
1. LOAD: Read the byte/word from memory into a CPU register
2. MODIFY: AND/OR the register with a mask
3. STORE: Write the register back to memory
This is 3 separate bus transactions. An interrupt can fire between any of them, potentially causing a data race if the ISR modifies the same memory location.

Bit-Band Write:
1. Single STORE to the alias address
The hardware internally performs the RMW but as a single locked bus cycle — no interrupt can interleave. This is atomic at the hardware level, requiring no critical section or interrupt disabling.
Q4. Calculate the bit-band alias address for bit 3 of peripheral register at 0x40020810.
Using the peripheral formula:

alias = 0x42000000 + 32 × (0x40020810 − 0x40000000) + 3 × 4
= 0x42000000 + 32 × 0x20810 + 12
= 0x42000000 + 32 × 133136 + 12
= 0x42000000 + 4,260,352 + 12
= 0x42000000 + 0x411000 + 0xC
= 0x4241100C

Verification: 0x40020810 = GPIOB_IDR (GPIOB Input Data Register). Bit 3 = PB3. Writing to 0x4241100C would atomically set/clear PB3’s output. (Note: IDR is read-only; use ODR 0x40020814 for output.)
Q5. What value should you write to the alias address to set a bit vs clear a bit?
To set a bit: write any non-zero value to the alias word. By convention, write 1. The hardware ignores all bits except bit 0 of the written value and sets the target bit if bit 0 is 1.

To clear a bit: write 0 to the alias word.

Reading the alias word returns 0x00000000 if the bit is 0, or 0x00000001 if the bit is 1. Only bit 0 of the read value is meaningful — bits 31:1 always read as 0.

Important: a write of 0xFFFFFFFF still only sets the single targeted bit, not all bits in the byte. The alias address is a per-bit gateway, not a byte write to the underlying register.
Q6. Why doesn’t STM32F407’s CCM RAM support bit banding?
CCM (Core Coupled Memory) RAM at 0x10000000 is a separate 64KB SRAM connected directly to the CPU’s D-bus (data bus). It is NOT accessible via the AHB system bus (no DMA access). The bit-band mechanism is an AHB bus feature — when a write to the alias region occurs, the AHB arbiter executes an atomic locked RMW on the target address via the AHB bus.

Because CCM RAM bypasses the AHB and connects directly to the CPU, there is no AHB alias region for it. Any attempt to access CCM addresses via a bit-band alias will either produce a bus fault or access incorrect memory. The bit-band alias only works for addresses that go through the AHB: SRAM (0x20000000) and peripherals (0x40000000).
Q7. In what scenarios would you prefer bit banding over LDREX/STREX?
Comparison:

Bit banding: Single write instruction. Atomic on the AHB bus (hardware guaranteed). No retry loop. Simpler code. Works for any address in the bit-band region. No memory barrier needed.

LDREX/STREX (exclusive access): Standard ARMv7 atomic mechanism. Works on any aligned address. Requires a retry loop (if STREX fails due to concurrent access, try again). Supports atomic operations on words (not just individual bits). Works on Cortex-A multi-core systems where LDREX uses a distributed monitor. More portable and more flexible.

Choose bit banding when: you need to set/clear a single bit atomically in the SRAM or peripheral bit-band region on a Cortex-M3/M4/M7 single-core system, and you want the simplest possible code.

Choose LDREX/STREX when: you need atomic operations on wider values (16-bit, 32-bit, 64-bit), need portability across cores, or are on a multi-core system.
Q8. What is the size relationship between the bit-band region and its alias?
The ratio is exactly 32:1. Each byte in the bit-band region has 8 bits. Each bit maps to one 32-bit (4-byte) word in the alias. So each byte → 8 × 4 = 32 bytes in the alias. Therefore:
• 1MB bit-band region → 32MB alias region
• 1 byte → 32 bytes in alias (8 words of 4 bytes)
• 1 bit → 4 bytes (1 word) in alias

This explains why the SRAM bit-band region (0x20000000, 1MB) has an alias at 0x22000000 that spans 32MB (ends at 0x23FFFFFF), and the peripheral bit-band region (0x40000000, 1MB) has an alias at 0x42000000 spanning 32MB (ends at 0x43FFFFFF).

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *