在uC-CPU/ARM-Cortex-M3/cpu_c.c中有两个位带访问的函数
//使用位带访问技术来对内存或外设地址addr中的第bit_nbr位进行清零操作
void CPU_BitBandClr (CPU_ADDR addr,CPU_INT08U bit_nbr)
{
// CPU_ADDR 为16位CPU_ADDR bit_word_off;CPU_ADDR bit_word_addr;// 地址范围的判断if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&(addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
/*CPU_BIT_BAND_SRAM_BASE + ((addr‐CPU_BIT_BAND_SRAM_REG_LO)*8+bit_nbr)*4 =0x22000000 + (addr‐0x20000000)*32 + bit_nbr*4*/bit_word_off = ((addr - CPU_BIT_BAND_SRAM_REG_LO) * 32) + (bit_nbr * 4);bit_word_addr = CPU_BIT_BAND_SRAM_BASE + bit_word_off;*(volatile CPU_INT32U *)(bit_word_addr) = 0;} else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&(addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
bit_word_off = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;*(volatile CPU_INT32U *)(bit_word_addr) = 0;}
}
//使用位带访问技术来对内存或外设地址addr中的第bit_nbr位进行置1操作
void CPU_BitBandSet (CPU_ADDR addr,CPU_INT08U bit_nbr)
{
CPU_ADDR bit_word_off;CPU_ADDR bit_word_addr;if ((addr >= CPU_BIT_BAND_SRAM_REG_LO) &&(addr <= CPU_BIT_BAND_SRAM_REG_HI)) {
bit_word_off = ((addr - CPU_BIT_BAND_SRAM_REG_LO) * 32) + (bit_nbr * 4);bit_word_addr = CPU_BIT_BAND_SRAM_BASE + bit_word_off;*(volatile CPU_INT32U *)(bit_word_addr) = 1;} else if ((addr >= CPU_BIT_BAND_PERIPH_REG_LO) &&(addr <= CPU_BIT_BAND_PERIPH_REG_HI)) {
bit_word_off = ((addr - CPU_BIT_BAND_PERIPH_REG_LO) * 32) + (bit_nbr * 4);bit_word_addr = CPU_BIT_BAND_PERIPH_BASE + bit_word_off;*(volatile CPU_INT32U *)(bit_word_addr) = 1;}
}
什么是位带访问技术:
它的对象可以是SRAM、I/O和外设空间。要实现对这些地方的某一位的操作。
它是这样做:*在寻址空间(32位对应的地址空间为 4GB)的另一地方,取个别名区空间,从这个地址开始处,每一个字(32BIT)对应SRAM或I/O的一位。
1MB SRAM 就可以有 32MB 的对应别名区空间,就是1位膨胀到32位(1 BIT 变为1个字节)。我们对这个别名区空间内的某一字操作(置0或置1),就等于它映射的 SRAM 或 I/O 相应的某地址的某一位的操作。
位带访问的好处
1、代码缩小、速度更快、效率更高、更安全。
2、一般操作是读-改-写,而位带别名区只有写的操作,防止了中断对读改写方式的影响。
应用
支持了位带操作(bit_band),位带别名区把每个比特膨胀成一个 32 位的字。 每个比特膨胀成一个32 位的字,就是把 1M 扩展为 32M 。位于 RAM 地址 0X200000000 的一个字节扩展为8个32位的字,扩展后每位相对应的的地址是:0X220000000,0X220000004,0X220000008。
支持位带操作的两个内存区的范围是:
0x2000 0000‐0x200F FFFF(SRAM 区中的最低1MB)
0x4000 0000‐0x400F FFFF(片上外设区中的最低1MB)
对 SRAM 位带区的某个比特,记该比特所在字节的地址为A,位序号为 n (0<=n<=7),则它在别名区的地址为:
AliasAddr = 0x22000000 + ((A‐0x20000000)*8+n)*4 =0x22000000 + (A‐0x20000000)*32 + n*4
(“*4”表示一个字为 4 个字节,“*8”表示一个字节中有 8 个比特。)
使用地址宏:
#define BITBAND(addr, bitnum) ((addr &0xF0000000)+0x2000000 + ((addr & 0xFFFFF)<<5) + (bitnum<<2))
使用指针的方式
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
MEM_ADDR(BITBAND((U32)&CRCValue, 1)) = 0x1
函数中的应用
bit_word_off = ((addr - CPU_BIT_BAND_SRAM_REG_LO) * 32) + (bit_nbr * 4);
bit_word_addr = CPU_BIT_BAND_SRAM_BASE + bit_word_off;
*(volatile CPU_INT32U *)(bit_word_addr) = 1;
映射公式:
bit_word_offset = (byte_offset x 32) + (bit_number × 4)
bit_word_addr = bit_band_base + bit_word_offset
其中:
bit_word_offset是目标位在存取器位段区中的位置
bit_word_addr 是别名存储器区中字的地址,它映射到某个目标位。
bit_band_base 是别名区的起始地址。
byte_offset 是包含目标位的字节在位段中的序号
bit_number 是目标位所在位置(0-31)
参考博客:
http://blog.sina.com.cn/s/blog_9f27507501011gg1.html
在此感谢。