ucos-ii在MC9S12XDP512上的移植
2021-08-11 来源:eefocus
搞了几天,总算把ucos-ii移植到MC9S12XDP512上了。做个简短的笔记。
ucos-ii版本:2.52, 编译器:Freescale CodeWarrior5.9 芯片:MC9S12XDP512
移植步骤:
1. 根据向导建立新的工程,芯片选择MC9S12XDP512,其余默认配置;
2. 将ucos-ii通用源文件复制到工程的Sources目录下下:OS_CORE.C,OS_DBG.C,OS_FLAG.C,OS_MBOX.C,OS_MEM.C,
OS+MUTEX.C,OS_Q.C,OS_SEM.C,OS_TASK.C,OS_TIME.C,uCos_II.H,os_cfg.h并将这些文件添加到工程中;
3. 创建新文件,并命名为includes.h,将其添加到工程中,includes.h文件内容为:
#include #include 'derivative.h' /* derivative-specific definitions */ #include #include #include #include #include 'OS_CPU.H' #include 'os_cfg.h' #include 'uCOS_II.H' 4. 创建新文件OS_CPU.H,并将其添加到工程中,OS_CPU.H文件内容为: #ifdef OS_CPU_GLOBALS #define OS_CPU_EXT #else #define OS_CPU_EXT extern #endif typedef unsigned char BOOLEAN; typedef unsigned char INT8U; /* 8 bit */ typedef signed char INT8S; /* 8 bit */ typedef unsigned int INT16U; /* 16 bit */ typedef signed int INT16S; /* 16 bit */ typedef unsigned long INT32U; /* 32 bit */ typedef signed long INT32S; /* 32 bit */ typedef float FP32; /* */ typedef double FP64; /* */ typedef unsigned char OS_STK; /* */ typedef unsigned char OS_CPU_SR; // CCR 8 bits #define OS_CRITICAL_METHOD 3 #if OS_CRITICAL_METHOD == 1 #define OS_ENTER_CRITICAL() #define OS_EXIT_CRITICAL() #endif #if OS_CRITICAL_METHOD == 2 #define OS_ENTER_CRITICAL() #define OS_EXIT_CRITICAL() #endif #if OS_CRITICAL_METHOD == 3 #define OS_ENTER_CRITICAL() asm tpa;asm sei;asm staa cpu_sr /* Disable interrupt */ #define OS_EXIT_CRITICAL() asm ldaa cpu_sr;asm tap /* Enable interrupt */ #endif #define OS_STK_GROWTH 1 /* top to bottom */ #define OS_TASK_SW() asm swi /* software interrupt */ 5. 创建新文件os_cpu_c.c,并添加到工程中,os_cpu_c.c文件内容较多,主要有以下部分: 1. 以下函数均为空: OSTaskCreateHook(),OSTaskDelHook(),OSTaskSwHook(),OSTaskIdleHook(), OSTaskStatHook(),OSTimeTickHook(),OSInitHookBegin(),OSInitHookEnd(),OSTCBInitHook(), 2. OSTaskStkInit()函数内容: 该函数主要模拟中断产生时CPU的压栈过程,根据芯片资料(IS12CpuV1.pdf),中断的压栈次序为: SP+7 RTNH:RTNL (返回地址) SP+5 Y SP+3 X SP+1 D(B:A) SP CCR 由上,OSTaskStkInit()内容为: // ============================================= // 模拟中断产生初始化堆栈 // 中断产生时,堆栈压栈过程: (参见9S12cpuV1.pdf P381) /* SP+7 RTNH:RTNL (返回地址) SP+5 Y SP+3 X SP+1 D(B:A) SP CCR */ // ============================================= OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) { INT16U *wstk; INT8U *bstk; opt = opt; // 'opt' is not used, prevent warning wstk = (INT16U *)ptos; // Load stack pointer *--wstk = (INT16U)pdata; // Simulate call to function with argument *--wstk = (INT16U)(((INT32U)task) >> 8); // Return address. Format: PCH:PCL:PPAGE (cut out PPage) // 函数地址构成: PCH:PCL:PPAGE *--wstk = (INT16U)(((INT32U)task) >> 8); // 存储Y,X,D,CCR的当前值,实际任务还未开始,因此,X,Y,D,等也未用,可以随便取值,此处都取0 *--wstk = (INT16U)0x0; // Y Register *--wstk = (INT16U)0x0; // X Register *--wstk = (INT16U)0x0; // D Register bstk = (INT8U *)wstk; // Convert WORD ptr to BYTE ptr to set CCR *--bstk = (0xC0); // CCR Register (Disable STOP instruction and XIRQ) *bstk = (INT8U)task; // Save the PPAGE register // 地址低8位为PPAGE return ((OS_STK *)bstk); // Return pointer to new top-of-stack } 3. 由于CodeWarrior可以内联汇编,因此将以下4个需要由汇编编写的函数也放于Os_cpu_c.c中:OSStartHighRdy(), OSCtxSw(), OSIntCtxSw(),OSTickISR().注意,这4个函数都应该编写在非分页区,4个函数的内容为: #pragma CODE_SEG NON_BANKED void OSStartHighRdy(void) { OSTaskSwHook(); //Call Hook function asm { ldx OSTCBCur; // load the value in OSTCBCur or // 偏移量0,此处实际为堆栈指针地址 lds 0,x; inc OSRunning; //OSRunning = 1 pula; // 弹出PPAGE staa PPAGE; nop; rti; } } void OSIntCtxSw(void) { OSTaskSwHook(); //Call Hook function OSTCBCur = OSTCBHighRdy; //change OSTCBCur and OSPrioCur OSPrioCur = OSPrioHighRdy; asm { ldx OSTCBCur; //Get the new task's TCB's address lds 0,x; pula; staa PPAGE; rti; } } void interrupt 4 OSCtxSw(void) /*swi interrupt */ { asm { // 保存PPAGE ldaa PPAGE; psha; nop; // 在当前任务控制块中保存当前任务的堆栈指针 ldx OSTCBCur; sts 0,x; } OSTaskSwHook(); //call Hook function OSTCBCur = OSTCBHighRdy; // 得到将要重新运行任务的堆栈指针 asm { ldx OSTCBCur; lds 0,x; pula; staa PPAGE; // 恢复PPAGE nop; rti; // 中断返回,恢复寄存器并运行任务 } } void interrupt 7 OSTickISR(void) { asm { ldaa PPAGE; psha; } // 保存PPAGE OSIntEnter(); if(OSIntNesting == 1) { asm { ldx OSTCBCur; sts 0,x; } } CRGFLG |= 0x80; // 清中断 OSTimeTick(); OSIntExit(); /* exit interrupt and task switch*/ // 没有更高优先级的任务进入就绪态,则中断返回 asm { pula; staa PPAGE; rti; } } #pragma CODE_SEG DEFAULT 6. 按自己需要修改os_cfg.h配置文件 7. 在main.c中编写如下测试代码: #include 'includes.h' #define TASK_STK_SIZE 64 /* static size */ OS_STK TaskStartStkA[TASK_STK_SIZE]; OS_STK TaskStartStkB[TASK_STK_SIZE]; void Basic_Init(void); void TaskStartA(void *data); void TaskStartB(void *data); void main(void) { OSInit(); Basic_Init(); OSTaskCreate(TaskStartA, (void *)0, &TaskStartStkA[TASK_STK_SIZE - 1], 0); OSTaskCreate(TaskStartB, (void *)0, &TaskStartStkB[TASK_STK_SIZE - 1], 1); OSStart(); } // 设备初始化 void Basic_Init(void) { // 实时时钟配置 RTICTL=0x49; //10ms Interrupt CRGINT_RTIE=1; //Enabe Interrupt // 端口配置 DDRB_DDRB2 = 1; // TaskA,PB2,输出 DDRB_DDRB3 = 1; // TaskB,PB3,输出 } // 任务 void TaskStartA (void *pdata) { pdata = pdata; /* nothing */ while (1) { PORTB_PB2 =~PORTB_PB2; OSTimeDly(100); /* 1000ms */ } } void TaskStartB (void *pdata) { pdata = pdata; while (1) { PORTB_PB3 = ~PORTB_PB3; OSTimeDly(20); /* 200ms */ } }
下一篇:MC9S12G128 串口通信