赞
踩
参考书籍《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 区。
32MB的 SRAM 别名区的访问映射为对 1MB SRAMbit-band 区的访问。如图
32MB 的外设别名区的访问映射为对 1MB 外设 bit-band 区的访问。如图
把每个比特膨胀或者说映射到一个32位的字,当访问这些字的时候就达到了访问比特的目的,比如说BSRR寄存器有32个位,那么可以映射到32个地址上,直接去访问(读-改-写)这32个地址就达到访问32个比特的目的。
文档这样说
当需要从一个32位寄存器中读/写/改某一个位值的时候,首先需要先将这个32位寄存的值都拿出来,然后根据需要经过偏移、按位或、按位与运算来读/写/改某一位的值。但是当我们使用bit-band操作时候,因为bit-band是将寄存器中某一个位映射或者说膨胀到一个具体地址上(bit-band alias),因此当我们需要读/写/改某一个位时候,就可以直接对bit-band alias地址进行操作,这样就大大提高了程序的执行效率。
通过上图就可以看出当使用bit-band操作方法直接对bit-band alias操作的时候明显比普通的操作执行效率更高,代码量也更少。
当不使用bit-band操作时,也可以使用互斥锁来保证共享资源的安全。
还有一种情况在任务程序中
0x4000_0000‐0x400F_FFFF(片上外设区中的最低 1MB)
用GPIO举例
- /* Peripheral base address in the alias region */
- #define PERIPH_BASE ((uint32_t)0x40000000)
-
- /* Peripheral memory map */
- #define APB1PERIPH_BASE PERIPH_BASE
- #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
- #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
-
- /* gpio memory map */
- #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
- #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
- #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
- #define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
- #define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
- #define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00)
- #define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)
-
- /*Port _OUTput data register Address offset*/
- #define ODR_OFFSET 0x0C
- /*Port input data register*/
- #define IDR_OFFSET 0x08
- /*the starting address of the alias region*/
- #define BIT_BAND_BASE 0x2000000
-
- /*寄存器位带地址映射转换*/
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+BIT_BAND_BASE+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
-
- /* IO口地址映射 */
- #define GPIOA_ODR_Addr (GPIOA_BASE+ODR_OFFSET) //0x4001080C
- #define GPIOB_ODR_Addr (GPIOB_BASE+ODR_OFFSET) //0x40010C0C
- #define GPIOC_ODR_Addr (GPIOC_BASE+ODR_OFFSET) //0x4001100C
- #define GPIOD_ODR_Addr (GPIOD_BASE+ODR_OFFSET) //0x4001140C
- #define GPIOE_ODR_Addr (GPIOE_BASE+ODR_OFFSET) //0x4001180C
- #define GPIOF_ODR_Addr (GPIOF_BASE+ODR_OFFSET) //0x40011A0C
- #define GPIOG_ODR_Addr (GPIOG_BASE+ODR_OFFSET) //0x40011E0C
-
- #define GPIOA_IDR_Addr (GPIOA_BASE+IDR_OFFSET) //0x40010808
- #define GPIOB_IDR_Addr (GPIOB_BASE+IDR_OFFSET) //0x40010C08
- #define GPIOC_IDR_Addr (GPIOC_BASE+IDR_OFFSET) //0x40011008
- #define GPIOD_IDR_Addr (GPIOD_BASE+IDR_OFFSET) //0x40011408
- #define GPIOE_IDR_Addr (GPIOE_BASE+IDR_OFFSET) //0x40011808
- #define GPIOF_IDR_Addr (GPIOF_BASE+IDR_OFFSET) //0x40011A08
- #define GPIOG_IDR_Addr (GPIOG_BASE+IDR_OFFSET) //0x40011E08
-
- /* IO口操作,只对单一的IO口! 确保n的值小于16! */
- #define GPIOA_OUT(bit_num) BIT_ADDR(GPIOA_ODR_Addr,bit_num) //输出
- #define GPIOA_IN(bit_num) BIT_ADDR(GPIOA_IDR_Addr,bit_num) //输入
-
- #define GPIOB_OUT(bit_num) BIT_ADDR(GPIOB_ODR_Addr,bit_num) //输出
- #define GPIOB_IN(bit_num) BIT_ADDR(GPIOB_IDR_Addr,bit_num) //输入
-
- #define GPIOC_OUT(bit_num) BIT_ADDR(GPIOC_ODR_Addr,bit_num) //输出
- #define GPIOC_IN(bit_num) BIT_ADDR(GPIOC_IDR_Addr,bit_num) //输入
-
- #define GPIOD_OUT(bit_num) BIT_ADDR(GPIOD_ODR_Addr,bit_num) //输出
- #define GPIOD_IN(bit_num) BIT_ADDR(GPIOD_IDR_Addr,bit_num) //输入
-
- #define GPIOE_OUT(bit_num) BIT_ADDR(GPIOE_ODR_Addr,bit_num) //输出
- #define GPIOE_IN(bit_num) BIT_ADDR(GPIOE_IDR_Addr,bit_num) //输入
-
- #define GPIOF_OUT(bit_num) BIT_ADDR(GPIOF_ODR_Addr,bit_num) //输出
- #define GPIOF_IN(bit_num) BIT_ADDR(GPIOF_IDR_Addr,bit_num) //输入
-
- #define GPIOG_OUT(bit_num) BIT_ADDR(GPIOG_ODR_Addr,bit_num) //输出
- #define GPIOG_IN(bit_num) BIT_ADDR(GPIOG_IDR_Addr,bit_num) //输入
设置GPIOA的第5位输出高电平
- /* 不使用位带操作 */
- GPIOA->ODR|=1<<5;
-
- /* 使用位带操作 */
- GPIOA_OUT(5) = 1;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。