ucosii内核总结

博主最近一直在看有关ucosii的代码,并将其成功移植到了正点原子STM32F103的开发板上。颇有一些收获,于是将其总结下来与大家一起分享。

本文不会向你介绍怎么移植ucos(在STM32上移植ucos的资料多的很,大家可以去自己亲自体验一下),本文只会对ucos的一些内核进行剖析。

严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,中断与时间管理,内存管理和任务间的通信和同步等基本功能,所以本文就基于这些内容向大家认真剖析ucosii的内核代码。

一、时间管理

首先就是时间管理,博主首先在这里把时钟放在了首位。因为时钟相对于处理器来说相当于心跳,我们在裸机开发的时候都需要使能系统时钟与外设时钟,μC/OS需要用户提供周期性信号源,用于
实现时间延时和确认超时。该周期性节拍可以通过os_cfg.h来进行配置,该节拍越快,实时性越好但CPU负载越重,该节拍越慢,实时性会变差但CPU负载会轻,所以我们需要根据自己的芯片以及所使用的场景来合理设置时钟节拍,一般设置为 10-100hz之间。

ucos时钟管理软件的核心代码便是OSTickISR(),该函数是一个定时中断函数,每隔一个固定的时钟节拍运行一次,该函数会调用OSTimeTick()函数,OSTimeTick()的主要功能便是检查每个任务的延时。STM32使用的是嘀嗒定时器产生的定时中断,作为ucos的时钟节拍。

二、任务调度

任务调度的含义便是指根据一定的约束规定,将CPU分配给符合条件的任务使用。约束规则又称为调度算法。而ucos的调度算法便是占先式多任务实时内核

ucos使用任务就绪表来存储任务的优先级以及就绪状态。

 ucos的任务调度函数有OSSched()与OSIntExt(),ucosii中任务调度的主要功能就是在任务就绪表中找到优先级最高的那一个,并进行上下文切换。ucos的任务调度很简单就是一个简单的查表法。
任务级调度是在OSSched()中完成的                                        

中断级调度是在OSIntExt()中完成的

任务切换

任务切换的主要功能便是保存旧任务的CPU现场至堆栈中,然后获得新任务的堆栈指针,运行新任务代码。

任务级的任务切换函数是        OS_TASK_SW()     该函数的主要功能为将被挂起任务的寄存器内容入栈;将较高优先级任务的寄存器内容出栈,恢复到硬件寄存器中。
中断级的任务切换函数        OSIntExit()        该函数调用了OSIntCtxSw()进行任务切换。退出中断后先不着急返回原来的程序,先检查是否有更高优先级的任务,如果有则进行切换。

使用OSIntCtxSw()的原因是

1、因为中断前一半的任务切换工作,即CPU寄存器入栈,已经在前面做完了;
2、需要保证所有被挂起任务的栈结构是一样的;

三、任务管理

ucos的任务管理功能有        创建任务、 删除任务、修改任务的优先级、挂起和恢复任务、获得一个任务的有关信息等

 任务控制块 OS_TCB是描述一个任务的核心数据结构,存放了它的各种管理信息,包括任务堆栈指针,任务的状态、优先级,任务链表指针等;

任务管理的功能需要使用到任务控制块。

函数名        功能
OSTaskCreate()创建任务
OSTaskDel()删除一个任务,从任务控制块中删除
OSTaskChangePrio()修改任务的优先级
OSTaskSuspend()挂起一个任务
OSTaskResume()恢复一个任务
OSTaskQuery()获取任务的有关信息

 四、中断管理

ucos开关中断一工有三种方式,一般我们默认使用方式三。

ucos的中断管理非常简单,只需要调用两个函数即可。

OSIntEnter()与OSIntExit()        这两个函数只能在中断中使用,不能在任务级场景下调用,移植时要根据处理器变化进行修改。

用户中断ISR框架

OSIntEnter()的意义        将中断嵌套层数      OSIntNesting 加1;

OSIntExit()的意义        判断中断退出后有无更高优先级的任务,并进行切换。

五、内存管理

        首先要认清ucos管理的是哪一部分内存,下图是嵌入式中堆和栈的定义。

 堆

程序员自己申请,自己释放 例如 malloc()、free()、new()、delete()

 栈

编译器自动申请释放,例如局部变量、函数的参数值

        Ucosii的内存管理全部是针对堆的。STM32中栈的增长方向是由高地址到低地址,堆的增长            方式是由低地址到高地址。

        ucosii的内存管理代码用到了内存控制块(MCB)

        

ucos的存储管理使用的是固定分区的存储管理方法,这样可以解决因为malloc和free而导致的内存碎片问题。

      内存管理的库函数

  1. 创建内存分区   OSMemCreate()        //初始化内存分区
  2. 分配内存块       OSMemGet()            //从内存分区中分配内存   按块获取内存
  3. 释放内存块       OSMemPut()            //从内存分区在释放内存   按块释放内存

六、任务间通讯与同步

        (一)、同步和互斥(低级通讯)

        临界区      信号量

        临界区:采用关中断,开中断

        代码: OS_ENTER_CRITICAL()           OS_EXIT_CRITICAL()          //必须成对出现

        信号量:

        1、实现对共享资源的互斥访问。       

        2、实现任务间的行为同步

        库函数有:

        信号量创建OSSemCreate()               
        等待信号量(带阻塞)OSSemPend()(类似P原语)
        发送信号量 OSSemPost()(类似V原语)                
        等待信号量(无阻塞)OSSemAccept()
        查询信号量 OSSemQuery()

                                信号量只能传递状态,整数值等控制信息,不够高级

         (二)、任务间通讯(高级通讯)

               共享内存、 邮箱、消息队列 

              uc/osIi中所有的通讯信号都被看成是事件,uc/osii 通过事件控制块管理每一个具体                          事 件。使用两个链表,空闲链表和使用链表。

                 邮箱:可以看成是带消息的信号量,包含msg的地址。

                 邮箱的状态,

                 满的状态:邮箱包含非空指针型变量

                 空的状态:邮箱的内容为空指针NULL

                  库函数:

                 邮箱创建、等待邮箱中的消息、发送消息至邮箱、无等待的请求邮箱中消息

                 查询邮箱的状态

                消息队列:一个消息队列可以容纳多个不同的消息,可以将其看成是由多个邮箱组成的                  数组,只不过公用一个等待任务列表

               消息队列使用专门的队列控制块,库函数功能与信号量邮箱等基本一致。

七、总结

        以上便是博主自己总结的ucosii操作系统的内核实现原理,本文写的比较简陋仓促,疏                    误之处殷切希望得到大家的批评指正,谢谢。

  参考资料:正点原子STM32F1光盘/ A盘/软件资料/ucosii 资料。

  • 4
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值