蓝牙BLE基础:CC2541 BLE临界资源保护


1 临界区代码保护示例:

      
      HAL_ENTER_CRITICAL_SECTION(intState);    // 进入临界区
 
      events = activeTask->events;
      activeTask->events = 0;                  // 清除任务的事件
 
      HAL_EXIT_CRITICAL_SECTION(intState);     // 退出临界区
 

2 相关宏定义如下:


#define st(x)      do { x } while (__LINE__ == -1)


   注:

1)   __LINE__ 是个宏,它代表当前代码在源文件的行号,它是大于0的,所以__LINE__ == -1 等同于0, 上述宏等价于: 

#define st(x)      do { x } while (0)     // 表示执行x指令,注意x是一个完整的语句,需要加分号

2) do {} while (0)通常用于宏中, 为的是避免如下情况: 


#define st(x) x 


那么我们在调用 if (0) st(a = b; b = c;) 时会被解释成 

if(0) 
a = b; 
b = c; 

此时 if 只对a = b;起作用

#define HAL_ENABLE_INTERRUPTS()         st( EA = 1; )  // 使能总中断
#define HAL_DISABLE_INTERRUPTS()        st( EA = 0; )  // 失能总中断
#define HAL_INTERRUPTS_ARE_ENABLED()    (EA)

typedef unsigned char halIntState_t;

#define HAL_ENTER_CRITICAL_SECTION(x)   st( x = EA;  HAL_DISABLE_INTERRUPTS(); )
#define HAL_EXIT_CRITICAL_SECTION(x)    st( EA = x; )
#define HAL_CRITICAL_STATEMENT(x)       st( halIntState_t  s; HAL_ENTER_CRITICAL_SECTION(s);  x;  HAL_EXIT_CRITICAL_SECTION(s); )

1) cc2541芯片中的中断使能的特殊功能寄存器(SFRs): IEN0、IEN1和IEN2

这三个寄存器的不同的位控制了不同的硬件的中断使能,比如IEN2中的第五位WDTIE控制着看门狗时钟的中断使能

其中有一个比较特殊的位是IEN0的第7位,名称为EA,控制着所有中断的使能,为0时将没有中断相应,为1时每一个中断源的使能受相应的位的控制

上面的宏即是用芯片的EA=0来关中断实现临界资源的保护

2) HAL_ENABLE_INTERRUPTS()和HAL_DISABLE_INTERRUPTS()这两个宏分别实现了cc2541的所有中断的开和关

HAL_ENTER_CRITICAL_SECTION(x)宏首先将EA的值保存在变量x中,然后关闭所有中断,进行后面的临界资源处理

HAL_EXIT_CRITICAL_SECTION(x)宏则是恢复刚才保存在x中的EA的值

HAL_CRITICAL_STATEMENT(x)宏的功能是将x作为临界代码执行,首先声明了用于保存EA值的变量,然后调用进入临界区宏,执行临界代码x,最后执行退出临

界区的宏

3) HAL_CRITICAL_STATEMENT(x)这个宏,因为st宏的实现中x是一些可以执行的完整c语句,更主要的是写在do{}while()中,它是一个子程序片段,因此x可以做很

多事,比如声明变量等

3 扩展:如何应用于其他平台代码设计

#include <stdio.h>
#define st(x) do{x}while(__LINE__==-1)
#define enable() st(EA = 1;) //使能所有中断
#define disable() st(EA = 0;) //关闭所有中断
#define enter(x) st(x = EA; disable();) //进入临界区
#define exit(x) st(EA = x;) //退出临界区

//临界代码执行
#define critical(s) st(int temp; enter(temp); s; exit(temp);)

//模拟控制所有中断的变量
int EA = 5;

int main()
{
int a = 0;
    
enter(a);
printf("EA=%d, a=%d\n", EA, a);
exit(a);
    
critical(printf("hello world-first\n"););
critical(printf("hello world-second\n"););

// 上面的 critical(printf("hello world-first\n");) 等价代码如下
do
{
int temp;
do {
temp = EA;
do{ EA = 0; } while(__LINE__==-1);
      } while(__LINE__==-1);

printf("hello world\n");
do{ EA =temp; } while(__LINE__==-1);
} while(__LINE__==-1);
}

执行结果为:
EA=0, a=5
hello world-first
hello world-second
hello world


猜你喜欢

转载自blog.csdn.net/liwei16611/article/details/74010862