uC/OS-ii移植详解
来源:互联网 发布:均不是c语言关键字 编辑:程序博客网 时间:2024/06/07 13:31
uC/OS ii的移植要点: uC/OS ii的移植相当LINUX来说是非常简单的,uC/OS ii的移植涉及到的代码很少;我们只需要修改与处理器相关的代码即可; OS_CPU.H:设置与处理器与编译器有关的代码 OS_CPU_C.C:在这其中用C语言编写6个与操作系统相关的函数 OS_CPU.ASM:在这其中用汇编语言编写4个与处理器相关的函数 如上图,需要移植的部分就是Ports路径下的几个代码文件,其他的代码都不要移植(os_cfg.h只是用来配置系统的各个功能,做系统的裁剪而且,ucos_ii.h中提供系统所有的接口函数,os_cpu_a.asm就是OS_CPU.ASM)1:修改OS_CPU.H OS_CPU.H中定义了数据类型、处理器的堆栈数据类型的字长、堆栈增长方向、任务切换宏、临界区访问处理。 从方便移植的角度,uC/OS ii使用的数据类型,都是自己定义的那一套。 typedef unsigned char BOOLEAN; typedef unsigned char INT8U; typedef signed char INT8S; typedef unsigned short INT16U; typedef signed short INT16S; typedef unsigned long INT32U; typedef signed long INT32S; typedef float FP32; typedef double FP64; typedef unsigned int OS_STK; typedef unsigned int OS_CPU_SR; M3使用的是向下生长的满栈,堆栈指针指向最后一个被压入堆栈的32位整数: #define OS_STK_GROWTH 1 定义开关中断的宏: #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 定义宏OS_TASK_SW执行任务切换:#define OS_TASK_SW() OSCtxSw()2:在OS_CPU_C.C中要求用户编写10个简单的C函数【唯一必要修改的函数是OSTaskStkInit(),其余的函数必须声明,但并不一定要包含任何代码】OSTaskStkInit():任务创建函数OSCreate()与OSCreateExt()通过调用OSTaskStkInit,初始化任务的栈结构,因此,任务的堆栈看起来就像刚发生了中断一样(所以的寄存器按一定的次序都保存在堆栈中,为什么要这样做?因为任务间的切换就是任务堆栈中保存的CPU现场的切换,所以任务被创建时,要初始化它的堆栈,为后面的切换做准备)OSTaskCreateHook(ptcb):【系统提供给用户的钩子函数】任务创建时OSCreate()与OSCreateExt()调用OS_TCBInit,OS_TCBInit会调用OSTaskCreateHook,同时传递指向刚刚建立的任务的任务控制块的指针,这样OSTaskCreateHook就可以访问任务控制块结构的所有成员,这个函数的功能有限,不是必要的函数,且需要通过OS_APP_HOOKS_EN使能,且该函数调用时中断是开着的。OSTaskDelHook(ptcb):OSTaskDel()会调用OSTaskDelHook(ptcb),即在将任务从uC/OS II的内部有效链表中删除之前被调用,同时传递一个指向被删除任务的任务控制块的指针,OSTaskDelHook可以用来检验TCB扩展部分是否已建立(一个非空指针),并可进行一些清0操作,OSTaskDelHook调用时,中断是关闭的,函数太长会影响中断响应时间。OSTaskSwHook():在任务切换时会调用OSTaskSwHook,不论是在OSCtxSw()还是OSIntCtxSw(),都会调用该函数,OSTaskSwHook可访问全局变量OSTCBCur(指向将被切换出去的任务的任务控制块)、OSTCBHiggRdy(指向新任务的任务控制块) ,OSTaskSwHook被调用时,中断是关闭的,函数太长会影响中断响应时间。OSTaskIdleHook():很多微处理器都允许执行相应的指令,将CPU置于低功耗模式,而当接收到中断信号时,CPU就会自动退出低功耗模式。OS_TaskIdle()函数可以调用OSTaskIdleHook()来实现CPU的这种低功耗模式【很好】。OSTaskStatHook():该函数每秒都会被统计任务OS_TaskStat()【统计任务每秒执行一次】调用一次,可以通过该函数扩展统计任务的功能,如可跟踪并显示每个任务的执行时间、每个任务所用的CPU份额以及每个任务执行的频率等等,该函数没有任何参数。OSTimeTickHook():该函数在每个时钟节拍都会被OSTimeTick()调用;systick中断服务程序SysTickHandler调用OSTimeTickHook,在这里面用户可以处理应急的事务。OSInitHookBegin():进入OSInit()函数后,OSInitHookBegin就会被调用,添加这个函数的原因在于想把与OS有关的初始化代码也放在OSInti()函数中,这个函数使得用户可以将自己特定的代码也放在OSInit()函数中。OSInitHookEnd():OSInitHookEnd与OSInitHookBegin相似,只是他在OSInit()函数返回之前被调用,添加这个函数的原因与OSInitHookBegin是一样的。OSTCBInitHook(ptcb):任务创建时OSCreate()与OSCreateExt()调用OS_TCBInit,OS_TCBInit会在调用OSTaskCreateHook前调用 OSTCBInitHook ,用户可以在OSTCBInitHook函数中做一些与初始化控制块OS_TCB有关的处理,在OSTaskCreateHook中做一些与初始化任务有关的处理;OSTCBInitHook收到的ptcb参数指向新添加任务的任务控制块的指针,而这个新添加任务的任务控制块绝大部分已经初始化完成,但是还没有链接到已经建立任务的链表中。OS_STK * OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt){ OS_STK *stk; (void)opt; stk = ptos; *(stk) = (INT32U)0x01000000L; //xPSR *(--stk) = (INT32U)task; //Entry Point *(--stk) = (INT32U)0xFFFFFFFEL; // R14(LR) (init value will cause fault if ever used) *(--stk) = (INT32U)0x12121212L; // R12 *(--stk) = (INT32U)0x03030303L; // R3 *(--stk) = (INT32U)0x02020202L; // R2 *(--stk) = (INT32U)0x01010101L; // R1 *(--stk) = (INT32U)p_arg; // R0 : argument //Remaining registers saved on process stack *(--stk) = (INT32U)0x11111111L; // R11 *(--stk) = (INT32U)0x10101010L; // R10 *(--stk) = (INT32U)0x09090909L; // R9 *(--stk) = (INT32U)0x08080808L; // R8 *(--stk) = (INT32U)0x07070707L; // R7 *(--stk) = (INT32U)0x06060606L; // R6 *(--stk) = (INT32U)0x05050505L; // R5 *(--stk) = (INT32U)0x04040404L; // R4 return (stk);}3:在OS_CPU_A.ASM中用汇编写4个与处理器相关的函数 需要移植的函数有,如下所示, OSStartHighRdy():在调用OSStart()函数时,使就绪态任务中优先级最高的任务开始运行 OSCtxSw(): OSIntCtxSw(): OSTickISR(): OS_CPU_SR_Save() OS_CPU_SR_Restore():OSCtxSw():可以参考学习笔记中的记录,M3中任务切换还需实现软中断的处理函数OSCtxSw ;悬起PSV异常 LDR R0, =NVIC_INT_CTRL LDR R1, =NVIC_PENDSVSET STR R1, [R0] BX LROSIntCtxSw():在退出中断前调用OSIntCtxSw,在ISR中执行任务的切换功能,OSIntCtxSw与OSCtxSw基本相同,M3的是一模一样的。OSPendSV 【软中断的处理函数】 MRS R0, PSP CBZ R0, OSPendSV_nosave SUBS R0, R0, #0x20 STM R0, {R4-R11} LDR R1, __OS_TCBCur LDR R1, [R1] STR R0, [R1] OSPendSV_nosave PUSH {R14} LDR R0, __OS_TaskSwHook ; OSTaskSwHook(); BLX R0 POP {R14} LDR R0, __OS_PrioCur LDR R1, __OS_PrioHighRdy LDRB R2, [R1] STRB R2, [R0] LDR R0, __OS_TCBCur LDR R1, __OS_TCBHighRdy LDR R2, [R1] STR R2, [R0] LDR R0, [R2] LDM R0, {R4-R11} ADDS R0, R0, #0x20 MSR PSP, R0 ORR LR, LR, #0x04 BX LR OSTickISR在这里即SysTickHandler函数void SysTickHandler(void){ OS_CPU_SR cpu_sr; OS_ENTER_CRITICAL(); OSIntNesting++; OS_EXIT_CRITICAL(); OSTimeTick(); //主要判断延时的任务是否计时到 OSIntExit(); //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换}OSStartHighRdy LDR R0, =NVIC_SYSPRI2 LDR R1, =NVIC_PENDSV_PRI STRB R1, [R0] //这几句是设置PendSV优先级 MOVS R0, #0 MSR PSP, R0 //设置PSP的初始值0(在第一次PendSV中断服务程序中不用保存CPU的各寄存器) LDR R0, __OS_Running MOVS R1, #1 STRB R1, [R0] // OSRunning = TRUE,表明操作系统已经运行 LDR R0, =NVIC_INT_CTRL LDR R1, =NVIC_PENDSVSET STR R1, [R0] //触发PendSV中断,暂时挂起 CPSIE I //开总中断【一定要在这里才开总中断,如果在此之前任何一个地方开中断,系统一旦响应中断,很有可能造成系统因没有做出足够的准备而出错(比如如果在初始化systicks时就开启了中断,uC/OS此时还处于未知阶段,就会崩溃),所在在这里开启总中断才是安全的】 OS_CPU_SR_Save() MRS R0, PRIMASK ;保存全局中断标志 CPSID I ;关中断 BX LROS_CPU_SR_Restore() MSR PRIMASK, R0 ;恢复全局中断标志 BX LR【到此移植完毕】
0 0
- uC/OS-ii移植详解
- uC/OS-II 移植
- uC/OS II移植
- UC/OS -II 移植对比
- UC/OS-II 操作系统移植
- UC/OS-II 操作系统移植
- uC/OS-II移植 详解 系统时钟部分
- uC/OS-II嵌入式操作系统移植
- uC/OS-II嵌入式操作系统移植
- uC/OS-II嵌入式操作系统移植
- uC/OS-II嵌入式操作系统移植
- UC/OS-II学习笔记--STM32移植
- uc/os-II的内存改进与实现TLSF算法的详解,移植实现(一)
- uc/os-II的内存改进与实现TLSF算法的详解,移植实现(二)
- uc/os-II的内存改进与实现TLSF算法的详解,移植实现(三)
- uc/os-II的内存改进与实现TLSF算法的详解,移植实现(四)
- 移植uC/OS-II到51_《嵌入式实时操作系统uC/OS-II》
- uc/os-II在ARM7上的移植探索
- java面试题总结(1)
- dubbo框架搭建
- Fragment与Fragment、Activity通信的四种方式(三)
- 第14周项目1-(2)验证分块查找算法
- 哈夫曼树详解
- uC/OS-ii移植详解
- Android Jni调用浅述
- 用matplotlib来画图-python学习笔记16
- 【NOIP 2016】 组合数问题 解题报告
- (2)C语言常用图形函数
- HDU2109 Fighting for HDU
- 学习 UML 核心元素
- Tomcat-----Linux下实时查看Tomcat日志
- macbook系统升级到10.12.1后office办公软件不可用问题解决