首页 > 代码库 > S3C2416裸机开发系列十五_GCC下uCOS的移植(2)

S3C2416裸机开发系列十五_GCC下uCOS的移植(2)

S3C2416裸机开发系列十五

GCC下uCOS的移植(2)

象棋小子    1048272975

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  LED6

 

OS_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 clear

    rINTPND1 |= (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.166MHZ

    rTCFG1 &= ~(0xf << 16);

    rTCFG1 |= (0x3 << 16);  // Timer4 16分频

    rTCFG0 &= ~(0xff << 8);

    rTCFG0 |= (0 << 8); // PCLK预分频为1

    rTCNTB4 = 4166; // System Tick设1ms

    rTCON |= (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,LED2output   

    rGPECON &=~((0x03<<(LED3<<1)) | (0x03<<(LED5<<1))

                |(0x03<<(LED2<<1)));

    rGPECON |= ((0x01<<(LED3<<1))| (0x01<<(LED5<<1))

                |(0x01<<(LED2<<1)));

    // GPL13 LED4 output   

    rGPLCON &= ~(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(); // 初始化uCOS

    OSTaskCreate(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