1.位带操作定义

        STM32的存储器映射中的内存区域和外设区域有一段地址空间(都是最低1MB)是位带区域,跟这个区域相对应的有一段位带别名区域,位带别名区的大小是位带区的32倍,位带别名区的每一个地址都对应位带区域的一个位,如位带别名区的0x42000000~0x42000007代表的是位带区的0x40000000的0-7位,给0x42000000赋值就相当于给0x40000000的最低位赋值。

2.位带操作的范围:内存和外设的最低1MB,对于内存小于1MB的MCU来说整个内存空间都是可以进行位带操作的;外设的话只要外设寄存器的地址没有超出1MB的范围(0x40100000)都是可以进行位带操作的,如GPIO寄存器,事实上绝大部分的外设寄存器都落在这个区域。

3.如何计算一个位带地址对应的位带别名地址(如一个内存地址中的某一个位的位带别名地址)

CM4比CM3多了一个VFP cm3和cm4的区别_宏定义

 在C中使用位带操作:配合宏定义

#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)) 

当然由于这个宏定义表达式比较复杂,涉及很多次逻辑运算和算术运算(宏定义在编译的时候只是进行简单的替换,并不计算),所以这样用的话无法完全体现出位操作对程序执行效率的提升,因此如果追求极致速率的话那就直接把需要位操作的地址的位带别名地址计算好再用宏定义定义起来,这样使用的时候就直接对该宏定义赋值或取值就行。(后面自己实际试了下好像不是这样,两者的执行时间是一样的,就好像宏定义并不是只是简单的替换,还把所有运算都算完了一样,但是网上说宏定义的确只是执行简单替换操作,搞不懂)。

4.位带操作的优越性/好处

        1.位带操作执行效率更高,无论是位带写还是读,编译到汇编指令时,位带操作对于直接操作寄存器都会少一个指令:

CM4比CM3多了一个VFP cm3和cm4的区别_寄存器_02

CM4比CM3多了一个VFP cm3和cm4的区别_stm32_03

        2.可以把一系列bool型变量封装到一个整形变量里去,然后还像操作内存地址一样读写某个bool值

        3.这点是最重要的,位带操作的读写动作是硬件级别支持的原子操作,不能被打断;常规的写某个寄存器或者内存的值都有“读-改-写”三个步骤,在这之间是可以被打断的,有的时候就会因为这个打断而导致数据异常从而导致程序异常,如下图:

CM4比CM3多了一个VFP cm3和cm4的区别_stm32_04

 因此,在程序中对于一些关键变量的读写操作最好使用位带操作。

4.使用注意事项:当你使用位带功能时,要访问的变量必须用 volatile 来修饰,因为 C 编译器并不知道同一个比特可以有两个地址。所以就要通过 volatile,使得编译器每次都如实地把新数值写入存储器,而不再会出于优化的 虑 在中途使用寄存器来操作数据的复本,直到最后才把复本写会(这和cache的原理是一样的)

5.使用

        1.使用位带操作读写变量:

CM4比CM3多了一个VFP cm3和cm4的区别_宏定义_05

        2.使用位带操作整合bool变量

CM4比CM3多了一个VFP cm3和cm4的区别_CM4比CM3多了一个VFP_06

         3.位带操作和常规操作速度对比