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)
{
u8 Res;
#if SYSTEM_SUPPORT_OS
OSIntEnter();
#endif
#if SYSTEM_SUPPORT_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系统初始化
使用系统之前需要将系统初始化,函数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();
OSInit(&err);
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,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
OS_CRITICAL_EXIT();
OSStart(&err);
}
任务创建与删除
任务创建
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
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;
while (DEF_ON) {
CPU_CRITICAL_ENTER();
OSIdleTaskCtr++;
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCtr++;
#endif
CPU_CRITICAL_EXIT();
OSIdleTaskHook();
}
}
二、时钟节拍任务
用来跟踪任务延时和任务等待超时
三、统计任务
可用来统计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
App_OS_SetAllHooks();
#endif
总结
创建任务注意事项
在UCOSIII系统初始化的时候会初始化几个基本的任务,这几个基本的任务使用了五个不同的优先级,后面创建的任务不可以使用这五个优先级。
OS_IdleTaskInit(p_err);
OS_TickTaskInit(p_err);
OS_StatTaskInit(p_err);
OS_IntQTaskInit(p_err);
OS_TmrInit(p_err);
系统裁剪
系统裁剪的文件是os_cfg.h和os_cfg_app.h,其中的宏定义就是控制一些功能的开或者关闭。
|