基于Cortex-M0的UCOS移植

2012-05-21的我突然想做一下ucos在cortex-m0平台上的移植,所以就看cortex-m0的内核架构和指令集,接着就开始着手移植了。先说明一下,我的开发板是新唐(Nuvoton)的NuTiny-EVB M051,芯片是M0516LAN。 

可以分两步走。第一步,移植ucos的底层代码。第二步,建立新任务。

 

第一步:移植ucos就是修改这么几个文件:os_cpu_c.c , os_cpu.h , os_cpu_a.asm

其中,os_cpu.h主要是定义数据类型的定义,和有关处理器的一些设置,如栈的生长方向,进入临界代码段的方式,数据存储的大小端设置等等。

 

1. os_cpu.h:

1.1 定义好数据类型。这个简单,所以不用怎么说。

1.2 定义进行临界代码段的方式,我定义为方式3。即进入时保存PSR,然后关中断,出来是恢复PSR的值。

  对应的函数为:OS_CPU_SR  OS_CPU_SR_Save(void), void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)

1.3 定义栈的生长方向。我定义为从高向下生长的方向。

1.4 函数的声明。这里有5个函数需要声明。分别是:

  void OSCtxSw(void)

  void OSIntCtxSw(void)

  void OSStartHighRdy(void)

  OS_CPU_SR  OS_CPU_SR_Save(void)

  void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr)

  由于OSIntCtxSw和OSCtxSw代码可以一致,所以只定义OSCtxSw。

 

1.5 具体代码如下:

  
  
  
  
  1. #ifndef  OS_CPU_H  
  2. #define  OS_CPU_H  
  3. #ifdef   OS_CPU_GLOBALS  
  4. #define  OS_CPU_EXT  
  5. #else  
  6. #define  OS_CPU_EXT  extern  
  7. #endif  
  8. #ifndef  OS_CPU_EXCEPT_STK_SIZE  
  9. #define  OS_CPU_EXCEPT_STK_SIZE    1           /* Default exception stack size is 128 OS_STK entries */  
  10. #endif  
  11. typedef unsigned char  BOOLEAN;  
  12. typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */ 
  13. typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */ 
  14. typedef unsigned short INT16U;                   /* Unsigned 16 bit quantity                           */ 
  15. typedef signed   short INT16S;                   /* Signed   16 bit quantity                           */ 
  16. typedef unsigned int   INT32U;                   /* Unsigned 32 bit quantity                           */ 
  17. typedef signed   int   INT32S;                   /* Signed   32 bit quantity                           */ 
  18. typedef float          FP32;                     /* Single precision floating point                    */ 
  19. typedef double      FP64;                     /* Double precision floating point                    */ 
  20. typedef unsigned int   OS_STK;                   /* Each stack entry is 32-bit wide                    */ 
  21. typedef unsigned int   OS_CPU_SR;            /* Define size of CPU status register (PSR = 32 bits) */ 
  22. #define  OS_CRITICAL_METHOD   3  
  23. #if OS_CRITICAL_METHOD == 3  
  24. #define  OS_ENTER_CRITICAL()  {cpu_sr = OS_CPU_SR_Save();}  
  25. #define  OS_EXIT_CRITICAL()     {OS_CPU_SR_Restore(cpu_sr);}  
  26. #endif  
  27. #define  OS_STK_GROWTH        1                   /* Stack grows from HIGH to LOW memory on ARM        */  
  28. #define  OS_TASK_SW()         OSCtxSw()  
  29. #if OS_CRITICAL_METHOD == 3                         
  30. OS_CPU_SR  OS_CPU_SR_Save        (void);  
  31. void       OS_CPU_SR_Restore     (OS_CPU_SR cpu_sr);  
  32. #endif  
  33. void       OSCtxSw               (void);             
  34. void       OSStartHighRdy        (void);  
  35.  
  36. #define OSIntCtxSw()         OSCtxSw();  
  37. #endif 

 

2. os_cpu_c.c

 2.1 定义函数OSTaskStkInit(),对于其它的函数可以不用理,因为如果你不需要用到钩子函数的话,是不用实现的。

  OSTaskStkInit()主要初始化各个任务的栈。

 2.2 由于cortex-m0的架构决定,当产生异常(包括中断)时,进栈的顺序如下:(这是Full descending的模式)

  XXX <---SP before exception

  xPSR

  PC

  LR

  R12

  R3

  R2

  R1

  R0    <--SP after before exception

 2.3 代码如下:

 

  
  
  
  
  1. OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)  
  2. {  
  3.     OS_STK *stk;  
  4.     (void)opt;                                  // 'opt' is not used, prevent warning                      
  5.     stk       = ptos;                          // Load stack pointer                                       
  6.                                                /* Registers stacked as if auto-saved on exception        */ 
  7.     *(--stk)  = (INT32U)0x01000000L;           // xPSR                                                     
  8.     *(--stk)  = (INT32U)task;                        // Entry Point (PC)                                         
  9.     *(--stk)  = (INT32U)0xefefefefL;                 // LR                                                      
  10.     *(--stk)  = (INT32U)0x12121212L;           // R12                                                     
  11.     *(--stk)  = (INT32U)0x03030303L;           // R3                                                      
  12.     *(--stk)  = (INT32U)0x02020202L;           // R2                                                       
  13.     *(--stk)  = (INT32U)0x01010101L;           // R1                                                       
  14.     *(--stk)  = (INT32U)p_arg;                       // R0 : argument                                            
  15.                                                /* Remaining registers saved on process stack             */ 
  16.     *(--stk)  = (INT32U)0x07070707L;           //R7                                                       
  17.     *(--stk)  = (INT32U)0x06060606L;           // R6                                               
  18.     *(--stk)  = (INT32U)0x05050505L;           // R5                                                      
  19.     *(--stk)  = (INT32U)0x04040404L;           // R4                                                     
  20.     *(--stk)  = (INT32U)0x11111111L;           // R11                                                     
  21.     *(--stk)  = (INT32U)0x10101010L;           // R10                                                    
  22.     *(--stk)  = (INT32U)0x09090909L;           // R9                                                     
  23.     *(--stk)  = (INT32U)0x08080808L;           // R8                                                     
  24.     return (stk);  

3. os_cpu_a.asm

 这个文件是对头文件 os_cpu.h所定义的函数进行实现。都是汇编代码,不过不是很难懂。

 

  
  
  
  
  1. ;2011-05-23 xiaoben  
  2.  
  3.      EXTERN  OSRunning  
  4.  
  5.      EXTERN  OSPrioCur  
  6.  
  7.      EXTERN  OSPrioHighRdy  
  8.  
  9.      EXTERN  OSTCBCur  
  10.  
  11.      EXTERN  OSTCBHighRdy  
  12.  
  13.      EXTERN  OSIntNesting  
  14.  
  15.      EXTERN  OSIntExit  
  16.  
  17.      EXTERN  OSTaskSwHook  
  18.  
  19.    
  20.  
  21.    
  22.  
  23.     EXPORT OS_CPU_SR_Save  
  24.  
  25.     EXPORT OS_CPU_SR_Restore  
  26.  
  27.     EXPORT OSStartHighRdy  
  28.  
  29.     EXPORT OSCtxSw  
  30.  
  31.     EXPORT OSIntCtxSw  
  32.  
  33.  
  34.     AREA os_cpu_asm, CODE, READONLY, ALIGN=2  
  35.  
  36.     THUMB  
  37.  
  38.     REQUIRE8  
  39.  
  40.     PRESERVE8  
  41.  
  42.    
  43.  
  44.  
  45. OS_CPU_SR_Save  
  46.  
  47.     MRS R0, PRIMASK  
  48.  
  49.     CPSID I  
  50.  
  51.     BX LR  
  52.  
  53.    
  54.  
  55.    
  56.  
  57.    
  58.  
  59.  
  60. OS_CPU_SR_Restore  
  61.  
  62.     MSR PRIMASK, R0  
  63.  
  64.     BX LR  
  65.  
  66.  
  67.    
  68.  
  69.    
  70.  
  71.    
  72.  
  73. OSStartHighRdy  
  74.  
  75.     LDR     R0, __OSTaskSwHook   ; Call OSTaskSwHook()  
  76.  
  77.     BLX     R0     
  78.  
  79.    
  80.  
  81.     LDR     R0, __OSRunning   ; OSRunning=1  
  82.  
  83.     MOVS    R1, #0x01  
  84.  
  85.     STRB    R1, [R0]      
  86.  
  87.    
  88.  
  89.     LDR     R0, __OSTCBHighRdy   ; SP = OSTCBHighRdy->OSTCBStkPtr  
  90.  
  91.     LDR     R1, [R0]  
  92.  
  93.     LDR     R2, [R1]  
  94.  
  95.     MSR     MSP, R2  
  96.  
  97.   ; Restore registers from new task stack  
  98.  
  99.     POP    {R0-R7}   ; Restore R4-R7, R8-R11  
  100.  
  101.     MOV    R11, R3  
  102.  
  103.     MOV    R10, R2  
  104.  
  105.     MOV    R9, R1  
  106.  
  107.     MOV    R8, R0  
  108.  
  109.    
  110.  
  111.     ADD    SP, #0x10   ; Restore PSR, PC, LR, R12  
  112.  
  113.     POP    {R0-R3}  
  114.  
  115.     MOV    R12, R0  
  116.  
  117.     MOV    LR, R1  
  118.  
  119.     PUSH   {R2}   ; Push PC into stack  
  120.  
  121.     MSR    PSR, R3  
  122.  
  123.         
  124.  
  125.     SUB    SP, #0x1C   ; Restore R0-R3  
  126.  
  127.     POP    {R0-R3}  
  128.  
  129.     ADD    SP, #0x0C  
  130.  
  131.  
  132.     CPSIE  I   ; Enable interrupts. NOTE: must not omit!  
  133.  
  134.     POP    {PC}   ; Jump to the task and execute, not return.  
  135.  
  136.    
  137.  
  138.    
  139.  
  140.    
  141.  
  142.    
  143.  
  144.    
  145.  
  146. OSCtxSw  
  147.  
  148. CPSID I     
  149.  
  150.   ; Save registers into current task stack  
  151.  
  152. SUB SP, #0x20   ; Save R4-R7  
  153.  
  154. PUSH {R4-R7}  
  155.  
  156.  
  157. ADD SP, #0x30   ; Save PSR, PC, LR, R12, R0-R3  
  158.  
  159. MRS R7, PSR  
  160.  
  161. MOV R6, LR   ; NOTE!  
  162.  
  163. MOV R5, LR  
  164.  
  165. MOV R4, R12  
  166.  
  167. PUSH {R0-R7}     
  168.  
  169.  
  170. SUB SP, #0x10   ; Save R8-R11  
  171.  
  172. MOV R3, R11  
  173.  
  174. MOV R2, R10  
  175.  
  176. MOV R1, R9  
  177.  
  178. MOV R0, R8  
  179.  
  180. PUSH {R0-R3}  
  181.  
  182.   ; Save SP in current stask stack  
  183.  
  184. MRS R0, MSP   ; OSTCBCur->OSTCBStkPtr = SP  
  185.  
  186. LDR R1, __OSTCBCur  
  187.  
  188. LDR R2, [R1]  
  189.  
  190. STR R0, [R2]  
  191.  
  192.  
  193. LDR R0, __OSTaskSwHook   ; Call OSTaskSwHook()  
  194.  
  195. BLX R0  
  196.  
  197.  
  198. LDR R0, __OSPrioCur   ; OSPrioCur = OSPrioHighRdy  
  199.  
  200. LDR R1, __OSPrioHighRdy  
  201.  
  202. LDRB R2, [R1]  
  203.  
  204. STRB R2, [R0]  
  205.  
  206.  
  207. LDR R0, __OSTCBCur   ; OSTCBCur = OSTCBHighRdy  
  208.  
  209. LDR R1, __OSTCBHighRdy  
  210.  
  211. LDR R2, [R1]  
  212.  
  213. STR R2, [R0]  
  214.  
  215.  
  216. LDR R0, [R2]   ; SP = OSTCBHighRdy->OSTCBStkPtr  
  217.  
  218. MSR MSP, R0  
  219.  
  220.   ; Restore registers from new task (with high priority) stack  
  221.  
  222. POP {R0-R7}   ; Restore R4-R7, R8-R11  
  223.  
  224. MOV R11, R3  
  225.  
  226. MOV R10, R2  
  227.  
  228. MOV R9, R1  
  229.  
  230. MOV R8, R0  
  231.  
  232.  
  233. ADD SP, #0X10   ; Restore PSR, PC, LR, R12  
  234.  
  235. POP {R0-R3}  
  236.  
  237. MSR PSR, R3  
  238.  
  239. PUSH {R2}  
  240.  
  241. MOV LR, R1  
  242.  
  243. MOV R12, R0  
  244.  
  245.  
  246. SUB SP, #0X1C   ; Restore R0-R3  
  247.  
  248. POP {R0-R3}  
  249.  
  250. ADD SP, #0X0C  
  251.  
  252. CPSIE I   ; Enable interrupts! NOTE: must not omit!  
  253.  
  254. POP {PC}   ; Jump to task and execute, not return 
  255.  
  256. NOP  
  257.  
  258.    
  259.  
  260.    
  261.  
  262.    
  263.  
  264. __OSRunning  
  265.  
  266.     DCD    OSRunning  
  267.  
  268.    
  269.  
  270. __OSTaskSwHook  
  271.  
  272.     DCD    OSTaskSwHook  
  273.  
  274.    
  275.  
  276. __OSIntExit  
  277.  
  278.     DCD    OSIntExit  
  279.  
  280.    
  281.  
  282. __OSIntNesting  
  283.  
  284.     DCD    OSIntNesting  
  285.  
  286.    
  287.  
  288. __OSPrioCur  
  289.  
  290.     DCD    OSPrioCur  
  291.  
  292.    
  293.  
  294. __OSPrioHighRdy  
  295.  
  296.     DCD    OSPrioHighRdy  
  297.  
  298.    
  299.  
  300. __OSTCBCur  
  301.  
  302.     DCD    OSTCBCur  
  303.  
  304.    
  305.  
  306. __OSTCBHighRdy  
  307.  
  308.     DCD    OSTCBHighRdy  
  309.  
  310.    
  311.  
  312.     END 

第二步: 到了这里,整个ucos内核就算移植好了。接下来就要建立任务了。对于任务的建立,与头文件 os_cfg.h有关。我们要在os_cfg.h设置一下有关任务的东西。

 1. os_cfg.h里面有很多开关量,对于任务里用不到的东西,比如说信号量、定时器之类的,我们可以把它关掉,以减少系统的内存占有率。对于最低优先级OS_LOWEST_PRIO和最大任务数OS_MAX_TASKS要注意一下。还有OS_TICKS_PER_SEC,关于系统的节拍,也要设置一下,一般100到200之间就可以了。

 

 2. 对于任务时钟的节拍,采用cortex-m0的SYSTick来作为节拍源,所以还要加上SysTick的异常处理函数!!!!我在main函数里面添加。

 

 3. main函数里面任务的建立。我们先建立一个闪烁的LED任务。代码如下:

 

  
  
  
  
  1. #include <stdio.h> 
  2.  
  3.    
  4.  
  5. #include "M051Series.h"  
  6.  
  7. #include "Driver/DrvGPIO.h"  
  8.  
  9. #include "Driver/DrvSYS.h"  
  10.  
  11. #include "ucos_ii.h"  
  12.  
  13.    
  14.  
  15.    
  16.  
  17. /* LED 任务相关 */  
  18.  
  19. #define LED_STK_SIZE        64  
  20.  
  21. #define TASK_LED_PRIO       10      //不要大于OS_LOWEST_PRIO  
  22.  
  23.    
  24.  
  25. OS_STK TaskLEDStk[LED_STK_SIZE];      //任务栈  
  26.  
  27.    
  28.  
  29. void task_led(void *pdata);  
  30.  
  31.    
  32.  
  33.    
  34.  
  35. /* 与开发板相关的函数定义 */  
  36.  
  37. void init_target(void);  
  38.  
  39. void init_sys_clock(void);  
  40.  
  41. void init_led(void);  
  42.  
  43. void led_on(void);  
  44.  
  45. void led_off(void);  
  46.  
  47.    
  48.  
  49.    
  50.  
  51.    
  52.  
  53. /* SysTick Exception ISR */  
  54.  
  55. void SysTick_Handler(void)  
  56.  
  57. {  
  58.  
  59.     OSIntEnter();  
  60.  
  61.     OSTimeTick();  
  62.  
  63.     OSIntExit();  
  64.  
  65. }  
  66.  
  67.    
  68.  
  69.    
  70.  
  71. /* main */  
  72.  
  73. int main()  
  74.  
  75. {  
  76.  
  77.     __disable_irq();  
  78.  
  79.     init_target();  
  80.  
  81.    
  82.  
  83.     OSInit();  
  84.  
  85.    
  86.  
  87.     OSTaskCreate( task_led, (void*)0, TaskLEDStk[LED_STK_SIZE-1], TASK_LED_PRIO );  
  88.  
  89.    
  90.  
  91.     OSStart();  
  92.  
  93.     return 0;  
  94.  
  95. }  
  96.  
  97.    
  98.  
  99.    
  100.  
  101. void task_led(void *pdata)  
  102.  
  103. {  
  104.  
  105.     (void)pdata;  
  106.  
  107.     while(1)  
  108.  
  109.     {  
  110.  
  111.         led_on();  
  112.  
  113.         OSTimeDlyHMSM(0, 0, 1, 0);  
  114.  
  115.         led_off();  
  116.  
  117.         OSTimeDlyHMSMj(0, 0, 1, 0);  
  118.  
  119.     }  
  120.  
  121. }  
  122.  
  123.    
  124.  
  125. void init_target(void)  
  126.  
  127. {  
  128.  
  129.     init_sys_clock();  
  130.  
  131.     init_led();  
  132.  
  133.     /* Note: Important */  
  134.  
  135.     SysTick_Config(DrvSYS_GetHCLKFreq()/OS_TICKS_PER_SEC-1);  //Init system tick  
  136.  
  137. }  
  138.  
  139.    
  140.  
  141.    
  142.  
  143. void init_sys_colock(void)  
  144.  
  145. {  
  146.  
  147.     UNLOCKREG();                                // Unlock the protected registers     
  148.     DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);         // Enable the 12MHz oscillator oscillation    
  149.     while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1); // Waiting for 12M Xtal stable    
  150.  
  151.     DrvSYS_SelectHCLKSource(0);  
  152.     LOCKREG();                                  // Lock the protected registers  
  153.     DrvSYS_SetClockDivider(E_SYS_HCLK_DIV, 0);  // HCLK clock frequency = HCLK clock source / (HCLK_N + 1)  
  154.  
  155. }  
  156.  
  157.    
  158.  
  159. void init_led(void)  
  160.  
  161. {  
  162.  
  163.     DrvGPIO_Open(E_PORT3, E_PIN6, E_IO_OUTPUT);  
  164.     DrvGPIO_SetBit(E_PORT3, E_PIN6);        //led 接P3.6引脚  
  165.  
  166. }  
  167.  
  168.    
  169.  
  170. void led_on(void)  
  171.  
  172. {  
  173.  
  174.     DrvGPIO_ClrBit(E_PORT3, E_PIN6);  
  175.  
  176. }  
  177.  
  178.    
  179.  
  180. void led_off(void)  
  181.  
  182. {  
  183.  
  184.     DrvGPIO_ClrBit(E_PORT3, E_PIN6);  
  185.  

到此,整个UCOS在cortex-m0就移植成功并且可以运行任务啦。。。从晚上跑到天亮,都非常稳定。

第二天,我又结合之前做过的TXT阅读器,在UCOS上也做了一个TXT电子书阅读器,也挺流畅,也很稳定。感觉很不错!

你可能感兴趣的:(嵌入式,ucos,cortex-m0)