📄 os_core.c
字号:
OS_TCB *ptcb1;
OS_TCB *ptcb2;
OSTCBList = (OS_TCB *)0; /* 任务控制块的初始化 */
for (i = 0; i < (OS_LOWEST_PRIO + 1); i++)
{
OSTCBPrioTbl[i] = (OS_TCB *)0; /* 优先级表清零 */
}
ptcb1 = &OSTCBTbl[0];
ptcb2 = &OSTCBTbl[1];
for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++)
{ /* 初始化空余任务控制块列表 */
ptcb1->OSTCBNext = ptcb2;
ptcb1++;
ptcb2++;
}
ptcb1->OSTCBNext = (OS_TCB *)0; /* 最后的任务控制块 */
OSTCBFreeList = &OSTCBTbl[0];
}
/*$PAGE*/
/*
*********************************************************************************************************
* 调度器
*
* 函数描述: 该函数可被其他 uC/OS-II 服务函数调用用以确定一个新的高优先级准备运行。该函数由任务级代码调用
* 不能从中断服务子程序中重新调度任务。(见用于中断服务子程序重新调度的 OSIntExit()函数)
*
* 输入参数 : 无
*
* 返回值 : 无
*
* 注释 : 1) 该函数为 uC/OS-II的内部函数,应用程序不该调用。
* 2) 当调度器上锁时,重新调度被禁止 (见 OS_SchedLock())
*********************************************************************************************************
*/
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
INT8U y;
OS_ENTER_CRITICAL();
if ((OSIntNesting == 0) && (OSLockNesting == 0))
{ /* 只有在所有中断服务子程序全退出及不上锁的条件下执行 */
y = OSUnMapTbl[OSRdyGrp]; /* 得到指向最高优先级就绪任务的指针 */
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
if (OSPrioHighRdy != OSPrioCur)
{ /* 如果当前就绪任务为最高优先级别,则任务不切换 */
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
OSCtxSwCtr++; /* 增加寄存器切换计数器的值 */
OS_TASK_SW(); /* 执行任务切换 */
}
}
OS_EXIT_CRITICAL();
}
/*$PAGE*/
/*
*********************************************************************************************************
* 空闲任务
*
* 函数描述: 该任务为 uC/OS-II的内部任务,当没有其他任务运行时,该任务运行。其他任务都在等待事件发生。
*
*
* 输入参数 : 无
*
* 返回值 : 无
*
* Note(s) : 1) 关键部分后,调用OSTaskIdleHook()以确保对一些指令中断至少是打开的。在一些处理器上 (例如
* 飞利蒲 XA), 打开和关闭中断,在他们再次关闭之前,处理器没有足够时间使能中断。因此,
* uC/OS-II 将不能识别中断。
* 2) 钩子函数允许使用者在程序中停止 CPU 以进入低功耗模式。
*
*********************************************************************************************************
*/
void OS_TaskIdle (void *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
pdata = pdata; /* 防止因未使用pdata,编译器发出警告 */
for (;;) {
OS_ENTER_CRITICAL();
OSIdleCtr++;
OS_EXIT_CRITICAL();
OSTaskIdleHook(); /* 调用用户定义的钩子函数 */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* 统计任务
*
* 函数描述: 该任务是 uC/OS-II 的内部任务,它用于计算多任务环境的一些统计数据。尤其,OS_TaskStat()
* 计算 CPU 的使用率
* CPU 的使用率由以下决定:
*
* OSIdleCtr
* OSCPUUsage = 100 * (1 - ------------) (units are in %)
* OSIdleCtrMax
*
* 输入函数 : pdata 指针这次未使用
*
* 返回值 : 无
*
* 注释 : 1) 该任务运行在高于空闲任务的优先级别上。 事实上,它运行在高一级上, OS_IDLE_PRIO-1.
* 2) 通过设置配置 #define OS_TASK_STAT_EN 到 0可禁止统计任务的产生。
* 3) 在作统计之前,开始先延时 5 秒,以使系统稳定和创建其他任务。必须延时至少2秒以使系统为
* 空闲计数器建立最大值。
*
*********************************************************************************************************
*/
#if OS_TASK_STAT_EN > 0
void OS_TaskStat (void *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
INT32U run;
INT32U max;
INT8S usage;
pdata = pdata; /* 防止因未使用pdata,编译器发出警告 */
while (OSStatRdy == FALSE) /* 等待直到统计任务就绪 */
{
OSTimeDly(2 * OS_TICKS_PER_SEC);
}
max = OSIdleCtrMax / 100L;
for (;;)
{
OS_ENTER_CRITICAL();
OSIdleCtrRun = OSIdleCtr; /* 得到空闲计数器的值 */
run = OSIdleCtr;
OSIdleCtr = 0L; /* 为下一秒复位空闲计数器 */
OS_EXIT_CRITICAL();
if (max > 0L)
{
usage = (INT8S)(100L - run / max);
if (usage >= 0)
{ /* Make sure we don't have a negative percentage */
OSCPUUsage = usage;
}
else
{
OSCPUUsage = 0;
}
}
else
{
OSCPUUsage = 0;
max = OSIdleCtrMax / 100L;
}
OSTaskStatHook(); /* 调用用户定义钩子函数 */
OSTimeDly(OS_TICKS_PER_SEC); /* 为下一秒增加 OSIdleCtr的值 */
}
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* 初始化任务控制块
*
* 函数描述: 该函数是 uC/OS-II 的内部函数,当任务创建是用于初始化任务控制块函数。(见 OSTaskCreate()及
* OSTaskCreateExt())
*
* 输入函数: prio 被创建的任务的优先级
*
* ptos 假设CPU 寄存器已被推入栈,则它使指向栈顶的指针。注意栈顶的位置在OS_STK_GROWTH
* 设为1时是存储器的高位,在OS_STK_GROWTH设为0时是存储器的低位。注意堆栈增长由CPU指定。
*
* pbos 指向栈底的指针。如果由OSTaskCreate()调用,则传递一个空指针。
*
*
* id 任务的识别号 (0..65535)
*
* stk_size 堆栈容量 (堆栈单元). 如果堆栈单元是 INT8U 的,则stk_size 包含堆栈的字节的数量。如
* 果堆栈是 INT32U 的,则堆栈包含'4 * stk_size'个字节数量。堆栈单元通过CPU 定义
* #define constant OS_STK 来建立。 如果由 'OSTaskCreate()'调用则 'stk_size' 是 0.
*
* pext 指向内存中分配给用户的扩展任务控制块的指针。允许存储浮点寄存器的内容、MMU寄存器
* 或者其他在任务切换中有用的数据。可以给每个任务起一个名字,并存储在任务控制块的扩展中。
* 如果由OSTaskCreate()调用,则传递一个空指针。
*
* opt 从 'OSTaskCreateExt()'传递选项,或从'OSTaskCreate()'传递0。
*
* 返回值: OS_NO_ERR 如果调用成功
* OS_NO_MORE_TCB 如果没有空余的任务控制块分配,则任务不能建立。
*
* 注释 : 该函数是 uC/OS-II的内部函数,应用程序不该调用。
*********************************************************************************************************
*/
INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
OS_ENTER_CRITICAL();
ptcb = OSTCBFreeList; /* 从空余任务控制块列表中得到任务控制块 */
if (ptcb != (OS_TCB *)0)
{
OSTCBFreeList = ptcb->OSTCBNext; /* 更新指向空余的任务控制块列表 */
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; /* 在任务控制块中装载堆栈指针 */
ptcb->OSTCBPrio = (INT8U)prio; /* 加载任务优先级到任务控制块 */
ptcb->OSTCBStat = OS_STAT_RDY; /* 任务准备运行 */
ptcb->OSTCBDly = 0; /* 任务不需延时 */
#if OS_TASK_CREATE_EXT_EN > 0
ptcb->OSTCBExtPtr = pext; /* 存储指针到任务控制块扩展中 */
ptcb->OSTCBStkSize = stk_size; /* 存储堆栈容量 */
ptcb->OSTCBStkBottom = pbos; /* 存储指针到堆栈栈底 */
ptcb->OSTCBOpt = opt; /* 存储任务选项 */
ptcb->OSTCBId = id; /* 存储任务识别号 */
#else
pext = pext; /* 防止编译器警告 */
stk_size = stk_size;
pbos = pbos;
opt = opt;
id = id;
#endif
#if OS_TASK_DEL_EN > 0
ptcb->OSTCBDelReq = OS_NO_ERR;
#endif
ptcb->OSTCBY = prio >> 3; /* 预先计算 X, Y, BitX and BitY */
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = prio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
#if OS_EVENT_EN > 0
ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* 任务不会挂起,当不使用消息、邮箱、信号量等*/
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /*指向事件标志节点的指针被初始化为空指针 */
#endif
#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
ptcb->OSTCBMsg = (void *)0; /* 没有接收到消息 */
#endif
#if OS_VERSION >= 204
OSTCBInitHook(ptcb);
#endif
OSTaskCreateHook(ptcb); /* 调用用户定义的钩子函数 */
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb;
ptcb->OSTCBNext = OSTCBList; /* 链接到任务控制块链上 */
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0)
{
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY; /* 使任务准备运行 */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_NO_MORE_TCB);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -