---------------------------------------------
-- 时间:2019-01-17
-- 创建人:Ruo_Xiao
-- 邮箱:xclsoftware@163.com
---------------------------------------------
一、源代码
#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))
二、功能
已知SRAM区或者Peripheral区的位带区某一位的地址,计算该位对应的位带别名区的地址,即:1b转到32b。
三、解释
上述代码主要理解的是第1行。第1行代码可以分解成以下几部分:
(1)addr & 0xF000_0000
因为位带功能只存在于SRAM区和Peripheral区,二者的位带区的地址范围如下:
SRAM区:0x2000_0000
Peripheral区:0x4000_0000
该代码的意思是获知当前位带区是位于SRAM区和Peripheral区。
(2)(addr & 0xF000_0000) + 0x200_0000
SRAM区和Peripheral区的位带别名区的首地址分别是0x2200_0000和0x4200_0000,所以这行代码的功能是计算所在区的位带别名区的首地址。
(3)(addr &0xFFFFF)<<5)+(bitnum<<2)
因为SRAM区和Peripheral区的位带区的大小为1M,故该区里面的位的地址最大为0xF_FFFF,所以addr &0xF_FFFF的功能是获取位带区中的位相对于位带区首地址的偏移。
为了便于理解,这里将(addr &0xFFFFF)<<5)+(bitnum<<2)拆解成((addr & 0xFFFFF)<<3 + bitnum)<<2。
① (addr & 0xFFFFF)<<3
将位带区的位转换成字节形式。“<<3”意思就是乘以8。
② (addr & 0xFFFFF)<<3 + bitnum
加上bitnum,转到指定的位。
③ ((addr & 0xFFFFF)<<3 + bitnum)<<2
乘以4,再将位带区的位转到了32位的字中。
经过上述操作,就完成了计算位带区的位对应的位带别名区位的地址的操作。
参考:
https://www.cnblogs.com/szhb-5251/p/6662417.html
https://blog.csdn.net/bgk083/article/details/40082103
(SAW:Game Over!)