BitBand:
Coretex M3共有4GB的記憶體定址空間,其中某些記憶體區域會當成Bit-band。例如SRAM內會有32MB拿來當成Bit-band alias,在此記憶體範圍內,每一個word位址會代表了bit-band內的一個bit (共1MB )。Cortex M3 的記憶體配置參考下圖。
Cortex-M3 有兩個 bit-band區域,
1. SRAM區域的第一個1MB處,0x20000000 – 0x200FFFFF。
2. 周邊區域的第一個1MB處,0x40000000 – 0x400FFFFF。
每次存取bit-band alias 都會造成對bit-band的存取。並且每次對於bit-band的存取都是一個不可分割(atomic)的運算。
每次存取bit-band alias 都會造成對bit-band的存取。並且每次對於bit-band的存取都是一個不可分割(atomic)的運算。
以 StellarisWare 提供的範例而言,hw_memmap.h記錄了記憶體分布的情況。其中可以看到 0x40000000– 0x400FFFFF的區間內,記錄了各種周邊裝置所對應的存取位置。如下:
#define WATCHDOG0_BASE 0x40000000 // Watchdog0
#define WATCHDOG1_BASE 0x40001000 // Watchdog1
#define GPIO_PORTA_BASE 0x40004000 // GPIO Port A
#define GPIO_PORTB_BASE 0x40005000 // GPIO Port B
#define GPIO_PORTC_BASE 0x40006000 // GPIO Port C
#define GPIO_PORTD_BASE 0x40007000 // GPIO Port D
#define SSI0_BASE 0x40008000 // SSI0
#define SSI1_BASE 0x40009000 // SSI1
#define UART0_BASE 0x4000C000 // UART0
#define UART1_BASE 0x4000D000 // UART1
#define UART2_BASE 0x4000E000 // UART2
#define I2C0_MASTER_BASE 0x40020000 // I2C0 Master
#define I2C0_SLAVE_BASE 0x40020800 // I2C0 Slave
#define I2C1_MASTER_BASE 0x40021000 // I2C1 Master
#define I2C1_SLAVE_BASE 0x40021800 // I2C1 Slave
#define GPIO_PORTE_BASE 0x40024000 // GPIO Port E
#define GPIO_PORTF_BASE 0x40025000 // GPIO Port F
#define GPIO_PORTG_BASE 0x40026000 // GPIO Port G
#define GPIO_PORTH_BASE 0x40027000 // GPIO Port H
#define PWM_BASE 0x40028000 // PWM
#define QEI0_BASE 0x4002C000 // QEI0
#define QEI1_BASE 0x4002D000 // QEI1
#define TIMER0_BASE 0x40030000 // Timer0
#define TIMER1_BASE 0x40031000 // Timer1
#define TIMER2_BASE 0x40032000 // Timer2
#define TIMER3_BASE 0x40033000 // Timer3
#define ADC0_BASE 0x40038000 // ADC0
#define ADC1_BASE 0x40039000 // ADC1
#define COMP_BASE 0x4003C000 // Analog comparators
#define GPIO_PORTJ_BASE 0x4003D000 // GPIO Port J
#define CAN0_BASE 0x40040000 // CAN0
#define CAN1_BASE 0x40041000 // CAN1
#define CAN2_BASE 0x40042000 // CAN2
#define ETH_BASE 0x40048000 // Ethernet
#define MAC_BASE 0x40048000 // Ethernet
#define USB0_BASE 0x40050000 // USB 0 Controller
#define I2S0_BASE 0x40054000 // I2S0
#define GPIO_PORTA_AHB_BASE 0x40058000 // GPIO Port A (high speed)
#define GPIO_PORTB_AHB_BASE 0x40059000 // GPIO Port B (high speed)
#define GPIO_PORTC_AHB_BASE 0x4005A000 // GPIO Port C (high speed)
#define GPIO_PORTD_AHB_BASE 0x4005B000 // GPIO Port D (high speed)
#define GPIO_PORTE_AHB_BASE 0x4005C000 // GPIO Port E (high speed)
#define GPIO_PORTF_AHB_BASE 0x4005D000 // GPIO Port F (high speed)
#define GPIO_PORTG_AHB_BASE 0x4005E000 // GPIO Port G (high speed)
#define GPIO_PORTH_AHB_BASE 0x4005F000 // GPIO Port H (high speed)
#define GPIO_PORTJ_AHB_BASE 0x40060000 // GPIO Port J (high speed)
#define EPI0_BASE 0x400D0000 // EPI0
#define HIB_BASE 0x400FC000 // Hibernation Module
#define FLASH_CTRL_BASE 0x400FD000 // FLASH Controller
#define SYSCTL_BASE 0x400FE000 // System Control
#define UDMA_BASE 0x400FF000 // uDMA Controller
通常會將 BitBand 與 Bit band alias 的對應關係寫成巨集,使用下列巨集,可以直接找到對應的 bit band alias 位址,並且針對每個位元單獨設定。
#define HWREG(x) \
(*((volatile unsigned long *)(x)))
#define HWREGBITW(x, b) \
HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \
(((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
例如:
The alias word at
0x23FFFFE0
maps to bit [0] of the bit-band byte at 0x200FFFFF
: 0x23FFFFE0
= 0x22000000
+ (0xFFFFF
*32
) + 0
*4
.
BitBand優點便是當需要用到大量的bit運算時(存取周邊裝置),可以直接存取bit-band alias,而不需要自行再對bit作運算,可以減少 code size。
l 一般作法
n 讀取暫存器
n 遮罩不需要的bit
n 取得所需的bit
l Bitband作法
n 讀取暫存器 (位址為 bit-band alias,因此可以直接定位到 bit-band區域內的某個bit)
n 取得所需的bit
除了可以節省 code size ,Bitband還有一個重要的不可分割 (atomic)的特性,可以在硬體層級作保護,藉以確認在一個連續的 Read-Modify-Write 的過程中,不會發生中斷。
參考資料: