位带区与别名区介绍
位带区与别名区组合使用形成了位带操作,首先对为什么要引进位带操作进行简介。
1.位带操作的意义
在MCU编程中,通常情况下,对RAM1及外设寄存器的操作,只能对整个字执行“读-改-写”操作,而只对字中某位的操作则需要位带操作的支持。
2.位带操作概述
位带操作实质是一种内存映射关系,系统将“位带区”的存储单元按“位”映射到对应的“别名区”的32位字上,“别名区”中的一个32位地址,对应“位带区”一个地址中的一个位。按“字”访问“别名区”的存储单元时,就相当于访问“位带区”对应“位”,即通过对“别名区”地址的访问等同于对真实地址的某个位的访问。
3.位带操作应用案例解析
以SRAM1中目标地址为0x2000_0300,修改其第二位为“0”为例:一般情况下,修改内存中的一位不影响其他位。
①不使用位带操作方法
需要对待修改的字执行“读-改-写”操作,即读内存赋给临时变量,然后对临时变量进行修改,最后将临时变量结果写回内存。具体方法如下:
1 2 3 4 5 6 7 8 9 10 11
| int main() { temp = (*(volatile unsigned long int*)(unsigned long int)0x20000300) temp = temp & 0xFFFFFFFB (*(volatile unsigned long int*)(unsigned long int)0x20000300) = temp; }
|
在AHL-GEC-IDE中对上述代码反汇编进行对比,可以发现使用位带操作比原有“读-改-写”方法的代码空间要小,执行效率更高。通过“别名区”的写操作就可以实现对SRAM1中位的操作,将位操作的“读-改-写”过程就变为了只有“写”的操作,提高了程序的运行效率。
一般情况下,“位带区”中修改一位的机器码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| __main: //"位带区"读一个字 temp = (*(volatile unsigned long int*)(unsigned long int)0x20000300); 800e5d4: 4b0a ldr r3,[pc,#40] 800e5d6: 681b ldr r3,[r3,#0] 800e5d8: 607b str r3,[r7,#4] //改一个位 temp = temp & 0xFFFFFFFB; 800e5e2: 4a07 800e5e4: 687b 800e5e6: 6013 //位带区写一个字 (*(volatile unsigned long int*)(unsigned long int)0x20000300) = temp; 800e5e2: 4a07 800e5e4: 687b 800e5e6: 6013
|
②使用位带操作方法
如果使用位带操作将“位带区”地址为0x2000_0300的内存单元第2位变成“0”。仅需一步写操作就可以实现。
1 2 3 4 5 6
| int main() { (*(volatile unsigned long int*)(unsigned long int)0x22006008) = 0; }
|
地址 |
bit7 |
bit6 |
bit5 |
bit4 |
bit3 |
bit2 |
bit1 |
bit0 |
0x20000300 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0x20000301 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
0/1 |
Tips:每个地址包含了8个bit位,在无符号整数中,0x20000300地址中存放的数是从0到255,在有符号整数中,0x20000300地址中存放的数是从-128到127,也就是一个byte位,short占据两个地址(byte),所以在无符号整数中可以表示0-65535,有符号整数中可以表示-32768到32767,int占据四个地址(byte),所以在无符号整数中可以表示0-4294967296,在有符号整数中可以表示-2147483648-2147483647。
在位带操作下,0x20000300中被映射到一个32个地址,这个地址下的每一个比特位都对应别名区的4个地址,0x20000300的bit0被映射成了0x20006000,bit1被映射成了0x20006004,bit2被映射成了0x20006008,bit3被映射成了0x2000600C,bit4被映射成了0x20006010,bit5被映射成了0x20006014,bit6被映射成了0x20006018,bit7被映射成了0x2000601C,0x20000301的bit0被映射成了0x20000620,以此类推。。。。。。
从上面的特性可以知道,位带区的一个字节会被映射称32个地址,即1位映射为4个地址(32位),那么一个48K的”位带区“就需要一个32×48K的”别名区“进行位带操作,一个1MB的”位带区“就需要一个32×1MB的”别名区“进行位带操作。
4.