【嵌入式系统】位带操作原理详解+LED实验解读

简介: 【嵌入式系统】位带操作原理详解+LED实验解读

【嵌入式系统】位带操作原理详解+LED实验解读

1、位带操作的实质

位带操作实质上就是为了让STM32拥有原子性位操作的能力,可以显著提高位操作的效率和安全性,对许多底层软件开发特别是操作系统和驱动程序具有重要意义。CM3提供了2个位带区(Bit Band Region)以及对应的位带别名区(Bit Band Alias),位带别名区将位带区的每一个bit扩展为四字节32bits(即一个字),所以位带别名区占用空间是位带区的32倍。于是位带区的bit与位带别名区的一个“寄存器”相对应,修改此“寄存器”就相当于修改了对应的bit。值得注意的是,位带别名区的每个“寄存器”仅LSB有效


image.png

图1给出了SRAM区位带操作的例子:位带区0x2000 0000的第一个bit与位带别名区以0x2200 0000为首地址的“寄存器”相映射,于是修改“寄存器”的LSB,例如置1,那么相应位带区的bit也被置位。更进一步,设位带区地址0x20000000处的字为0x3355 AACC,要求对bit2置0:


①读取位带别名区0x2200 0008

②往位带别名区0x2200 0008处写0,本次操作将被映射成对地址0x2000 0000的“读-改-写” 操作(原子操作),把bit2置0

③现在再读取0x2000 0000,将返回0x3355 AAC8(bit[2]已置0)


上述具体的过程就体现了原子位操作。对原子性的理解要从汇编语言层次入手:


image.png

左侧没有位带操作的四条汇编指令中都有间隔,都可被打断。假设在左侧任一箭头处被打断进入服务函数修改R0,中断返回后继续执行,然而中断返回后的指令也在修改R0,这可能导致ISR修改的数据又被篡改;而右侧位带操作即实现了原子操作,将位操作封装成一个整体。中断只能在位操作前后打入,这保证了变量安全被使用,不会因为是共享资源而被各线程强占

2、位带操作的地址映射关系

位带别名区与位带区的映射公式:

A l i a s A d d r = A l i a s B a s e + ( ( B i t A d d r − B i t B a s e ) × 8 + n ) × 4 AliasAddr=AliasBase+((BitAddr-BitBase)×8+n) ×4

AliasAddr=AliasBase+((BitAddr−BitBase)×8+n)×4


其中 ( ( B i t A d d r − B i t B a s e ) × 8 + n ) × 4 ((BitAddr-BitBase)×8+n) ×4 ((BitAddr−BitBase)×8+n)×4为膨胀幅度,因为每一个bit要扩展成位带别名区的一个字。 B i t B a s e BitBase BitBase与 A l i a s B a s e AliasBase AliasBase均为常数。 n n n为 B i t A d d r BitAddr BitAddr处的第 n n n个bit


例如位带区0x200F FFFF的bit7,映射到位带别名区就是首地址为如下计算所得 A l i a s A d d r AliasAddr AliasAddr的一个字

A l i a s A d d r AliasAddr AliasAddr =0x2200 0000+((0x200F FFFF-0x2000 0000)×8+7)×4=0x23FF FFFC


image.png

3、LED实验中的位带操作

int main(void)
{ 
    HAL_Init();                       //初始化HAL库    
    Stm32_Clock_Init(RCC_PLL_MUL9);     //设置时钟,72M
  delay_init(72);                     //初始化延时函数
  LED_Init();             //初始化LED  
  while(1)
  {
         LED0=0;            //LED0亮
       LED1=1;          //LED1灭
     delay_ms(500);
     LED0=1;          //LED0灭
     LED1=0;          //LED1亮
     delay_ms(500);
   }
}

主程序代码如上。可见的是LED0=0这行代码直接就使LED0亮灯,在没有引入位带操作时,STM32系列单片机是没有这种位操作的。因此这里的位操作是对位带操作的一种封装,使代码简化,可读性增强。

在led.h中,LED0被定义为:

#define LED0 PCout(0)     //LED0

在sys.h中,PCout被定义为:

#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))
#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出

其中(addr & 0xF0000000)+0x2000000即为 A l i a s B a s e AliasBase AliasBase,addr &0xFFFFF即为(BitAddr-BitBase),用与操作的目的是增强代码的适用性,因为CM3有两个位带区,用与操作使两个位带区都适用此公式。BITBAND(addr, bitnum)实质上就是将位带区addr的bit[bitnum]映射到位带别名区,再通过MEM_ADDR(addr)转为volatile型的地址,位带操作时volatile的修饰是必要的,因为I/O设备经常涉及硬件设备更新,从寄存器读数据可能不会得到预料结果。GPIOC_ODR_Addr是寄存器映射地址,其第n位即为PCn,也就对应LEDn的状态。


综上所述,LED通过对位带操作的封装,实现了对GPIO设备的原子性位操作。


目录
相关文章
第二章:单片机硬件结构
第二章:单片机硬件结构
102 0
|
芯片
GPIO实验【嵌入式系统】
GPIO实验【嵌入式系统】
105 0
|
异构计算
实验四 基于FPGA的数字电子钟设计(1) 基本功能的实现 quartus电路图演示
实验四 基于FPGA的数字电子钟设计(1) 基本功能的实现 quartus电路图演示
951 0
实验四 基于FPGA的数字电子钟设计(1) 基本功能的实现 quartus电路图演示
|
C语言 Python Windows
MicroPython 玩转硬件系列2:点灯实验
MicroPython 玩转硬件系列2:点灯实验
第五章:单片机控制
第五章:单片机控制
75 0
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第九章:多功能运算电路
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第九章:多功能运算电路
203 0
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第九章:多功能运算电路
复习单片机:串口通信(内含:1.代码部分+2.串口内部结构+3.串口控制寄存器 SCON+4.电源控制寄存器 PCON+5. 串口的使用方法+6.硬件设计+7.实验现象)
复习单片机:串口通信(内含:1.代码部分+2.串口内部结构+3.串口控制寄存器 SCON+4.电源控制寄存器 PCON+5. 串口的使用方法+6.硬件设计+7.实验现象)
363 1
复习单片机:串口通信(内含:1.代码部分+2.串口内部结构+3.串口控制寄存器 SCON+4.电源控制寄存器 PCON+5. 串口的使用方法+6.硬件设计+7.实验现象)
|
JavaScript IDE 物联网
鸿蒙系统控制LED的实现方法之经典
鸿蒙系统控制LED的实现方法之经典
225 0
鸿蒙系统控制LED的实现方法之经典
|
Perl
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第四章:七段译码器
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第四章:七段译码器
159 0
|
存储 编译器 异构计算
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第十二章:存储器
基于Verilog HDL与虚拟实验平台的计算机组成与CPU实验第十二章:存储器
210 0