当前位置:   article > 正文

STM32 位带操作 Bit-band operation详解_arm的bitband

arm的bitband

1.STM32位带区和位带别名区

参考书籍《The Defi nitive Guide to the ARM Cortex-M3》

Bit-band operation support allows a single load/store operation to access (read/write) to a single data bit. In the Cortex-M3, this is supported in two predefi ned memory regions called bit-band regions. One of them is located in the fi rst 1 MB of the SRAM region, and the other is located in the fi rst 1 MB of the peripheral region.

处理器存储器映射包括两个 bit-banding 区域。它们分别为 SRAM 和外设存储区域中的最低的 1MB。这些 bit-band 区域将存储器别名区的一个字映射为 bit-band 区的一个位。Cortex-M3 存储器映射有 2 个 32MB 别名区,它们被映射为两个 1MB 的 bit-band 区。

2.STM32内存图

32MB的 SRAM 别名区的访问映射为对 1MB SRAMbit-band 区的访问。如图

32MB 的外设别名区的访问映射为对 1MB 外设 bit-band 区的访问。如图

3.Bit-band原理

把每个比特膨胀或者说映射到一个32位的字,当访问这些字的时候就达到了访问比特的目的,比如说BSRR寄存器有32个位,那么可以映射到32个地址上,直接去访问(读-改-写)这32个地址就达到访问32个比特的目的。

4.优点1-操作简单:

文档这样说

当我们读一个寄存器中的某一个位值的时候如下操作。

 

汇编语言程序:

当我们写一个寄存器中的某一个位值的时候如下操作。

 

汇编语言程序

当需要从一个32位寄存器中读/写/改某一个位值的时候,首先需要先将这个32位寄存的值都拿出来,然后根据需要经过偏移、按位或、按位与运算来读/写/改某一位的值。但是当我们使用bit-band操作时候,因为bit-band是将寄存器中某一个位映射或者说膨胀到一个具体地址上(bit-band alias),因此当我们需要读/写/改某一个位时候,就可以直接对bit-band alias地址进行操作,这样就大大提高了程序的执行效率。

通过上图就可以看出当使用bit-band操作方法直接对bit-band alias操作的时候明显比普通的操作执行效率更高,代码量也更少。

5.优点2-多任务中实现共享资源的互斥访问

当不使用bit-band操作时,也可以使用互斥锁来保证共享资源的安全。

 

 

 

 

还有一种情况在任务程序中

 

6.实际应用

0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)

用GPIO举例

 

6.1转换成实际应用代码

  1. /* Peripheral base address in the alias region */
  2. #define PERIPH_BASE ((uint32_t)0x40000000)
  3. /* Peripheral memory map */
  4. #define APB1PERIPH_BASE PERIPH_BASE
  5. #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
  6. #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
  7. /* gpio memory map */
  8. #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
  9. #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
  10. #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
  11. #define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
  12. #define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
  13. #define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00)
  14. #define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)
  15. /*Port _OUTput data register Address offset*/
  16. #define ODR_OFFSET 0x0C
  17. /*Port input data register*/
  18. #define IDR_OFFSET 0x08
  19. /*the starting address of the alias region*/
  20. #define BIT_BAND_BASE 0x2000000
  21. /*寄存器位带地址映射转换*/
  22. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+BIT_BAND_BASE+((addr &0xFFFFF)<<5)+(bitnum<<2))
  23. #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
  24. #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
  25. /* IO口地址映射 */
  26. #define GPIOA_ODR_Addr (GPIOA_BASE+ODR_OFFSET) //0x4001080C
  27. #define GPIOB_ODR_Addr (GPIOB_BASE+ODR_OFFSET) //0x40010C0C
  28. #define GPIOC_ODR_Addr (GPIOC_BASE+ODR_OFFSET) //0x4001100C
  29. #define GPIOD_ODR_Addr (GPIOD_BASE+ODR_OFFSET) //0x4001140C
  30. #define GPIOE_ODR_Addr (GPIOE_BASE+ODR_OFFSET) //0x4001180C
  31. #define GPIOF_ODR_Addr (GPIOF_BASE+ODR_OFFSET) //0x40011A0C
  32. #define GPIOG_ODR_Addr (GPIOG_BASE+ODR_OFFSET) //0x40011E0C
  33. #define GPIOA_IDR_Addr (GPIOA_BASE+IDR_OFFSET) //0x40010808
  34. #define GPIOB_IDR_Addr (GPIOB_BASE+IDR_OFFSET) //0x40010C08
  35. #define GPIOC_IDR_Addr (GPIOC_BASE+IDR_OFFSET) //0x40011008
  36. #define GPIOD_IDR_Addr (GPIOD_BASE+IDR_OFFSET) //0x40011408
  37. #define GPIOE_IDR_Addr (GPIOE_BASE+IDR_OFFSET) //0x40011808
  38. #define GPIOF_IDR_Addr (GPIOF_BASE+IDR_OFFSET) //0x40011A08
  39. #define GPIOG_IDR_Addr (GPIOG_BASE+IDR_OFFSET) //0x40011E08
  40. /* IO口操作,只对单一的IO口! 确保n的值小于16! */
  41. #define GPIOA_OUT(bit_num) BIT_ADDR(GPIOA_ODR_Addr,bit_num) //输出
  42. #define GPIOA_IN(bit_num) BIT_ADDR(GPIOA_IDR_Addr,bit_num) //输入
  43. #define GPIOB_OUT(bit_num) BIT_ADDR(GPIOB_ODR_Addr,bit_num) //输出
  44. #define GPIOB_IN(bit_num) BIT_ADDR(GPIOB_IDR_Addr,bit_num) //输入
  45. #define GPIOC_OUT(bit_num) BIT_ADDR(GPIOC_ODR_Addr,bit_num) //输出
  46. #define GPIOC_IN(bit_num) BIT_ADDR(GPIOC_IDR_Addr,bit_num) //输入
  47. #define GPIOD_OUT(bit_num) BIT_ADDR(GPIOD_ODR_Addr,bit_num) //输出
  48. #define GPIOD_IN(bit_num) BIT_ADDR(GPIOD_IDR_Addr,bit_num) //输入
  49. #define GPIOE_OUT(bit_num) BIT_ADDR(GPIOE_ODR_Addr,bit_num) //输出
  50. #define GPIOE_IN(bit_num) BIT_ADDR(GPIOE_IDR_Addr,bit_num) //输入
  51. #define GPIOF_OUT(bit_num) BIT_ADDR(GPIOF_ODR_Addr,bit_num) //输出
  52. #define GPIOF_IN(bit_num) BIT_ADDR(GPIOF_IDR_Addr,bit_num) //输入
  53. #define GPIOG_OUT(bit_num) BIT_ADDR(GPIOG_ODR_Addr,bit_num) //输出
  54. #define GPIOG_IN(bit_num) BIT_ADDR(GPIOG_IDR_Addr,bit_num) //输入

7.使用

设置GPIOA的第5位输出高电平

  1. /* 不使用位带操作 */
  2. GPIOA->ODR|=1<<5;
  3. /* 使用位带操作 */
  4. GPIOA_OUT(5) = 1;

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/219806
推荐阅读
相关标签
  

闽ICP备14008679号