4. uCOS配置

uCOS是可裁减实时操作系统,可以根据实际的应用对内核未使用到的功能进行裁减,以进一步节省系统宝贵的硬件资源,通常可用的uCOS-II内核代码在6K~26K,这在uCOS-II配置文件os_cfg.h中进行配置,这个配置文件在源码目录为os_cfg_r.h,从目录中拷贝添加到uCOS/uCOS-II/Cfg目录中,并重命名为os_cfg.h。

  1. #ifndef OS_CFG_H
  2. #define OS_CFG_H
  3. /* ---------------------------- MISCELLANEOUS -------------------------- */
  4. #define OS_CFG_APP_HOOKS_EN 1u /* Enable/Disable application specific hooks*/
  5. #define OS_CFG_ARG_CHK_EN 1u /*Enable/Disable argument checking*/
  6. #define OS_CFG_CALLED_FROM_ISR_CHK_EN 1u /* check for called from ISR*/
  7. #define OS_CFG_DBG_EN 1u /* Enable (1) debugcode/variables */
  8. #define OS_CFG_ISR_POST_DEFERRED_EN 0u /* Enable/Disable DeferredISR posts */
  9. #define OS_CFG_OBJ_TYPE_CHK_EN 1u /* Enable/Disable object typechecking*/
  10. #define OS_CFG_TS_EN 1u /* Enable/Disable timestamping*/
  11. #define OS_CFG_PEND_MULTI_EN 1u /* code generation formulti-pend feature */
  12. #define OS_CFG_PRIO_MAX 32u /* maximum number of taskpriorities */
  13. #define OS_CFG_SCHED_LOCK_TIME_MEAS_EN 1u /* code to measure schedulerlock time */
  14. #define OS_CFG_SCHED_ROUND_ROBIN_EN 1u /* code for Round-Robinscheduling */
  15. #define OS_CFG_STK_SIZE_MIN 64u /* Minimum allowable taskstack size */
  16. /* ----------------------------- EVENT FLAGS --------------------------- */
  17. #define OS_CFG_FLAG_EN 1u /* Enable/Disable code forEVENT FLAGS*/
  18. #define OS_CFG_FLAG_DEL_EN 0u /* Include code forOSFlagDel()*/
  19. #define OS_CFG_FLAG_MODE_CLR_EN 0u /* code for Wait on ClearEVENT FLAGS*/
  20. #define OS_CFG_FLAG_PEND_ABORT_EN 0u /* Include code forOSFlagPendAbort()*/
  21. /* -------------------------- MEMORY MANAGEMENT ------------------------ */
  22. #define OS_CFG_MEM_EN 1u /* code generation for MEMORYMANAGER */
  23. /* --------------------- MUTUAL EXCLUSION SEMAPHORES ------------------- */
  24. #define OS_CFG_MUTEX_EN 1u /* code generation for MUTEX*/
  25. #define OS_CFG_MUTEX_DEL_EN 0u /* code for OSMutexDel()*/
  26. #define OS_CFG_MUTEX_PEND_ABORT_EN 0u /* code for OSMutexPendAbort()*/
  27. /* --------------------------- MESSAGE QUEUES -------------------------- */
  28. #define OS_CFG_Q_EN 1u /* code generation for QUEUES*/
  29. #define OS_CFG_Q_DEL_EN 0u /* Include code forOSQDel()*/
  30. #define OS_CFG_Q_FLUSH_EN 0u /* Include code forOSQFlush()*/
  31. #define OS_CFG_Q_PEND_ABORT_EN 1u /* Include code forOSQPendAbort()*/
  32. /* ----------------------------- SEMAPHORES ---------------------------- */
  33. #define OS_CFG_SEM_EN 1u /* code generation for SEMAPHORES */
  34. #define OS_CFG_SEM_DEL_EN 0u /* Include code forOSSemDel()*/
  35. #define OS_CFG_SEM_PEND_ABORT_EN 1u /* Include code forOSSemPendAbort()*/
  36. #define OS_CFG_SEM_SET_EN 1u /* Include code forOSSemSet()*/
  37. /* -------------------------- TASK MANAGEMENT -------------------------- */
  38. #define OS_CFG_STAT_TASK_EN 1u /* Enable/Disable thestatistics task*/
  39. #define OS_CFG_STAT_TASK_STK_CHK_EN 1u /* Check task stacks fromstatistic task*/
  40. #define OS_CFG_TASK_CHANGE_PRIO_EN 1u /* Include code forOSTaskChangePrio()*/
  41. #define OS_CFG_TASK_DEL_EN 0u /* Include code forOSTaskDel()*/
  42. #define OS_CFG_TASK_Q_EN 1u /* Include code forOSTaskQXXXX()*/
  43. #define OS_CFG_TASK_Q_PEND_ABORT_EN 0u /* Include code forOSTaskQPendAbort()*/
  44. #define OS_CFG_TASK_PROFILE_EN 1u /* variables in OS_TCB forprofiling */
  45. #define OS_CFG_TASK_REG_TBL_SIZE 1u /* Number of task specificregisters*/
  46. #define OS_CFG_TASK_SEM_PEND_ABORT_EN 1u /* Include code forOSTaskSemPendAbort()*/
  47. #define OS_CFG_TASK_SUSPEND_EN 1u /* OSTaskSuspend() and OSTaskResume()*/
  48. /* -------------------------- TIME MANAGEMENT -------------------------- */
  49. #define OS_CFG_TIME_DLY_HMSM_EN 1u /* Include code forOSTimeDlyHMSM()*/
  50. #define OS_CFG_TIME_DLY_RESUME_EN 0u /* Include code forOSTimeDlyResume()*/
  51. /* ------------------- TASK LOCAL STORAGE MANAGEMENT ------------------- */
  52. #define OS_CFG_TLS_TBL_SIZE 0u /* code for Task LocalStorage (TLS) registers */
  53. /* ------------------------- TIMER MANAGEMENT -------------------------- */
  54. #define OS_CFG_TMR_EN 1u /*Enable/Disablecode generation for TIMERS */
  55. #define OS_CFG_TMR_DEL_EN 0u /*Enable/Disable code generation for OSTmrDel()*/
  56. #endif

5. 用户代码

用户需要提供一个周期性定时中断作为uCOS-II的运行Tick,每个Tick需调用OSTimeTick()来让内核管理时钟节拍,在s3c2416用定时器4产生这个系统Tick。在main()函数中需调用OSInit()初始化内核,创建任务后,再调用OSStart()把cpu管理权交给内核。内核即可正确地管理用户的任务。

  1. #include "s3c2416.h"
  2. #include "Exception.h"
  3. #include "ucos_ii.h"
  4. // IO port for controling LEDs
  5. #define LED2 (13) // GPE13 LED2
  6. #define LED3 (11) // GPE11 LED3
  7. #define LED4 (13) // GPL13 LED4
  8. #define LED5 (12) // GPE12 LED5
  9. #define LED6 (2) // GPG2 LED6
  10. OS_STK TaskStartStk[TASK_START_STK_SIZE];
  11. OS_STK Task1Stk[TASK1_STK_SIZE];
  12. OS_STK Task2Stk[TASK2_STK_SIZE];
  13. OS_STK Task3Stk[TASK3_STK_SIZE];
  14. static void Timer4_IRQ(void)
  15. {
  16. OSTimeTick(); // uCOS时钟节拍管理
  17. rSRCPND1 |= (0x01 <<INT_TIMER4); // write 1 to clear
  18. rINTPND1 |= (0x01 <<INT_TIMER4); // write 1 to clear
  19. }
  20. void Timer4_Start()
  21. {
  22. rTCON |= (0x1 << 20); // 定时器开启
  23. }
  24. void Timer4_Stop()
  25. {
  26. rTCON &= ~(0x1 << 20);// 定时器停止
  27. }
  28. void Timer4_Init()
  29. {
  30. // 定时器4时钟频率为PCLK(66.66666M)/(0+1)/16=4.166MHZ
  31. rTCFG1 &= ~(0xf << 16);
  32. rTCFG1 |= (0x3 << 16); // Timer4 16分频
  33. rTCFG0 &= ~(0xff << 8);
  34. rTCFG0 |= (0 << 8); // PCLK预分频为1
  35. rTCNTB4 = 4166; // System Tick设1ms
  36. rTCON |= (0x1 << 21); // 更新计数值
  37. rTCON &= ~(0x1 << 21);// 清除
  38. rTCON |= (0x1 << 22); // 自动重装载
  39. IRQ_Register(INT_TIMER4,Timer4_IRQ); // 注册Timer4中断函数
  40. rINTMOD1 &= ~(1 <<INT_TIMER4); // Timer4 IRQ 模式
  41. rINTMSK1 &= ~(1 <<INT_TIMER4); // Timer4开中断
  42. }
  43. void Gpio_LED2(unsigned char On)
  44. {
  45. if (!On) {
  46. rGPEDAT &=~(1<<LED2);
  47. } else {
  48. rGPEDAT |= (1<<LED2);
  49. }
  50. }
  51. void Gpio_LED3(unsigned char On)
  52. {
  53. if (!On) {
  54. rGPEDAT &=~(1<<LED3);
  55. } else {
  56. rGPEDAT |= (1<<LED3);
  57. }
  58. }
  59. void Gpio_LED4(unsigned char On)
  60. {
  61. if (!On) {
  62. rGPLDAT &=~(1<<LED4);
  63. } else {
  64. rGPLDAT |= (1<<LED4);
  65. }
  66. }
  67. void Gpio_LED5(unsigned char On)
  68. {
  69. if (!On) {
  70. rGPEDAT &=~(1<<LED5);
  71. } else {
  72. rGPEDAT |= (1<<LED5);
  73. }
  74. }
  75. void Gpio_Init()
  76. {
  77. // GPE11,12,13 LED3,LED5,LED2output
  78. rGPECON &=~((0x03<<(LED3<<1)) | (0x03<<(LED5<<1))
  79. |(0x03<<(LED2<<1)));
  80. rGPECON |= ((0x01<<(LED3<<1))| (0x01<<(LED5<<1))
  81. |(0x01<<(LED2<<1)));
  82. // GPL13 LED4 output
  83. rGPLCON &= ~(0x03 <<(LED4<<1));
  84. rGPLCON |= (0x01 <<(LED4<<1));
  85. }
  86. void Task3(void *pdata)
  87. {
  88. (void)pdata;
  89. while (1) {
  90. Gpio_LED5(1);
  91. OSTimeDly(2000); // LED5 2000ms闪烁
  92. Gpio_LED5(0);
  93. OSTimeDly(2000); // LED52000ms闪烁
  94. }
  95. }
  96. void Task2(void *pdata)
  97. {
  98. (void)pdata;
  99. while (1) {
  100. Gpio_LED4(1);
  101. OSTimeDly(1500); // LED41500ms闪烁
  102. Gpio_LED4(0);
  103. OSTimeDly(1500); // LED41500ms闪烁
  104. }
  105. }
  106. void Task1(void *pdata)
  107. {
  108. (void)pdata;
  109. while (1) {
  110. Gpio_LED3(1);
  111. OSTimeDly(1000); // LED31000ms闪烁
  112. Gpio_LED3(0);
  113. OSTimeDly(1000); // LED31000ms闪烁
  114. }
  115. }
  116. void TaskStart(void *pdata)
  117. {
  118. (void)pdata;
  119. Gpio_Init();
  120. Timer4_Init();
  121. Timer4_Start();
  122. OSTaskCreate(Task1, (void *)0,&Task1Stk[TASK1_STK_SIZE - 1], Task1Prio);
  123. OSTaskCreate(Task2, (void *)0,&Task2Stk[TASK2_STK_SIZE - 1], Task2Prio);
  124. OSTaskCreate(Task3, (void *)0,&Task3Stk[TASK3_STK_SIZE - 1], Task3Prio);
  125. while (1) {
  126. Gpio_LED2(1);
  127. OSTimeDly(500); // LED2 500ms闪烁
  128. Gpio_LED2(0);
  129. OSTimeDly(500); // LED2 500ms闪烁
  130. }
  131. }
  132. int main (void)
  133. {
  134. OSInit(); // 初始化uCOS
  135. OSTaskCreate(TaskStart, (void *)0,&TaskStartStk[TASK_START_STK_SIZE-1], TaskStartPrio);
  136. OSStart();// 开始uCOS调度
  137. return 0;
  138. }

uCOS-II通过app_cfg.h文件来配置任务的栈、优先级等,app_cfg.h的内容如下:

  1. #ifndef APP_CFG_MODULE_PRESENT
  2. #define APP_CFG_MODULE_PRESENT
  3. // 任务TaskStart的栈及优先级分配
  4. #define TASK_START_STK_SIZE 256u
  5. #define TaskStartPrio 10
  6. // 任务Task1的栈及优先级分配
  7. #define TASK1_STK_SIZE 256u
  8. #define Task1Prio 11
  9. // 任务Task2的栈及优先级分配
  10. #define TASK2_STK_SIZE 256u
  11. #define Task2Prio 12
  12. // 任务Task3的栈及优先级分配
  13. #define TASK3_STK_SIZE 256u
  14. #define Task3Prio 13
  15. // 定时器优先级配置
  16. #define OS_TASK_TMR_PRIO (OS_LOWEST_PRIO - 2)
  17. #endif

uCOS-II+uCGUI效果图: 15_GCC下uCOS的移植(2) - 图1 15_GCC下uCOS的移植(2) - 图2

6. 附录

本篇uCOS接口部分的移植对于ARM7、ARM9都是适用的,不同型号的cpu只需加入定时器产生系统Tick,通过调用OSTimeTick()来让内核管理时钟节拍。总的来说,熟悉一款操作系统的工作原理,了解其任务调度、信号量同步、临界区访问等概念,对学习其它操作系统、多线程编程等均是有很较大的帮助的。 uCOS_GCC,GCC下uCOS-II的移植工程,可直接make http://pan.baidu.com/s/1o6NTaVw uCOS_MDK,MDK下uCOS-II的移植工程 http://pan.baidu.com/s/1jGjzE0A