嵌入式系统学习笔记【华电】——《第五章 实时操作系统μC/OS-II》

第五章 实时操作系统μC/OS-II

1、μC/OS-II概述

μC/OS:微控制器操作系统。其性能特点:
(1)开源
(2)可移植
(3)可固化
(4)可裁剪

(5)…

2、任务管理

创建任务: O S T a s k C r e a t e ( ) 、 O S T a s k C r e a t e E x t ( ) OSTaskCreate()、OSTaskCreateExt() OSTaskCreate()OSTaskCreateExt()
主函数是无限循环。
删除任务: O S T a s k D e l ( ) OSTaskDel() OSTaskDel(),只是内核看不到了而已
创建空闲任务: O S T a s k I d l e ( ) OSTaskIdle() OSTaskIdle(),任务优先级最低

64个任务,优先级从高到低: [ 0 , 1 , . . . , O S _ L O W E S T _ P R I O ] [0,1,...,OS\_LOWEST\_PRIO] [0,1,...,OS_LOWEST_PRIO],也是任务的标识号,其中 O S _ L O W E S T _ P R I O OS\_LOWEST\_PRIO OS_LOWEST_PRIO的值为63。用户可用的只有56个任务。

任务控制块(TCB),用来存放各种管理信息。
TCB链表:空闲链表、使用链表(双向)。

任务状态:
(1)休眠:内核不可见
(2)就绪
(3)运行
(4)等待
(5)中断:中断服务程序ISR接管了CPU
状态转换图:
嵌入式系统学习笔记【华电】——《第五章 实时操作系统μC/OS-II》_第1张图片
任务就绪表
任务的优先级数值可以写成8位二进制的形式,因为不会超过63,所以最高的两位用不到。
⊠ ⊠ { □ □ □ } { □ □ □ } \boxtimes\boxtimes\{\Box\Box\Box\}\{\Box\Box\Box\} {}{}
任务就绪表由8位的组号 O s R d y G r p OsRdyGrp OsRdyGrp和就绪表数组 O s R d y T b l [   ] OsRdyTbl[\ ] OsRdyTbl[ ]组成。其中,最低的三优先级数值的低三位表示组内编号,中间三位表示组号。
很容易得出如下的推导,
{ p r i o / 8 = 组 号 p r i o % 8 = 组 内 编 号 组 号 × 8 + 组 内 编 号 = p r i o \begin{cases} prio/8=组号 \\[2ex] prio\%8=组内编号 \\[2ex] 组号\times 8+组内编号=prio \end{cases} prio/8=prio%8=×8+=prio

(1)任务进入就绪态的操作
O s R d y G r p   ∣ = O s M a p T b l [ p r i o ≫ 3 ] O s R d y T b l [ p r i o ≫ 3 ]   ∣ = O s M a p T b l [ p r i o   &   0 x 07 ] OsRdyGrp\ |=OsMapTbl[prio\gg3] \\[2ex] OsRdyTbl[prio\gg3]\ |=OsMapTbl[prio\ \&\ 0x07] OsRdyGrp =OsMapTbl[prio3]OsRdyTbl[prio3] =OsMapTbl[prio & 0x07]
(2)任务脱离就绪态的操作
r e t = ( O s R d y T b l [ p r i o ≫ 3 ]   & = ! O s M a p T b l [ p r i o   &   0 x 07 ] ) i f ( r e t = = 0 )        { O s R d y G r p   & = ! O s M a p T b l [ p r i o ≫ 3 ] } ret=(OsRdyTbl[prio\gg3]\ \&=!OsMapTbl[prio\ \&\ 0x07]) \\[2ex] if(ret==0)\ \\[1ex] \ \ \ \ \{OsRdyGrp\ \&=!OsMapTbl[prio\gg3] \} ret=(OsRdyTbl[prio3] &=!OsMapTbl[prio & 0x07])if(ret==0)     {OsRdyGrp &=!OsMapTbl[prio3]}

任务的调度
可抢占实施多任务操作系统,每次都运行当前就绪队列中优先级最高的任务,一般使用 O S S c h e d ( ) OSSched() OSSched()函数。
y = O s U n M a p T b l [ O s R d y G r p ] x = O s U n M a p T b l [ O s R d y T b l [ y ] ] p r i o = ( y ≪ 3 ) + x y=OsUnMapTbl[OsRdyGrp]\\[2ex] x=OsUnMapTbl[OsRdyTbl[y]]\\[2ex] prio=(y\ll3)+x y=OsUnMapTbl[OsRdyGrp]x=OsUnMapTbl[OsRdyTbl[y]]prio=(y3)+x

任务切换: O S _ T A S K _ S W ( ) OS\_TASK\_SW() OS_TASK_SW()
(1)保护现场(当前)
(2)恢复新任务的现场
(3)执行中断返回指令
(4)执行新任务

操作 函数
创建任务 O S T a s k C r e a t e ( ) OSTaskCreate() OSTaskCreate()
申请堆栈空间 O S _ S T K    x x x [   ] OS\_STK\ \ xxx[\ ] OS_STK  xxx[ ] m a l l o c ( ) malloc() malloc()
删除任务 O S T a s k D e l ( ) OSTaskDel() OSTaskDel()
改变优先级 O S T a s k C h a n g e P r i o ( ) OSTaskChangePrio() OSTaskChangePrio()
任务查询 O S T a s k Q u e r y ( ) OSTaskQuery() OSTaskQuery()
挂起 O S T a s k S u s p e n d ( ) OSTaskSuspend() OSTaskSuspend()
恢复 O S T a s k R e s u m e ( ) OSTaskResume() OSTaskResume()

3、中断和时间管理

CPU响应中断的条件:
(1)至少有一个中断源
(2)系统允许中断,且未屏蔽此信号

进入中断服务程序(ISR)的过程:
(1)保存CPU寄存器的值
(2) O s I n t E n t e r ( ) OsIntEnter() OsIntEnter()
(3)中断服务
(4) O s I n t E x i t ( ) OsIntExit() OsIntExit()
(5)恢复CPU寄存器的值
(6)执行中断返回指令

时钟节拍也是一种特殊的中断。
O S S t a r t ( ) OSStart() OSStart()之后再开启时钟节拍器。

void main(void)
{
    OSInit();     /* 初始化uC/OS-II*/ 
    /* 应用程序初始化代码... */ 
    /* 调用OSTaskCreate()创建至少一个任务*/
    OSStart();     /* 开始多任务调度 */ 
    允许时钟节拍中断; 
}

4、通信与同步

通过控制事件控制块(ECB),控制任务的通信和同步。
等待任务列表,操作同任务就绪表。

同步与互斥,通过开关中断来实现:

  • 临界区
  • 信号量
    • P操作: O S _ E N T E R _ C R I T I C A L ( ) → OS\_ENTER\_CRITICAL()\rightarrow OS_ENTER_CRITICAL()关中断
    • V操作: O S _ E X I T _ C R I T I C A L ( ) → OS\_EXIT\_CRITICAL()\rightarrow OS_EXIT_CRITICAL()开中断

3种开关中断的方法:
(1)执行 E N T E R ( ) ENTER() ENTER()关中断,执行 E X I T ( ) EXIT() EXIT()开中断
(2) E N T E R ( ) ENTER() ENTER()先在栈中保存当前中断状态,然后关中断, E X I T ( ) EXIT() EXIT()从栈中弹出
(3)在局部变量中保存中断状态

操作 函数
创建信号量 O S S e m C r e a t e ( ) OSSemCreate() OSSemCreate()
P操作 O S S e m P e n d ( ) OSSemPend() OSSemPend()
V操作 O S S e m P o s t ( ) OSSemPost() OSSemPost()
查询 O S S e m Q u e r y ( ) OSSemQuery() OSSemQuery()

任务的通信:

  • 低级通信方式
    • 信号量
  • 高级通信方式
    • 共享内存
    • 邮箱(Mbox)
    • 消息队列(Q)

5、存储管理

内存管理是对进行管理。
采用(可变大小)固定分区的方式 ⇒ \Rightarrow 解决了内存碎片。

操作 函数
创建分区 O S M e m C r e a t e ( ) OSMemCreate() OSMemCreate()
分配内存块 O S M e m G e t ( ) OSMemGet() OSMemGet(),为了防止将同一个块分配给多个任务,必须使用信号量PV操作进行加锁
释放内存块 O S M e m P u t ( ) OSMemPut() OSMemPut()

你可能感兴趣的:(嵌入式系统学习笔记,操作系统,嵌入式)