原创 UCOS开关中断函数移植

2010-8-30 14:25 2270 4 4 分类: MCU/ 嵌入式

OS_ENTER_CRITICAL()OS_EXIT_CRITICAL()用来关中断和开中断。在执行临界段代码时要关中断,如果中断打开,临界段代码中的一些全局变量值可能会被中断服务子程序代码改变,或者因为中断引起的任务切换被其它任务函数改变。


何谓“临界段”?在网上搜了下:


临界段也称为关键代码段,它是指一个小代码段。在它能够执行前,它必须独占对某些共享资源的访问权。一旦线程执行进入了临界段。就意味着它获得了这些共享资源的访问权。那么在该线程处于临界段内的期间,其它同样需要独占这些共享资源的线程就必须等待,直到获得资源的线程离开临界段而释放资源。


 


在LPC2214上移植这两个函数。


在OS_CPU.H中定义


采用第三种实现方法:


#define  OS_CRITICAL_METHOD    3


定义一个数据类型OS_CPU_SR


typedef unsigned int   OS_CPU_SR;  /* Define size of CPU status register (PSR = 32 bits) */


采用第3中方式,需要在UCOS-II函数中定义一个变量:


OS_CPU_SR  cpu_sr;


用来保存CPU的状态寄存器值。


定义关中断宏和开中断宏


#define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}


#define  OS_EXIT_CRITICAL()   {OS_CPU_SR_Restore(cpu_sr);}


函数声明:


#if OS_CRITICAL_METHOD == 3    /* Allocate storage for CPU status register          */


OS_CPU_SR  OS_CPU_SR_Save(void);


void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);


#endif


以上都是在OS_CPU.H文件中的。


 


NO_INT      EQU     0xC0        ; Mask used to disable interrupts (Both FIR and IRQ)


OS_CPU_SR_Save()和OS_CPU_SR_Restore()函数用汇编语言编写,在OS_CPU_A.S文件中


OS_CPU_SR_Save


        MRS     R0,CPSR                     1


        ORR     R1,R0,#NO_INT               2


        MSR     CPSR_c,R1                   3


        MRS     R1,CPSR                     4


 


        AND     R1,R1,#NO_INT               5


        CMP     R1,#NO_INT                  6


        BNE     OS_CPU_SR_Save             7


        MOV     PC,LR                       8


1-      读CPSR,把CPSR的值送到R0


2-      把R0和常量#NO_INT相或,结果送给R1,把F和I位置1,禁止IRQ中断和FIQ中断。


3-      把R1的值送给CPSR的低8位,CPSR_c的_c是位域,指CPSR的低8位。


4-      把修改后的CPSR值送到R1


5-      R1的值和#NO_INT相与,结果送到R1


6-      比较R1和#NO_INT是否相等


7-      不相等,跳到OS_CPU_SR_Save重新关中断,直到相等。


8-      LR保存的是在调用OS_CPU_SR_Save函数时的断点地址,把LR的值送到PC,退出OS_CPU_SR_Save函数,开始执行临界段代码。这条命令的功能相当于51中的RET。


   注意:ARM中调用子程序时不会自动保存CPSR的值到SPSR,所以子程序返回时,执行MOV     PC,LR也不会把SPSR的值返回到CPSR。这是ARM种调用子程序和进入中断的区别。


汇编函数的返回值是通过R0返回的,把修改前的CPSR值保存到cpu_sr.


 


OS_CPU_SR_Restore


        MSR     CPSR_c,R0           1


        MOV     PC,LR               2


1-      把R0的值送到CPSR的低8位。


在ARM中用R0传递函数的参数,这句指令就是把保存在cpu_sr中的值送到CPSR低8位。高24位没有修改。为什么不直接用MSR     CPSR,R0呢?因为ARM指令中规定MSR命令中,CPSR必须指定位域。把这句改成MSR     CPSR_cxsf,R0,即把R0的32位都送给CPSR,应该也没问题。不过在OS_CPU_SR_Save函数中,CPSR的高24位并没有改变。所以这里只需要把保存在cpu_sr中的低8位送到CPSR就可以了。


2-退出OS_CPU_SR_Restore函数。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条