UCOS 整理

学习ucos系统的总结。

利用 STM32 的 SYSTICK 定时器来提供 UCOSII 时钟节拍。

Ucos 任务的一般格式为:

void MyTask (void *pdata)

{ 任务准备工作

While(1)//死循环

{ 任务 MyTask实体代码;

OSTimeDlyHMSM(x,x,x,x);//调用任务延时函数,释放 cpu控制权,

 }

 }

假如我们新建了 2 个任务为 MyTask 和 YourTask,这里我们先忽略任务优先级的概念,两个任务死循环中延时时间为 1s。如果某个时刻,任务 MyTask 在执行中,当它执行到延时函数 OSTimeDlyHMSM 的时候,它释放 cpu 控制权,这个时候,任务 YourTask 获得 cpu 控制权开 始执行,任务 YourTask 执行过程中,也会调用延时函数延时 1s 释放 CPU 控制权,这个过程中 任务 A 延时 1s 到达,重新获得 CPU 控制权,重新开始执行死循环中的任务实体代码。如此循环,现象就是两个任务交替运行,就好像 CPU 在同时做两件事情一样。

前面我们学习的所有实验,都是一个大任务(死循环),这样,有些事情就比较不好处理,比如:MP3 实验,在 MP3 播放的时候,我们还希望显示歌词,如果是一个死循环(一个任务),那么很可能在显示歌词的时候,MP3 声音出现停顿(尤其是高码率的时候),这主要是歌词显 示占用太长时间,导致 VS1053 由于不能及时得到数据而停顿。而如果用 UCOSII 来处理,那 么我们可以分 2 个任务,MP3 播放一个任务(优先级高),歌词显示一个任务(优先级低)。 这样,由于 MP3 任务的优先级高于歌词显示任务,MP3 任务可以打断歌词显示任务,从而及 时给 VS1053 提供数据,保证音频不断,而显示歌词又能顺利进行。这就是 UCOSII 带来的好 处。

任务优先级,这个概念比较好理解,ucos 中,每个任务都有唯一的一个优先级。优先级是任务的唯一标识。在 UCOSII 中,使用 CPU 的时候,优先级高(数值小)的任务比优先级低的任务具有优先使用权,即任务就绪表中总是优先级最高的任务获得 CPU 使用权,只有高优先级 的任务让出 CPU 使用权(比如延时)时,低优先级的任务才能获得 CPU 使用权。UCOSII 不支 持多个任务优先级相同,也就是每个任务的优先级必须不一样。任务堆栈,就是存储器中的连续存储空间。为了满足任务切换和响应中断时保存 CPU 寄存 器中的内容以及任务调用其他函数时的需要,每个任务都有自己的堆栈。在创建任务的时候,任务堆栈是任务创建的一个重要入口参数。 任务控制块 OS_TCB,用来记录任务堆栈指针,任务当前状态以及任务优先级等任务属性。 UCOSII 的任何任务都是通过任务控制块(TCB)的东西来控制的,一旦任务创建了,任务控制块 OS_TCB 就会被赋值。每个任务管理块有 3 个最重要的参数:1,任务函数指针;2,任务 堆栈指针;3,任务优先级;任务控制块就是任务在系统里面的身份证(UCOSII 通过优先级识 别任务),任务就绪表,简而言之就是用来记录系统中所有处于就绪状态的任务。它是一个位图,系统中每个任务都在这个位图中占据一个进制位,该位置的状态(1 或者 0)就表示任务是否处于 就绪状态。任务调度的作用一是在任务就绪表中查找优先级最高的就绪任务,二是实现任务的切换。比如说,当一个任务释放 cpu 控制权后,进行一次任务调度,这个时候任务调度器首先要去任 务就绪表查询优先级最高的就绪任务,查到之后,进行一次任务切换,转而去执行下一个任务。任务的创建,删除,挂起和恢复。

任务删除,释放CPU资源。

挂起:无论程序到哪里,直接挂起。

删除:删除后,执行完该次循环。A请求删除B,B得知后自己删除自己。

在uc/os中删除一个任务,一般情况下是自己删除自己。如果任务A直接调用OSTaskDel (INT8U prio)函数来直接删除任务B,任务B占用的资源会得不到释放,系统到最后会没有内存可用。所以当任务A想要删除任务B的时候,会先调用OSTaskDelReq (INT8U prio)函数来请求任务B删除自己,比如B的优先级是10,即调用OSTaskDelReq (10)。

       任务B会通过OSTaskDelReq (INT8U prio)函数来查询是否有其他任务请求删除自己。若有,则释放自己占用的资源、内存,调用OSTaskDel (OS_PRIO_SELF)来删除自己。

信号量:

“信号量”为操作系统用于处理临界区问题和实现进程间同步提供了一种有效的机制。在很多操作系统原理书中都提到了信号量的概念,常用P操作与V操作来表明信号量的行为。PV操作的伪代码如下:

设s为一整数型变量:

  P操作:while( s==0); s--;

  V操作:s++

每个任务中的delay_ms:让出CPU控制量

 

邮箱

邮箱是信号量的扩展,相当于把一个指针定义的变量从一个任务传递到另一个或多个任务中去,这个指针是先发到邮箱,然后等待任务从邮箱里提取指针,这也就传递了指针指向的具体变量值。等待邮箱的任务是可以设置无限等待和等待若干个时钟节拍后任务自动恢复执行。

两个任务之间相互传递参数

队列是多个邮箱的数组,可以看做是个指针数组,任务之间可以按照一定顺序以指针定义的变量来传递,即是发送一个个指针给任务,任务获得指针,来处理指向的变量。这个方式有先进先出,后进后出。

    信号量,邮箱,队列的最大不同在于它们发送的内容不同。

            (1).信号量是一个触发信号,也是一个计数器。

       (2).邮箱是信号量的扩展,相当于一个指针定义的变量。

       (3).队列是多个邮箱的数组,可以看做是个指针数组。

 

前后台系统

简单的小系统通常是前后台系统,这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。


   RTOS操作系统:UCOS,FreeRTOS,RTX,RT-Thread,DJYOS等

Ucos freertosrtx rt-thread linux

RTOS操作系统的核心内容在于:实时内核

Ucos: 可剥夺内核顾名思义就是可以剥夺其他任务的CPU使用权,它总是运行就绪任务中的优先级最高的那个任务。0-10(统计,空闲。)

UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。UCOSIII提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。

ucosⅡ2.86版本起支持256任务

 

Ucosiii时钟节拍:

#define OS_CFG_TICK_RATE_HZ           200u               /* Tick rate inHertz (10 to 1000 Hz)  

    UCOSIII就是一个可剥夺的多任务系统,我们使用UCOSIII的一个重要 的原因就是它的多任务处理能力

UCOSIII中的任务由三部分组成:任务堆栈、任务控制块和任务函数。

    UCOSIII默认有5个系统任务:

   1、空闲任务:UCOSIII创建的第一个任务,UCOSIII必须创建的任务,此任务有UCOSIII自动创建,不需要用户手动创建。

   2、时钟节拍任务:此任务也是必须创建的任务。

   3、统计任务:可选任务,用来统计CPU使用率和各个任务的堆栈使用量。此任务是可选任务,由宏OS_CFG_STAT_TASK_EN控制是否使用此任务。

   4、定时任务:用来向用户提供定时服务,也是可选任务,由宏OS_CFG_TMR_EN控制是否使用此任务。

   5、中断服务管理任务:可选任务,由宏OS_CFG_ISR_POST_DEFERRED_EN控制是否使用此任务。

UCOSIII的任务一共有5种状态:

   1、休眠态:任务已经在CPU的flash中了,但是还不受UCOSIII管理。

   2、就绪态:系统为任务分配了任务控制块,并且任务已经在就绪表中登记,这时这个任务就具有了运行的条件,此时任务的状态就是就绪态。

   3、运行态:任务获得CPU的使用权,正在运行。

   4、等待态:正在运行的任务需要等待一段时间,或者等待某个事件,这个任务就进入了等待态,此时系统就会把CPU使用权转交给别的任务。

   5、中断服务态:当发送中断,当前正在运行的任务会被挂起,CPU转而去执行中断服务函数,此时任务的任务状态叫做中断服务态。

 

任务调度就是中止当前正在运行的任务转而去执行其他的任务。

      UCOSIII是可剥夺型内核,因此当一个高优先级的任务准备就绪,并且此时发生了任务调度,那么这个高优先级的任务就会获得CPU的使用权!

       UCOSIII中的任务调度是由任务调度器来完成的,任务调度器有2种:任务级调度器和中断级调度器。

    任务级调度器为函数OSSched()。

    中断级调度器为函数OSIntExit(),当退出外部中断服务函数的时候使用中断级任务调度。

 

时间片轮转调度

 

任务切换分为两种:任务级切换和中断级切换。

任务级切换函数为:OSCtxSw()。

中断级切换函数为:OSIntCtxSw()。

 

UCOSIII中要想使用任务,第一件事就是创建一个任务,创建任务使用函数OSTaskCreate()。如果我们不想使用某个任务了就可将其删除,删除任务使用函数OSTaskDel()。当我们想暂停某个任务,但是又不想删除掉这个任务的时候就可以使用函数OSTaskSuspend()来将这个任务挂起。当我们想要恢复某个被挂起的任务的时候可以调用函数OSTaskResume()


以上大多内容摘自原子资料。在这里表示感谢。

你可能感兴趣的:(ucos)