4. uCOS配置
uCOS是可裁减实时操作系统,可以根据实际的应用对内核未使用到的功能进行裁减,以进一步节省系统宝贵的硬件资源,通常可用的uCOS-II内核代码在6K~26K,这在uCOS-II配置文件os_cfg.h中进行配置,这个配置文件在源码目录为os_cfg_r.h,从目录中拷贝添加到uCOS/uCOS-II/Cfg目录中,并重命名为os_cfg.h。
#ifndef OS_CFG_H#define OS_CFG_H/* ---------------------------- MISCELLANEOUS -------------------------- */#define OS_CFG_APP_HOOKS_EN 1u /* Enable/Disable application specific hooks*/#define OS_CFG_ARG_CHK_EN 1u /*Enable/Disable argument checking*/#define OS_CFG_CALLED_FROM_ISR_CHK_EN 1u /* check for called from ISR*/#define OS_CFG_DBG_EN 1u /* Enable (1) debugcode/variables */#define OS_CFG_ISR_POST_DEFERRED_EN 0u /* Enable/Disable DeferredISR posts */#define OS_CFG_OBJ_TYPE_CHK_EN 1u /* Enable/Disable object typechecking*/#define OS_CFG_TS_EN 1u /* Enable/Disable timestamping*/#define OS_CFG_PEND_MULTI_EN 1u /* code generation formulti-pend feature */#define OS_CFG_PRIO_MAX 32u /* maximum number of taskpriorities */#define OS_CFG_SCHED_LOCK_TIME_MEAS_EN 1u /* code to measure schedulerlock time */#define OS_CFG_SCHED_ROUND_ROBIN_EN 1u /* code for Round-Robinscheduling */#define OS_CFG_STK_SIZE_MIN 64u /* Minimum allowable taskstack size *//* ----------------------------- EVENT FLAGS --------------------------- */#define OS_CFG_FLAG_EN 1u /* Enable/Disable code forEVENT FLAGS*/#define OS_CFG_FLAG_DEL_EN 0u /* Include code forOSFlagDel()*/#define OS_CFG_FLAG_MODE_CLR_EN 0u /* code for Wait on ClearEVENT FLAGS*/#define OS_CFG_FLAG_PEND_ABORT_EN 0u /* Include code forOSFlagPendAbort()*//* -------------------------- MEMORY MANAGEMENT ------------------------ */#define OS_CFG_MEM_EN 1u /* code generation for MEMORYMANAGER *//* --------------------- MUTUAL EXCLUSION SEMAPHORES ------------------- */#define OS_CFG_MUTEX_EN 1u /* code generation for MUTEX*/#define OS_CFG_MUTEX_DEL_EN 0u /* code for OSMutexDel()*/#define OS_CFG_MUTEX_PEND_ABORT_EN 0u /* code for OSMutexPendAbort()*//* --------------------------- MESSAGE QUEUES -------------------------- */#define OS_CFG_Q_EN 1u /* code generation for QUEUES*/#define OS_CFG_Q_DEL_EN 0u /* Include code forOSQDel()*/#define OS_CFG_Q_FLUSH_EN 0u /* Include code forOSQFlush()*/#define OS_CFG_Q_PEND_ABORT_EN 1u /* Include code forOSQPendAbort()*//* ----------------------------- SEMAPHORES ---------------------------- */#define OS_CFG_SEM_EN 1u /* code generation for SEMAPHORES */#define OS_CFG_SEM_DEL_EN 0u /* Include code forOSSemDel()*/#define OS_CFG_SEM_PEND_ABORT_EN 1u /* Include code forOSSemPendAbort()*/#define OS_CFG_SEM_SET_EN 1u /* Include code forOSSemSet()*//* -------------------------- TASK MANAGEMENT -------------------------- */#define OS_CFG_STAT_TASK_EN 1u /* Enable/Disable thestatistics task*/#define OS_CFG_STAT_TASK_STK_CHK_EN 1u /* Check task stacks fromstatistic task*/#define OS_CFG_TASK_CHANGE_PRIO_EN 1u /* Include code forOSTaskChangePrio()*/#define OS_CFG_TASK_DEL_EN 0u /* Include code forOSTaskDel()*/#define OS_CFG_TASK_Q_EN 1u /* Include code forOSTaskQXXXX()*/#define OS_CFG_TASK_Q_PEND_ABORT_EN 0u /* Include code forOSTaskQPendAbort()*/#define OS_CFG_TASK_PROFILE_EN 1u /* variables in OS_TCB forprofiling */#define OS_CFG_TASK_REG_TBL_SIZE 1u /* Number of task specificregisters*/#define OS_CFG_TASK_SEM_PEND_ABORT_EN 1u /* Include code forOSTaskSemPendAbort()*/#define OS_CFG_TASK_SUSPEND_EN 1u /* OSTaskSuspend() and OSTaskResume()*//* -------------------------- TIME MANAGEMENT -------------------------- */#define OS_CFG_TIME_DLY_HMSM_EN 1u /* Include code forOSTimeDlyHMSM()*/#define OS_CFG_TIME_DLY_RESUME_EN 0u /* Include code forOSTimeDlyResume()*//* ------------------- TASK LOCAL STORAGE MANAGEMENT ------------------- */#define OS_CFG_TLS_TBL_SIZE 0u /* code for Task LocalStorage (TLS) registers *//* ------------------------- TIMER MANAGEMENT -------------------------- */#define OS_CFG_TMR_EN 1u /*Enable/Disablecode generation for TIMERS */#define OS_CFG_TMR_DEL_EN 0u /*Enable/Disable code generation for OSTmrDel()*/#endif
5. 用户代码
用户需要提供一个周期性定时中断作为uCOS-II的运行Tick,每个Tick需调用OSTimeTick()来让内核管理时钟节拍,在s3c2416用定时器4产生这个系统Tick。在main()函数中需调用OSInit()初始化内核,创建任务后,再调用OSStart()把cpu管理权交给内核。内核即可正确地管理用户的任务。
#include "s3c2416.h"#include "Exception.h"#include "ucos_ii.h"// IO port for controling LEDs#define LED2 (13) // GPE13 LED2#define LED3 (11) // GPE11 LED3#define LED4 (13) // GPL13 LED4#define LED5 (12) // GPE12 LED5#define LED6 (2) // GPG2 LED6OS_STK TaskStartStk[TASK_START_STK_SIZE];OS_STK Task1Stk[TASK1_STK_SIZE];OS_STK Task2Stk[TASK2_STK_SIZE];OS_STK Task3Stk[TASK3_STK_SIZE];static void Timer4_IRQ(void){OSTimeTick(); // uCOS时钟节拍管理rSRCPND1 |= (0x01 <<INT_TIMER4); // write 1 to clearrINTPND1 |= (0x01 <<INT_TIMER4); // write 1 to clear}void Timer4_Start(){rTCON |= (0x1 << 20); // 定时器开启}void Timer4_Stop(){rTCON &= ~(0x1 << 20);// 定时器停止}void Timer4_Init(){// 定时器4时钟频率为PCLK(66.66666M)/(0+1)/16=4.166MHZrTCFG1 &= ~(0xf << 16);rTCFG1 |= (0x3 << 16); // Timer4 16分频rTCFG0 &= ~(0xff << 8);rTCFG0 |= (0 << 8); // PCLK预分频为1rTCNTB4 = 4166; // System Tick设1msrTCON |= (0x1 << 21); // 更新计数值rTCON &= ~(0x1 << 21);// 清除rTCON |= (0x1 << 22); // 自动重装载IRQ_Register(INT_TIMER4,Timer4_IRQ); // 注册Timer4中断函数rINTMOD1 &= ~(1 <<INT_TIMER4); // Timer4 IRQ 模式rINTMSK1 &= ~(1 <<INT_TIMER4); // Timer4开中断}void Gpio_LED2(unsigned char On){if (!On) {rGPEDAT &=~(1<<LED2);} else {rGPEDAT |= (1<<LED2);}}void Gpio_LED3(unsigned char On){if (!On) {rGPEDAT &=~(1<<LED3);} else {rGPEDAT |= (1<<LED3);}}void Gpio_LED4(unsigned char On){if (!On) {rGPLDAT &=~(1<<LED4);} else {rGPLDAT |= (1<<LED4);}}void Gpio_LED5(unsigned char On){if (!On) {rGPEDAT &=~(1<<LED5);} else {rGPEDAT |= (1<<LED5);}}void Gpio_Init(){// GPE11,12,13 LED3,LED5,LED2outputrGPECON &=~((0x03<<(LED3<<1)) | (0x03<<(LED5<<1))|(0x03<<(LED2<<1)));rGPECON |= ((0x01<<(LED3<<1))| (0x01<<(LED5<<1))|(0x01<<(LED2<<1)));// GPL13 LED4 outputrGPLCON &= ~(0x03 <<(LED4<<1));rGPLCON |= (0x01 <<(LED4<<1));}void Task3(void *pdata){(void)pdata;while (1) {Gpio_LED5(1);OSTimeDly(2000); // LED5 2000ms闪烁Gpio_LED5(0);OSTimeDly(2000); // LED52000ms闪烁}}void Task2(void *pdata){(void)pdata;while (1) {Gpio_LED4(1);OSTimeDly(1500); // LED41500ms闪烁Gpio_LED4(0);OSTimeDly(1500); // LED41500ms闪烁}}void Task1(void *pdata){(void)pdata;while (1) {Gpio_LED3(1);OSTimeDly(1000); // LED31000ms闪烁Gpio_LED3(0);OSTimeDly(1000); // LED31000ms闪烁}}void TaskStart(void *pdata){(void)pdata;Gpio_Init();Timer4_Init();Timer4_Start();OSTaskCreate(Task1, (void *)0,&Task1Stk[TASK1_STK_SIZE - 1], Task1Prio);OSTaskCreate(Task2, (void *)0,&Task2Stk[TASK2_STK_SIZE - 1], Task2Prio);OSTaskCreate(Task3, (void *)0,&Task3Stk[TASK3_STK_SIZE - 1], Task3Prio);while (1) {Gpio_LED2(1);OSTimeDly(500); // LED2 500ms闪烁Gpio_LED2(0);OSTimeDly(500); // LED2 500ms闪烁}}int main (void){OSInit(); // 初始化uCOSOSTaskCreate(TaskStart, (void *)0,&TaskStartStk[TASK_START_STK_SIZE-1], TaskStartPrio);OSStart();// 开始uCOS调度return 0;}
uCOS-II通过app_cfg.h文件来配置任务的栈、优先级等,app_cfg.h的内容如下:
#ifndef APP_CFG_MODULE_PRESENT#define APP_CFG_MODULE_PRESENT// 任务TaskStart的栈及优先级分配#define TASK_START_STK_SIZE 256u#define TaskStartPrio 10// 任务Task1的栈及优先级分配#define TASK1_STK_SIZE 256u#define Task1Prio 11// 任务Task2的栈及优先级分配#define TASK2_STK_SIZE 256u#define Task2Prio 12// 任务Task3的栈及优先级分配#define TASK3_STK_SIZE 256u#define Task3Prio 13// 定时器优先级配置#define OS_TASK_TMR_PRIO (OS_LOWEST_PRIO - 2)#endif
uCOS-II+uCGUI效果图:

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
