UCOSIII操作系统学习笔记——任务

RTOS系统

RTOS全程为:Real Time OS,就是实时操作系统。实时操作系统分为硬实时和软实时。硬实时要求在规定时间内必须完成操作,硬件实时系统有不允许超时。
RTOS操作系统:UCOS,FreeRTOS,RTX,RT-Thread,DJYOS等
UCOS的内核是可剥夺型的,可剥夺内核顾名思义就是可以剥夺其他任务的CPU使用权,它总是运行就绪任务中的优先级最高的那个任务。
UCOSIII中的任务主要有三部分组成:1)任务堆栈;2)任务控制块;3)任务函数。

任务堆栈

任务堆栈实际上就是一个数组,是任务的重要部分,堆栈是在RAM中按照“FIFO”的原则组织的一块连续的存储空间。用于保存任务切换和响应中断时保存CPU寄存器中的内容及任务调用其他函数时的需要。

任务控制块

任务控制块是用来记录与任务相关的信息的数据结构

优先级

UCOSIII中任务优先级数由宏OS_CFG_PRIO_MAX定义来配置,数值越小优先级越高,最低可用优先级就是OS_CFG_PRIO_MAX-1。

就绪表

UCOSIII中就绪表由2部分组成:
1)优先级位映射表OSPrioTbl[],用来记录那个优先级下有任务就绪;
2)就绪任务列表OSRdyList[],用来记录每一个优先级下所有就绪的任务。
优先级位映射表主要就是存储不同优先级的任务,而就绪任务列表是记录每一个优先级下有没有已经就绪的任务。
一个是记录不同优先级下的就绪任务,另外一个是记录同一个优先级下的就绪任务

任务调度器

任务调度就是中止当前正在运行的任务转而去执行其他的任务
UCOSIII是可剥夺型内核,高优先级任务准备就绪后,发送任务调度,高优先级的任务就会获得CPU的使用权!

任务调度器分类

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

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif

	//串口接收中断函数主体(省略)
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  									 
#endif
}

任务调度点

定义:在什么时间和什么位置发生了任务的调度
1)释放信号消息或发送消息,也可通过相应的参数不发生任务调度。
2)使用延时函数OSTimeDly()或者OSTimeDlyHMSM();
3)任务等待的事情还没发送(等待信号量,消息队列等);
4)任务取消等待
5)创建任务
6)删除任务
7)删除一个内核任务
8)任务改变自身的优先级或者其他任务的优先级
9)任务通过调用OSTaskSuspend()将自身挂起
10)任务解挂某个任务
11)退出所有的嵌套中断
12)调度器解锁
13)放弃其执行时间片
14)用户调用OSSched()(任务级调度器函数)

调度器的上锁和解锁

不希望发生任务调度的时候,例如一些代码的执行过程是不能被打断的。此时我们就可以使用函数OSSchedLock()对调度器加锁,当需要回复任务调度的时候就可以使用函数OSSchedUnlock()给已经上锁的任务调度器解锁。

时间片轮转调度(同一优先级下)

UCOSIII允许一个优先级下有多个任务,每个任务可以执行指定的时间(时间片),然后轮到下一个任务。这个过程就是时间片轮转调度,当一个任务不想在运行的时候就可以放弃其时间片。
时间片轮转调度为:OS_SchedRoundRobin()。

任务切换

将保存当前任务的现场到当前任务的堆栈中,主要是CPU寄存器值,然后恢复新的现场并且执行新的任务,这个过程就是任务切换。

任务的状态

从用户的角度讲任务一共有五种状态:
1)休眠态:任务已经在CPU的flash中了,但是还不受UCOSIII管理;
2)就绪态:系统为任务分配了任务控制块,并且任务已经在就绪表中登记,这时这个任务就具有了运行的条件,此时的任务就处于就绪的状态
3)运行态:任务获得CPU使用权
4)等待态:正在运行的任务需要等待一段时间,或者等待某个事件,这个任务就进入了等待态,此时系统就会把CPU使用权转给别的任务
5)中断服务态:当发送中断,当前正在运行的任务会被挂起,CPU转而去执行中断服务函数,此时任务的状态叫中断服务态。
UCOSIII操作系统学习笔记——任务_第1张图片

UCOSIII系统初始化

使用系统之前需要将系统初始化,函数OSInit()用来初始化UCOSIII的初始化,初始化是初始化其中的一些控制系统的变量,初始化函数必须先于其他UCOSIII函数调用(包括OSStart())。例:

int main(){
    OS_ERR err;
    CPU_SR_ALLOC();
    
    delay_Init(168);	//时钟初始化
    NVIC_PriorityGroupConfig(NVIC_PriortyGroup_2);	//中断分组配置
    uart_init(115200);		//串口初始化
    LED_Init();			//LED初始化
    
    OSInit(&err);	//初始化UCOSIII 初始化5个系统任务函数,最基本的需要初始化2个任务
    OS_CRITICAL_ENTER(); //进入临界区
    //创建开始任务
    OSTaskCreate((OS_TCB 	* )&StartTaskTCB,//任务控制块
				 (CPU_CHAR	* )"start task", //任务名字
                 (OS_TASK_PTR )start_task, //任务函数
                 (void		* )0,	//传递给任务函数的参数
                 (OS_PRIO	  )START_TASK_PRIO, //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],//任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,//任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,//任务堆栈大小
                 (OS_MSG_QTY  )0,//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK	  )0,//当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void   	* )0,//用户补充的存储区
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                 (OS_ERR 	* )&err);//存放该函数错误时的返回值
	OS_CRITICAL_EXIT();	//退出临界区	 
	OSStart(&err);  //开启UCOSIII
}

任务创建与删除

任务创建

UCOSIII中使用函数OSTaskCreate()创建任务,

void  OSTaskCreate (OS_TCB        *p_tcb, //任务控制块
                    CPU_CHAR      *p_name, //任务名称
                    OS_TASK_PTR    p_task,//任务函数
                    void          *p_arg,//传递给任务函数的参数
                    OS_PRIO        prio,//任务优先级
                    CPU_STK       *p_stk_base, //任务堆栈的初始地址
                    CPU_STK_SIZE   stk_limit,//任务堆栈的栈深
                    CPU_STK_SIZE   stk_size, //任务堆栈的大小
                    OS_MSG_QTY     q_size,	//任务内部消息队列能接收的最大消息数目
                    OS_TICK        time_quanta,//时钟片的大小
                    void          *p_ext,	//用户补充的存储区
                    OS_OPT         opt,	//任务选项
                    OS_ERR        *p_err)	//存放该函数错误时的返回值

扩展:OS_OPT opt有四个不同的选项,OS_OPT_TASK_NONE(表示没有任何选项)、OS_OPT_TASK_STK_CHK(指定是否允许监测该任务的堆栈)、OS_OPT_TASK_STK_CLR(指定是否清除该任务的堆栈)、OS_OPT_TASK_SAVE_FP(指定是否存储浮点寄存器,CPU需要有浮点运算硬件并且有专用代码保存浮点寄存器)。
错误码有解释调试的时候可以使用串口打印,然后对比寻找问题的原因。

任务删除

使用函数OSTaskDel(),函数原型如下:void OSTaskDel(OS_TCB *p_tch OS_ERR *p_err)
1、不要在运行中删除某个任务,防止一个任务影响另外一个任务的执行。

任务挂起和恢复

任务挂起

当需要该任务暂停,但是又不需要删除这个任务的时候就可以使用函数OSTaskSuspend()来将这个任务挂起,函数原型如下:

void OSTaskSuspend(OS_TCB *p_tcb,OS_ERR *p_err);

任务恢复

恢复某个被挂起的任务的时候可以调用函数OSTaskResume(),函数原型如下:

void OSTaskResume(OS_TCB *p_tcb,OS_ERR *p_err);

时间片轮转调度

时间片轮转调度主要是用于同一优先级下的任务,执行时间的控制。要是不同优先级的任务时间片轮转调度没有实际的意义,只会影响后面低优先级任务的执行而已。

#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候,修改宏置1
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif

系统内部任务(5个)

一、空闲任务

1)空闲任务是UCOSIII创建的第一个任务
2)空闲任务是UCOSIII必须创建的
3)空闲任务优先级总是OS_CFG_PRIO_MAX-1
4)空闲任务中不能调用任何可使空闲任务进入等待态的函数

void  OS_IdleTask (void  *p_arg)
{
    CPU_SR_ALLOC();
    p_arg = p_arg;                                          /* Prevent compiler warning for not using 'p_arg'         */

    while (DEF_ON) {
        CPU_CRITICAL_ENTER();
        OSIdleTaskCtr++;//一个变量,该变量增加的越快表示系统处于空闲的时间越多,也就表示系统越‘闲’
#if OS_CFG_STAT_TASK_EN > 0u
        OSStatTaskCtr++;
#endif
        CPU_CRITICAL_EXIT();
        OSIdleTaskHook();                                   /* Call user definable HOOK                               */
    }
}

二、时钟节拍任务

用来跟踪任务延时和任务等待超时

三、统计任务

可用来统计CPU的使用率、各个任务的CPU使用率和各任务的堆栈使用情况。开启步骤
1)将宏OS_CFG_STAT_TASK_EN置1
2)在唯一的一个应用任务里面调用函数OSStatTaskCPUUsageInit()。

四、定时任务

系统提供软件定时器功能,将宏OS_CFG_TMR_EN设置为1就会使能定时任务。要使用软件定时器一定需要使能定时任务。

五、中断服务管理任务

减少中断关闭的时间

钩子函数

钩子函数一般主要是用来扩展其他函数(任务)功能的,钩子函数有如下几个:
1)OSIdleTaskHook(),空闲任务调用这个函数,可以用来让CPU进入低功耗模式
2)OSInitHook(),初始化函数OSInit()调用此函数
3)OSStatTaskHook(),统计任务每秒中都会调用的函数
4)OSTaskCreateHook(),任务创建的钩子函数
5)OSTaskDelHook(),任务删除的钩子函数
6)OSTaskReturnHook(),任务意外返回时调用的钩子函数
7)OSTaskSwHook(),任务切换时候调用的钩子函数
8)OSTimeTickHook(),滴答定时器调用的钩子函数
钩子函数中可以添加自己的应用函数,但是不可以直接在这些函数中添加需要到APP函数中添加,例如空闲任务就需要在os_app_hooks.c文件中的App_OS_IdleTaskHook()函数添加。不可以在空闲任务函数中调用任何使该任务变为等待态的代码

#if OS_CFG_APP_HOOKS_EN				//使用钩子函数,使用前需要将该宏修改为1
	App_OS_SetAllHooks();			
#endif

总结

创建任务注意事项

在UCOSIII系统初始化的时候会初始化几个基本的任务,这几个基本的任务使用了五个不同的优先级,后面创建的任务不可以使用这五个优先级

OS_IdleTaskInit(p_err); //初始化空闲任务 优先级OS_CFG_PRIO_MAX-1
OS_TickTaskInit(p_err); //初始化时钟节拍任务 优先级1
OS_StatTaskInit(p_err); //初始化统计任务 优先级OS_CFG_PRIO_MAX-2
OS_IntQTaskInit(p_err); //初始化中断队列处理程序任务 优先级0
OS_TmrInit(p_err); //初始化定时器任务 优先级2

系统裁剪

系统裁剪的文件是os_cfg.h和os_cfg_app.h,其中的宏定义就是控制一些功能的开或者关闭。

你可能感兴趣的:(UCOSIII,单片机,stm32,嵌入式)