概念
Cortex-M3的存储器系统支持所谓的“位带”(bit‐band)操作。通过它,实现了对单一比特的原子操作。位带操作仅适用于一些特殊的存储器区域中.
支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。在CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低1MB范围。
从上图得知,支持位带操作的两个内存区的范围是:
● 0x2000_0000‐0x200F_FFFF(SRAM 区中的最低 1MB;
● 0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)。
这两个区中的地址除了可以像普通的RAM一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。
从上图看出位带操作将0x20000000地址内的8bit数据映射到了0x22000000-0x2200001C区间内,操作0x22000000-0x2200001C区间的数据,相当于操作了0x20000000地址内的8bit数据。
映射计算公式
对 SRAM 位带区的某个比特,记它所在字节地址为 A,位序号在别名区的地址为:
对于片上外设位带区的某个比特记它所在字节地址为 A,位序号在别名区的地址为:
对上面公式进行总结为一个公式:
STM32单片机应用
//IO操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) //地址计算
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) //转化为单片机能识别的地址
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //简化
//端口A IO地址定义
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输入
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输出
参考资料
Cortex-M3内核权威指南