Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1323723
  • 博文数量: 168
  • 博客积分: 2124
  • 博客等级: 大尉
  • 技术积分: 2590
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-16 23:51
文章分类

全部博文(168)

文章存档

2014年(6)

2013年(74)

2012年(71)

2011年(17)

分类: 嵌入式

2012-02-13 14:55:26

 

 

 

 

 

CM3的存储器系统支持所谓的“位带”(bit-band)操作。通过它,实现了对单一比特

的原子操作。位带操作仅适用于一些特殊的存储器区域中。

 

位带区与位带别名区的膨胀关系图

 

 

 

 

 

 

在位带区中,每个比特都映射到别名地址区的一个字——这是个只有 LSB才有效的字。

 

支持位带操作的两个内存区的范围是:

0x2000_0000-0x200F_FFFFSRAM区中的最低 1MB

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

 

例子:

1.  在地址 0x20000000处写入 0x3355AACC

2.  读取地址 0x22000008。本次读访问将读取 0x20000000,并提取比特 2,值为1

3.  往地址 0x22000008 处写 0。本次操作将被映射成对地址 0x20000000 的“读-改-写”操作

(原子的),把比特 20

4.  现在再读取 0x20000000,将返回 0x3355AAC8bit[2]已清零)。

位带别名区的字只有 LSB 有意义。另外,在访问位带别名区时,不管使用哪一种长度的数据传

送指令(字/半字/字节),都把地址对齐到字的边界上,否则会产生不可预料的结果。

 

 

位带操作的优越性

 

1.      位带操作对于硬件 I/O密集型的底层程序最有用处了

 

 

2.位带操作还能用来化简跳转的判断。当跳转依据是某个位时,以前必须这样做:

  读取整个寄存器

  掩蔽不需要的位

  比较并跳转

  现在只需:

从位带别名区读取状态位

      比较并跳转

 

3.位带操作还有一个重要的好处是在多任务中,用于实现共享资源在任务间的“互锁”访问。多任务的共享资源必须满足一次只有一个任务访问它——亦即所谓的“原子操作”。以前的读-改-写需要 3 条指令,导致这中间留有两个能被中断的空当。于是可能会出现如下图所示的紊乱危象:

 

 

同样的紊乱危象可以出现在多任务的执行环境中。其实,图 5.8所演示的情况可以看作是多任

务的一个特例:主程序是一个任务,ISR是另一个任务,这两个任务并发执行。

通过使用 CM3的位带操作,就可以消灭上例中的紊乱危象。CM3把这个“读-改-写”做成一

个硬件级别支持的原子操作,不能被中断,如图 5.9所演示

 

 

5.5.2    其它数据长度上的位带操作

 

 

  位带操作并不只限于以字为单位的传送。亦可以按半字和字节为单位传送。例如,可以使用

LDRB/STRB来以字节为长度单位去访问位带别名区,同理可用于 LDRH/STRH。但是不管用哪一个对

子,都必须保证目标地址对齐到字的边界上。

 

 

5.5.3    C语言中使用位带操作

 

 

 为简化位带操作,也可以定义一些宏。比如,我们可以建立一个把“位带地址+位序号”转换成别名地址的宏,再建立一个把别名地址转换成指针类型的宏:

 

//把“位带地址+位序号”转换成别名地址的宏

#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x20000000 + ((addr & 0xFFFFF) << 5) + (bit<<2));

 

//把该地址转换成一个指针

#define MEM_ADDR(addr) *((volatile unsigned long *) (adr));

 

在此基础上,我们就可以如下改写代码:

MEM_ADDR(DEVICE REG0) = 0xAB; //使用正常地址访问寄存器,即把0xAB作为DEVICE REG0地址上的值

MEM_ADDR(DEVICE_REG0) = MEM_ADDR(DEVICE_REG0) | 0x2; //传统做法

MEM_ADDR(BITBAND(DEVICE_REG0 1)) = 0x1 //使用位带别名地址

 

请注意:当使用位带功能时,要访问的变量必须用 volatile来定义。因为 C编译器并不知道同一个比特可以有两个地址。所以就要通过 volatile使得编译器每次都如实地把新数值写入存储器,而不再会出于优化的考虑,在中途使用寄存器来操作数据的复本,直到最后才把复本写回——这会导致按不同的方式访问同一个位会得到不一致的结果(可能被优化到不同的寄存器来保存中间结果——译注)

 

 

参考资料:《《Cortex-M3权威指南》》

阅读(12012) | 评论(1) | 转发(1) |
0

上一篇:名词积累

下一篇:stm32f10x_bkp.c 注释

给主人留下些什么吧!~~

reallsc2015-10-19 16:39:57

既然支持“其它数据长度上的位带操作”,为什么1 bit要扩展为32bit呢?
扩展为8bit不久够了吗?32bit读写比8bit读写更快吗?