本文内容简介:
一共分为三部分:
第一部分:任务调度,讲述了任务级和中断级的任务调度和调度点
第二部分:任务切换
第三部分:系统初始化部分。
重点在于第三部分代码讲解
任务调度 |
- UCOSIII可剥夺型内核调度
任务调度器 |
一、任务级调度器
OS_Sched(),在OSTimeDlyHMSM中调用了该函数
二、中断级调度器
OSInitExit(),在退出中断的时候,启动任务调度。
任务调度点 |
1、释放信号量或者发送消息,也可通过配置相应的参数不发生任务调度。
2、使用延时函数OSTimeDly()或者OSTimeDlyHMSM()。
Dly()是时间延迟,DlyHMSM()是按节拍延迟
delay_ms()封装了TimeDly
3、任务等待的事情还没发生(等待信号量,消息队列等)。
4、任务取消等待。
5、创建任务。
6、删除任务。
7、删除一个内核对象。
8、任务改变自身的优先级或者其他任务的优先级。
9、任务通过调用OSTaskSuspend()将自身挂起。
10、任务解挂某个挂起的任务。
11、退出所有的嵌套中断。
12、通过OSSchedUnlock()给调度器解锁。
13、任务调用OSSchedRoundRobinYield()放弃其执行时间片。
14、用户调用OSSched()。
调度器上锁和解锁 |
OSSchedLock()上锁
OSSchedUnlock()解锁
时间片轮转 |
- 时间片轮转调度器为:OS_SchedRoundRobin()
- 任务可以主动放弃时间片
任务切换 |
任务切换是任务调度的一部分
任务切换分为两种:任务级切换和中断级切换。
任务级切换函数为:OSCtxSw()。
中断级切换函数为:OSIntCtxSw()。
系统初始化和启动 |
OS_ERR err;
...
OSInit(&err); //OSInit(&err)必须先于其他所有函数执行
OS_CRITICAL_ENTER(); //进入临界区
OSTaskCreate();
OS_CRITICAL_EXIT(); //退出临界区
...
OSStart(&err);
- 临界区是用于保护代码不被打断的
OSInit()系统初始化函数-讲解 |
代码讲解在于理清该函数的思路。部分代码会省略
中文备注的是讲解部分
void OSInit (OS_ERR *p_err)
{
CPU_STK *p_stk;
CPU_STK_SIZE size;
/*检查参数是否合格*/
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
OSInitHook(); /* Call port specific initialization code */
OSIntNestingCtr = (OS_NESTING_CTR)0; /* Clear the interrupt nesting counter */
/*标识操作系统是否在运行*/
OSRunning = OS_STATE_OS_STOPPED; /* Indicate that multitasking not started */
OSSchedLockNestingCtr = (OS_NESTING_CTR)0; /* Clear the scheduling lock counter */
OSTCBCurPtr = (OS_TCB *)0; /* Initialize OS_TCB pointers to a known state */
OSTCBHighRdyPtr = (OS_TCB *)0;
/*=============此处省略部分初始化,暂时不讲解==============================*/
/*优先级位映射表初始化,在任务管理(中)中进行了讲解*/
OS_PrioInit(); /* Initialize the priority bitmap table */
/*任务就绪队列,在任务管理(中)中进行了讲解*/
OS_RdyListInit(); /* Initialize the Ready List */
/*内存管理初始化*/
#if OS_CFG_MEM_EN > 0u /* Initialize the Memory Manager module */
OS_MemInit(p_err);
if (*p_err != OS_ERR_NONE) {
return;
}
#endif
/*消息池初始化*/
#if (OS_MSG_EN) > 0u /* Initialize the free list of OS_MSGs */
OS_MsgPoolInit(p_err);
if (*p_err != OS_ERR_NONE) {
return;
}
#endif
/*互斥量初始化*/
#if OS_CFG_MUTEX_EN > 0u /* Initialize the Mutex Manager module */
OS_MutexInit(p_err);
if (*p_err != OS_ERR_NONE) {
return;
}
#endif
/*消息队列初始化*/
#if OS_CFG_Q_EN > 0u
OS_QInit(p_err); /* Initialize the Message Queue Manager module */
if (*p_err != OS_ERR_NONE) {
return;
}
#endif
/*信号量初始化*/
#if OS_CFG_SEM_EN > 0u /* Initialize the Semaphore Manager module */
OS_SemInit(p_err);
if (*p_err != OS_ERR_NONE) {
return;
}
#endif
/*=============省略了task一些初始化,暂时不讲解==============================*/
/*空闲任务初始化,优先级MAX-1*/
OS_IdleTaskInit(p_err); /* Initialize the Idle Task */
if (*p_err != OS_ERR_NONE) {
return;
}
/*时钟节拍任务初始化*/
OS_TickTaskInit(p_err); /* Initialize the Tick Task */
if (*p_err != OS_ERR_NONE) {
return;
}
/*=============省略了一些初始化,暂时不讲解==============================*/
OSCfg_Init();
}
通过如上OSInit对操作系统运行所需要的资源进行了准备
OSStart()系统初始化函数-讲解 |
- 本质是开始运行就绪队列中最高优先级的任务
void OSStart (OS_ERR *p_err)
{
/*检查参数合法性*/
#ifdef OS_SAFETY_CRITICAL
if (p_err == (OS_ERR *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return;
}
#endif
if (OSRunning == OS_STATE_OS_STOPPED) {
/*找到就绪队列中最高优先级任务*/
OSPrioHighRdy = OS_PrioGetHighest(); /* Find the highest priority */
OSPrioCur = OSPrioHighRdy;
OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
OSTCBCurPtr = OSTCBHighRdyPtr;
OSRunning = OS_STATE_OS_RUNNING;
/*开始执行*/
OSStartHighRdy(); /* Execute target specific code to start task */
*p_err = OS_ERR_FATAL_RETURN; /* OSStart() is not supposed to return */
} else {
*p_err = OS_ERR_OS_RUNNING; /* OS is already running */
}
}