分类:
2009-07-16 15:13:26
1 要使UCOSII正常运行,处理器必须满足以下要求:
(1)处理器的C编译器能产生可重入代码;
(2)处理器支持中断,并且能产生定时中断(通常为10-100KHZ);
(3)用C语言就可以开关中断;
(4)处理器能支持一定数量的数据存储硬件堆栈(可能几千字节);
(5)处理器有将堆栈指针以及其他CPU寄存器的内容读出、并存储到堆栈或内存中去的指令。
这里先学习下,可重入代码是什么?
可重入代码(Reentry code),也叫纯代码(Pure code)是一种允许多个进程同时访问的代码。为了使各进程所执行的代码完全相同,故不允许任何进程对其进行修改。程序在运行过程中可以被打断,并由开始处再次执行,并且在合理的范围内(多次重入,而不造成堆栈溢出等其他问题),程序可以在被打断处继续执行,且执行结果不受影响。
看两个程序例子:
void test1() {
int i=2;
i++;
printf("%d\n",i );
} //可重入代码
void test2() {
static int i=2;
i++;
printf("%d\n",i );
} //不可重入代码
test1 无论你是那次调用,结果始终是 2 ;test2则不同。
2 UCOSII 硬件软件体系结构
3 UCOSII移植所需要修改的部分
(1)OS_CPU.H 中的:
名称 |
类型 |
C语言?汇编? |
BOOLEAN |
数据类型 |
C语言 |
INT8U |
数据类型 |
C语言 |
INT8S |
数据类型 |
C语言 |
INT16U |
数据类型 |
C语言 |
INT16S |
数据类型 |
C语言 |
INT32U |
数据类型 |
C语言 |
INT32S |
数据类型 |
C语言 |
FP32 |
数据类型 |
C语言 |
FP64 |
数据类型 |
C语言 |
OS_STK |
数据类型 |
C语言 |
OS_CPU_SR |
数据类型 |
C语言 |
OS_CRITICAL_METHOD |
宏定义 |
C语言 |
OS_STK_GROWTH |
宏定义 |
C语言 |
OS_ENTER_GRITICAL() |
宏 |
C语言 |
OS_EXIT_CRTTICAL() |
宏 |
C语言 |
移植讲解:
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned int INT16U;
typedef signed int INT16S;
typedef unsigned long int INT32U;
typedef signed long int INT 32S;
typedef float FP32;
typedef double FP64;
typedef unsigned short OS_CPU_SR; /*CPU状态寄存器的宽度,在使用 OS_CRITICAL_METHOD #3的情况下,必须声明 OS_CPU_SR的数据类型*/
这些都是和编译器有关的,移植到不同的编译器的时候,需要对这些进行修改。
typedef unsigned int OS_STK; /*堆栈的入口宽度,如果处理器堆栈是32位的时候,那么必须声明 OS_STK INT32U*/
#define OS_STK_GROWTH 1 /* 定义堆栈方向 1 向下递减 0 向上递增*/
这是和处理器相关的。
OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()可用于临界代码的使用中。
注意:所有的PEND调用(OSTimeDly()之类)之前,不能关掉中断,否则,应用程序崩溃。
OS_ENTER_CRITICAL 和OS_EXIT_CRITICAL 的实现方法有3种,取决于处理器的类型以及C编译器的特性。
实现方法1 OS_CRITICAL_METHOD == 1
这是最简单的方法,直接使用处理器指令关中断;
这种方式的缺点是: 如果在禁止中断的情况下,调用UCOSII功能函数,从函数返回时,中断可能会变成允许的!
实现方法2 OS_CRITICAL_METHOD == 2
执行OS_ENTER_CRITICAL时,先将中断状态保存到堆栈,再关中断;执行OS_EXIT_CRITICAL时,从堆栈中恢复原来的中断状态。
缺点,当用户使用的处理器有堆栈指针相对寻址模式时,可能出现严重错误。
实现方法3 OS_CRITICAL_METHOD == 3
某些编译器提供了扩展功能,用户可以得到当前处理器状态字的值,并将其保存在C函数局部变量之中。
相关临界代码如下
OS_CPU_SR cpu_sr
cpu_sr = get_processor_psw();
disable_interrupts();
/*临界代码*/
set_processor_psw();
OS_TASK_SW() 的修改
OS_TASK_SW()是一个宏,是在UCOSII从低优先级切换到高优先级任务是必须用到的。另一个函数OSInitExit()用在中断服务子程序ISR中。当中断服务子程序使更高优先级的任务进入就绪态时,OSIntExit()完成任务切换功能。任务切换只是简单地将处理器的寄存器保存到将被挂起的任务的堆栈中,并且从堆栈中恢复要运行的更高优先级的任务。
为了任务调度,可以通过执行OS_TASK_SW()模仿中断的产生。绝大多数处理器会提供软中断或指令陷阱(TRAP)来完成这项功能。中断服务子程序或指令陷阱处理程序(也叫做异常处理程序)的中断向量地址必须指向汇编语言函数OSCtxSW().
示例程序清单
#define OS_TASK_SW() asm INT 080H
(2)OS_CPU_A.ASM中的
名称 |
类型 |
C语言?汇编 |
OSStartHighRdy() |
函数 |
汇编 |
OSCtwSw() |
函数 |
汇编 |
OSIntCtxSw() |
函数 |
汇编 |
OSTickISR() |
函数 |
汇编 |
(3)OS_CPU_C.C中的
名称 |
类型 |
C语言?汇编? |
OSTaskStkInit() |
函数 |
C语言 |
OSInitHookBegin() |
函数 |
C语言 |
OSInitHookEnd() |
函数 |
C语言 |
OSTaskCreateHook() |
函数 |
C语言 |
OSTaskDelHook() |
函数 |
C语言 |
OSTaskSwHook() |
函数 |
C语言 |
OSTaskStatHook() |
函数 |
C语言 |
OSTCBInitHook() |
函数 |
C语言 |
OSTimeTickHook() |
函数 |
C语言 |
OSTaskIdleHook() |
函数 |
C语言 |
4 开发工具
标准的C交叉编译器,同时还要支持汇编语言程序,并且能在C语言中开关中断
tang_m_cong2016-03-12 20:50:27
你这里描述可重入函数有误,1可重入函数一般指的是单进程多线程之间的情况,2printf函数本身就是不可重入的,你调用它你的函数也就不可重入了。