UCosII移植之OS_CPU.H详解

来源:互联网 发布:白宫陷落 知乎 编辑:程序博客网 时间:2024/05/17 00:19

数据类型

 /******************************************************************************

*      定义数据类型    

******************************************************************************/

 typedef unsigned char  BOOLEAN;

typedef unsigned char  INT8U;                 /*Unsigned  8 bit quantity       */

typedef signed   char INT8S;                 /*Signed    8 bit quantity       */

typedef unsigned short INT16U;                 /* Unsigned 16 bitquantity       */

typedef signed   short INT16S;                 /* Signed   16bit quantity       */

typedef unsigned int   INT32U;                 /*Unsigned 32 bit quantity       */

typedef signed   int  INT32S;                /*Signed   32 bit quantity       */

typedef float          FP32;                   /*Single precision floating point*/

typedef double         FP64;                  /*Double precision floating point*/

 

typedef unsigned int   OS_STK;                /*Each stack entry is 32-bit wide*/

typedef unsigned int   OS_CPU_SR;          /*Define size of CPU status register*/

解析:因为CM3是32位宽的,所有OS_STK被类型重定义成32位的unsigned int,CM3的状态寄存器(xPSR)也是32位宽的,OS_CPU_SR被类型重定义为unsigned int类型重定义是为了方便移植,不同处理器编译不一样,比如ARM7 处理器字长为32位,半字长为16位,字节为8位,因此在移植时涉及到变量类型时只需要修改类型重定义即可。

临界区

/*******************************************************************************OS_CRITICAL_METHOD=1直接使用处理器的开关中断指令来实线宏

*OS_CRITICAL_METHOD=2 利用堆栈保护和恢复CPU状态

*OS_CRITICAL_METHOD=3 利用编译器扩展功能获得的程序状态字,保存在局部变量cpu_sr中

******************************************************************************/

#define OS_CRITICAL_METHOD   3        

/********选择第三种方法********************/

#if OS_CRITICAL_METHOD == 3

/********进入临界代码区********************/

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

/*********退出临界代码区*****************/

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

#endif

#if OS_CRITICAL_METHOD == 3                                       

OS_CPU_SR OS_CPU_SR_Save(void);

void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);

 

解析:一般喜欢使用第三种方法来实现临界区。

第一种直接开关中断的实现临界区的方法很少采用,因为这种方法可能将原本关闭了的中断意外的打开。

(简单的如51单片机的开关中断指令EA=1与EA=0,即实现直接使用处理器的开关中断,但问题是调用了OS_EXIT_CRITICAL后,处理器的中断一定为打开,而无论在进入临界代码之前的处理器的中断是打开或者关闭。但最理想的状态应该是,在用了OS_EXIT_CRITICAL后,处理器的中断打开与否状态,应该跟进入临界代码段之前处理器的中断状态一致)

第二种方法是最高效的实现方法,但是这种方法调整了堆栈指针,对于需要利用堆栈指针间接寻址局部变量的系统并不适用。(x86通常采用第二种方法,因为它有单独的寄存器来做局部变量的寻址)

(即在关闭中断之前,通过堆栈缓存CPU的中断寄存器状态,即记住进入临界代码之前CPU的中断打开与否状态,然后在推出临界代码的时候,只需将堆栈中的CPU中断状态寄存器弹出堆栈,这样即能实现用了宏OS_EXIT_CRITICAL后,处理器的中断打开与否状态,跟进入临界代码段之前处理器的中断状态一致)

第三种方法最保险,虽然效率比第二种方法略低一点。

(一些处理器可以读取PSW寄存器的值,将包含中断开关状态的PSW寄存器值保持在C语言变量中没在退出临界代码段时,再将局部变量中的值回写到PSW寄存器中。STM32可以通过MRS与MSR指令读写特殊寄存器,因此选用了第三种方式)

OS_CPU_SR_Save()和OS_CPU_SR_Restore(cpu_sr)在os_cpu_a.asm中实现

其实也可以通过C代码(OS_CPU_C.C)中插入汇编的方式来实现:

1.    __asm OS_CPU_SR OS_CPU_SR_Save(void)  

2.    {  

3.        MRS     R0, PRIMASK ; Set prio int mask to mask all (except faults)  

4.        CPSID   I  

5.        BX      LR  

6.    }  

7.    __asm void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)  

8.    {  

9.        MSR     PRIMASK, R0  

10.     BX      LR  

11.  }  

三堆栈

#define OS_STK_GROWTH        1    

CM3中,栈是由高地址向低地址生长的,因此OS_STK_GROWTH设为1

任务切换

#define OS_TASK_SW()         OSCtxSw()

任务切换宏,由汇编实现,在os_cpu_a.asm中

函数原型声明

未作修改应该是这样

void       OSCtxSw(void);

void       OSIntCtxSw(void);

void       OSStartHighRdy(void);

void       OS_CPU_PendSVHandler(void);

void       OS_CPU_SysTickHandler(void);         

void       OS_CPU_SysTickInit(INT32U  cnts);

 修改:

A:将OS_CPU_PendSVHandler(void)改为PendSV_Handler(void)

B:注释掉

OS_CPU_SysTickHandler(void)和OS_CPU_SysTickInit(INT32U  cnts)

详细分析:

A:修改为PendSV_Handler

UCOSII在stm32中的上下文切换是通过触发一个PendSV的异常(优先级较低),然后再异常服务程序里实现的。os_cpu_a.asm中标号为OS_CPU_PendSVHandler和OS_CPU_PendSVHandler_nosave的内容即是。


但是Micrium官方没有ST公司官方的启动代码,用的是自己的启动代码,在startup_stm32f10x_cl.s中看到在启动设置中断向量表时,PendSV的异常标号为PendSV_Handler,因此两者有矛盾,可选择不改变ST官方的文件,即不改变启动代码,修改ucosII的接口文件中的代码


 修改PendSV

(1)在os_cpu.a.asm中




(2)在os_cpu.h中


(3)在stm32f10x_it.h中


B:注释掉OS_CPU_SysTickHandler(void)

OS_CPU_SysTickHandler(void)定义在os_cpu_c.c中,是systick的中断处理函数,而在stm32f10x_it.c中已经有该函数的定义


C:注释掉OS_CPU_SysTickInit(INT32U  cnts)

OS_CPU_SysTickInit(INT32U  cnts)定义在os_cpu_c.c中,用以初始化systick定时器,此函数我们自己实现,故注释掉

 

0 0