UCGUI 联系客服

发布时间 : 星期二 文章UCGUI更新完毕开始阅读40228020aaea998fcd220e05

__swi(0x41) void *GetUsrFunctionAddr(int Index);/* 获取自定义服务函数入口 */

__swi(0x42) void OSISRBegin(void); /* 中断开始处理 */

__swi(0x43) int OSISRNeedSwap(void); /* 判断中断是否需要切换 */ __swi(0x80) void ChangeToSYSMode(void); /* 任务切换到系统模式 */ __swi(0x81) void ChangeToUSRMode(void); /* 任务切换到用户模式 */ __swi(0x82) void TaskIsARM(INT8U prio); /* 任务代码是ARM代码 */ __swi(0x83) void TaskIsTHUMB(INT8U prio); /* 任务代码是THUMB */ #define OS_STK_GROWTH 1 /* 堆栈是从上往下长的 */ #define USR32Mode 0x10 /* 用户模式 */ #define SYS32Mode 0x1f /* 系统模式 */ #define NoInt 0x80 #ifndef USER_USING_MODE

#define USER_USING_MODE USR32Mode /* 任务缺省模式 */ #endif

#ifndef OS_SELF_EN

#define OS_SELF_EN 0 /* 允许返回OS与任务分别编译、固化*/ #endif

OS_CPU_EXT INT32U OsEnterSum; /* 关中断计数器(开关中断的信号量)*/ uC/OS II需要先关中断再访问临界区的代码,并且在访问完后重新允许中断。uC/OS II定义了两个宏来禁止和允许中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL(),本移植实现这两个宏的汇编代码。 #define interrupts*/ #define interrupts*/ EXPORT OSCPUSaveSR OSCPUSaveSR

OS_EXIT_CRITICAL()(OSCPURestoreSR(cpu_sr))/*Enable OS_ENTER_CRITICAL()(cpu_sr=OSCPUSaveSR())/*Disable

16

mrs r1,cpsr mov r0,r1 orr r1,r1,#0xc0 msr cpsr_cxsf,r1 mov pc,lr

EXPORT OSCPURestoreSR OSCPURestoreSR msr cpsr_cxsf,r0 mov pc,lr

3.3.2用C语言实现与处理器任务相关的函数[OS_CPU_C。C]

这个.C文件一共包含以下几个函数 OSTaskStkInit() OSTaskCreateHook() OSTaskDelHook() OSTaskSwHook() OSTaskStatHook() OSTimeTickHook()

实际需要修改的只有OSTaskStkInit()函数,其他五个函数需要声明,但不一定有实际内容。这五个函数都是用户定义的,所以OS_CPU_C。C中没有给出代码。如果需要使用这些函数,可以将文件OS_CFG。H中的#define constant OS_CPU_HOOKS_EN设为1,设为0表示不使用这些函数。

OSTaskStkInit()函数由OSTaskCreate()或OSTaskCreateExt()调用,需要传递的参数是任务代码的起始地址、参数指针(pdata)、任务堆栈顶端的地址和任务的优先级,用来初始化任务的堆栈,初始状态的堆栈模拟发生一次中断后的堆栈结构。堆栈初始化工作结束后,OSTaskStkInit()返回新的堆栈栈顶指针,OSTaskCreate()或OSTaskCreateExt()将指针保存在任务的OS_TCB中。调用OSTaskStkInit()给任务做一个初始的任务上下文堆栈(图3.3.2)

17

3.3.2 任务初始化堆栈

高端地址 任务最初栈指针 低端地址 CPSR R0 R1 ... LR(R14) PC(R15) 3.3.3处理器相关部分汇编实现

整个uC/OS II移植实现中,只需要提供一个汇编语言文件,提供几个必须由

汇编才能实现的函数。 a)OSStartHighRdy()

该函数在OSStart()多任务启动之后,负责从最高优先级任务的TCB控制块中获得该任务的堆栈指针sp,通过sp依次将CPU现场恢复,此时系统就将控制权交给用户创建的该任务的进程,直到该任务被阻塞或者被其他更高优先级的任务抢占了CPU。该函数仅仅在多任务启动时被执行一次,用来启动第一个,也就是最高优先级的任务执行。 b)OSCtxSw()

该函数是任务级的上下文切换函数,在任务因为被阻塞而主动请求与CPU调度时执行,主要工作是先将当前任务的CPU现场保存到该任务堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现场,使之继续执行,从而完成一次任务切换。 C)OSIntExit()

18

该函数是中断级的任务切换函数,在时钟中断ISR中发现有高优先级任务在等待时,需要在中断退出后不返回被中断的任务,而是直接调度就绪的高优先级任务执行。其目的在于能够尽快让高优先级的任务得到响应,保证系统的实时性能。

d)OSTickISR()

该函数是时钟中断处理函数,主要任务是负责处理时钟中断,调用系统实现的OSTimeTick函数,如果有等待时钟信号的高优先级任务,则需要在中断级别上调度其执行。另外两个相关函数是OSIntEnter()和OSIntExit(),都需要在ISR中执行。

3.3.4 uC/os2的移植与测试

1 验证OsTaskStkInit()和OSStartHighRdy()函数

在保证编译器能够正常工作和代码可以正常下载的后,编写一个最小的测试程序,并修改OS_CFG。H文件,设置OS_TASK_STAT_EN为0,以禁止统计任务,因为这里只需要一个任务就是空闲任务:OS_TaskIdle()。 代码如下: void main(void) {

Init_Settings(); /* 进行硬件的初始化工作 */ DisableInterrupts; /* 关闭中断 */ OSInit(); /* 初始化uCOS-II */ OSStart(); /* 运行uCOS-II */ }

这样代码只会执行一个任务,就是系统空闲任务OS_TaskIdle()。

在代码下载后,单步执行main()程序。跳过OSInit()函数,单步进入OSStart()函数,一直运行到OSStartHighRdy(),运行这个函数后,会切换到第一个任务进行运行,这里会切换到OS_TaskIdle()。

实际上,OSStartHighRdy()函数会将OsTaskStkInit()推入堆栈的CPU寄存器按照相反的顺序弹出。如果这一点不正确,堆栈指针就会错误。可以通过OSTCB

19