uC/OS-ii移植详解

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.ASM1:修改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      LR



OSIntCtxSw():在退出中断前调用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      LR

OS_CPU_SR_Restore()


    MSR     PRIMASK, R0    ;恢复全局中断标志

    BX      LR





【到此移植完毕】
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值