9-位带区-别名区功能与用法详解

位带区与别名区介绍

位带区与别名区组合使用形成了位带操作,首先对为什么要引进位带操作进行简介。

1.位带操作的意义

​ 在MCU编程中,通常情况下,对RAM1及外设寄存器的操作,只能对整个字执行“读-改-写”操作,而只对字中某位的操作则需要位带操作的支持。

2.位带操作概述

​ 位带操作实质是一种内存映射关系,系统将“位带区”的存储单元按“位”映射到对应的“别名区”的32位字上,“别名区”中的一个32位地址,对应“位带区”一个地址中的一个位。按“字”访问“别名区”的存储单元时,就相当于访问“位带区”对应“位”,即通过对“别名区”地址的访问等同于对真实地址的某个位的访问。

3.位带操作应用案例解析

以SRAM1中目标地址为0x2000_0300,修改其第二位为“0”为例:一般情况下,修改内存中的一位不影响其他位。

​ ①不使用位带操作方法

​ 需要对待修改的字执行“读-改-写”操作,即读内存赋给临时变量,然后对临时变量进行修改,最后将临时变量结果写回内存。具体方法如下:

1
2
3
4
5
6
7
8
9
10
11
int main()
{
//读一个字:读取0x20000300~0x20000303中内容到临时变量temp中
temp = (*(volatile unsigned long int*)(unsigned long int)0x20000300)

//改一个位:将temp中的第2位清0(从左向右为31--0)
temp = temp & 0xFFFFFFFB

//写一个字:将temp写回目标地址
(*(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;
//"别名区"的地址0x20006008通过公式 0x22000000 + ((0x20000300 - 0x20000000) * 32) + (2 * 4)
//3*32 = 96 96/16 = 6 --> 0x20000300对应 0x22006000,再加上2位偏移地址即成为0x22006008
}
地址 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.