snifer

【嵌入式】[原创]µC/OS-II嵌入式操作系统的实践新体验

0
阅读(19143)

最近都在弄Linux和Wince,这方面可能大家比较熟悉,今天就写写µC/OS-II嵌入式操作系统,与大家共勉。


主要特点

UC/OS是一个非常小巧的实时操作系统;整个代码分为内核层以及移植层,这样使得它的植性很方便。

采用抢占式调度策略,保证任务的实时性。
能够管理多达64个任务。

提供了邮箱、消息队列、信号量、内存管理、时间管理等系统服务。


µC/OS-II嵌入式操作系统全世界有数百种产品在应用:
医疗器械
移动电话
路由器
工业控制
GPS 导航系统

智能仪器


mC/OS-II的内核结构主要包括:

临界段(Critical Sections):


为了实现资源共享,一个操作系统必须提供临界段擦作的功能。
μC/OS-Ⅱ为了处理临界段代码需要关中断,处理完毕后再开中断。这使得μC/OS-Ⅱ能够避免同时有其它任务或中断服务进入临界段代码。
μC/OS-Ⅱ定义两个宏(macros)来开关中断。分别是:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。

这两个宏的定义取决于所用的微处理器,每种微处理器都有自己的OS_CPU.H文件。  

任务(task


一个任务通常是一个无限的循环:

void mytask(void *pdata)

{

  do init

     while (1) {

     do something;

     waiting;

     do something;

     }

}

μC/OS-Ⅱ可以管理多达64个任务。
保留了优先级为0、1、2、3、OS_LOWEST_PRIO-3、OS_LOWEST_PRI0-2,OS_LOWEST_PRI0-1以及OS_LOWEST_PRI0这8个任务以被将来使用。

用户可以有多达56个应用任务。必须给每个任务赋以不同的优先级。优先级号越低,任务的优先级越高。

μC/OS中的中断处理:

μC/OS中,中断服务子程序要用汇编语言来写。然而,如果用户使用的C语言编译器支持在线汇编语言的话,用户可以直接将中断服务子程序代码放在C语言的程序文件中。
用户中断服务子程序框架:                                                           
1.保存全部CPU寄存器;                   
2.调用OSIntEnter或OSIntNesting直接加1;
3.执行用户代码做中断服务;                
4.调用OSIntExit();
5.恢复所有CPU寄存器;
6.执行中断返回指令;
OSIntEnter:



void OSIntEnter (void)

{

    OS_ENTER_CRITICAL();

    OSIntNesting++;

    OS_EXIT_CRITICAL();

}

OSIntExit:


OS_ENTER_CRITICAL();

if ((--OSIntNesting | OSLockNesting) == 0) { 

OSIntExitY    = OSUnMapTbl[OSRdyGrp];

OSPrioHighRdy = (INT8U)((OSIntExitY << 3) +

                  OSUnMapTbl[OSRdyTbl[OSIntExitY]]);

     if (OSPrioHighRdy != OSPrioCur) {

       OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];

            OSCtxSwCtr++;

            OSIntCtxSw(); }

}

OS_EXIT_CRITICAL();

中断与时钟节拍

当发生中断时,首先应保护现场,将CPU寄存器入栈,再处理中断函数,然后恢复现场,将CPU寄存器出栈,最后执行中断返回。


uC/OS中提供了OSIntEnter()和OSIntExit()告诉内核进入了中断状态。

时钟节拍是一种特殊的中断,操作系统的心脏。对任务列表进行扫描,判断是否有延时任务应该处于准备就绪状态,最后进行上下文切换。


μC/OS需要用户提供周期性信号源,用于实现时间延时和确认超时。节拍率应在说10到100Hz。时钟节拍率越高,系统的额外负荷就越重。
时钟节拍的实际频率取决于用户应用程序的精度。时钟节拍源可以是专门的硬件定时器,也可以是来自50/60Hz交流电源的信号。

用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用OSStart()之后。

OSTickISR:

void OSTickISR(void)

{

    保存处理器寄存器的值;

    调用OSIntEnter()或是将OSIntNesting加1;

    调用OSTimeTick();

     调用OSIntExit();

    恢复处理器寄存器的值;

    执行中断返回指令;

}

μC/OS-Ⅱ初始化:


在调用μC/OS-Ⅱ的任何其它服务之前,μC/OS-Ⅱ要求用户首先调用系统初始化函数OSInit()。


OSInit()建立空闲任务idle task,这个任务总是处于就绪态的。空闲任务OSTaskIdle()的优先级总是设成最低,即OS_LOWEST_PRIO。

μC/OS-Ⅱ还初始化了4个空数据结构缓冲区。

μC/OS-Ⅱ的启动:

q多任务的启动是用户通过调用OSStart()实现的。然而,启动μC/OS-Ⅱ之前,用户至少要建立一个应用任务。


  OSInit();     /* 初始化uC/OS-II*/

  ……

  调用OSTaskCreate()或OSTaskCreateExt();

  ……

  OSStart();   /*开始多任务调度!永不返回 */

这样就完成了μC/OS-Ⅱ的初始化的介绍,这方面我还准备在写几篇,多个操作系统比较大家才能有更深入的体会,夏天真的来了,好热。