μC/OS-III---I笔记2---实钟节拍
所谓时钟节拍,就是CPU以固定的频率产生中断,可以看做是系统的心跳。内核利用这个时钟节拍来管理各个任务的一些时间管理比如延时,定时,超时检测,时间轮片调度等。时钟节拍的频率一般10Hz--1000Hz。频率太高内核负担加重,频率太低实时性就差。这个频率在μC/OS-III源码OS_CFG_APP.c中可以自定义,在STM32平台的具体实现如下:
1.配置滴答定时器
void OS_CPU_SysTickInit (CPU_INT32U cnts)
{
CPU_INT32U prio; CPU_REG_NVIC_ST_RELOAD = cnts - 1u; /* Set SysTick handler prio. */
prio = CPU_REG_NVIC_SHPRI3;
prio &= DEF_BIT_FIELD(24, 0);
prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24); CPU_REG_NVIC_SHPRI3 = prio; /* Enable timer. */
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_CLKSOURCE |
CPU_REG_NVIC_ST_CTRL_ENABLE;
/* Enable timer interrupt. */
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_TICKINT;
}
void OS_CPU_SysTickInit (CPU_INT32U cnts)
2.定时器中断
void OS_CPU_SysTickHandler (void)
{
CPU_SR_ALLOC(); CPU_CRITICAL_ENTER();
OSIntNestingCtr++; /* Tell uC/OS-III that we are starting an ISR */
CPU_CRITICAL_EXIT(); OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */ OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */
}
void OS_CPU_SysTickHandler (void)
这就是一个滴答定时器的中断函数,函数内主要做了中断嵌套级变量OSIntNestingCtr加1的操作,和调用了OSTimeTick()这个函数
void OSTimeTick (void)
{
OS_ERR err;
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
CPU_TS ts;
#endif OSTimeTickHook(); /* Call user definable hook */ #if OS_CFG_ISR_POST_DEFERRED_EN > 0u ts = OS_TS_GET(); /* Get timestamp */
OS_IntQPost((OS_OBJ_TYPE) OS_OBJ_TYPE_TICK, /* Post to ISR queue */
(void *)&OSRdyList[OSPrioCur],
(void *) 0,
(OS_MSG_SIZE) 0u,
(OS_FLAGS ) 0u,
(OS_OPT ) 0u,
(CPU_TS ) ts,
(OS_ERR *)&err); #else (void)OSTaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
(OS_OPT ) OS_OPT_POST_NONE,
(OS_ERR *)&err); #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
OS_SchedRoundRobin(&OSRdyList[OSPrioCur]);
#endif #if OS_CFG_TMR_EN > 0u
OSTmrUpdateCtr--;
if (OSTmrUpdateCtr == (OS_CTR)0u) {
OSTmrUpdateCtr = OSTmrUpdateCnt;
OSTaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
(OS_OPT ) OS_OPT_POST_NONE,
(OS_ERR *)&err);
}
#endif #endif
}
void OSTimeTick (void)
注意 其中的信号发布函数指向了任务控制块OSTickTaskTCB,每次到达滴答定时器中断时都会发布一个信号量给这个任务控制块,从而使这个任务就可以执行下去,任务详情见代码
void OS_TickTask (void *p_arg)
{
OS_ERR err;
CPU_TS ts; p_arg = p_arg; /* Prevent compiler warning */ while (DEF_ON) {
(void)OSTaskSemPend((OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err); /* Wait for signal from tick interrupt */
if (err == OS_ERR_NONE) {
if (OSRunning == OS_STATE_OS_RUNNING) {
OS_TickListUpdate(); /* Update all tasks waiting for time */
}
}
}
}
void OS_TickTask (void *p_arg)
任务中请求信号,如果请求到就执行OS_TickListUpdate(),这个函数主要是用到了哈希算法(求余)来对加入的时间列表的任务检查看是否到时,对于延时到时且符合就绪条件的任务加入就绪任务列表里下次任务调度时就会按照该有的优先级进行任务调度。不满足就绪条件的按情况修改任务状态。
void OS_TickListUpdate (void)
{
CPU_BOOLEAN done;
OS_TICK_SPOKE *p_spoke;
OS_TCB *p_tcb;
OS_TCB *p_tcb_next;
OS_TICK_SPOKE_IX spoke;
CPU_TS ts_start;
CPU_TS ts_end;
CPU_SR_ALLOC(); OS_CRITICAL_ENTER();
ts_start = OS_TS_GET();
OSTickCtr++; /* Keep track of the number of ticks */
spoke = (OS_TICK_SPOKE_IX)(OSTickCtr % OSCfg_TickWheelSize);
p_spoke = &OSCfg_TickWheel[spoke];
p_tcb = p_spoke->FirstPtr;
done = DEF_FALSE;
while (done == DEF_FALSE) {
if (p_tcb != (OS_TCB *)0) {
p_tcb_next = p_tcb->TickNextPtr; /* Point to next TCB to update */
switch (p_tcb->TaskState) {
case OS_TASK_STATE_RDY:
case OS_TASK_STATE_PEND:
case OS_TASK_STATE_SUSPENDED:
case OS_TASK_STATE_PEND_SUSPENDED:
break; case OS_TASK_STATE_DLY:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
p_tcb->TaskState = OS_TASK_STATE_RDY;
OS_TaskRdy(p_tcb); /* Make task ready to run */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break; case OS_TASK_STATE_PEND_TIMEOUT:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
#if (OS_MSG_EN > 0u)
p_tcb->MsgPtr = (void *)0;
p_tcb->MsgSize = (OS_MSG_SIZE)0u;
#endif
p_tcb->TS = OS_TS_GET();
OS_PendListRemove(p_tcb); /* Remove from wait list */
OS_TaskRdy(p_tcb);
p_tcb->TaskState = OS_TASK_STATE_RDY;
p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */
p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break; case OS_TASK_STATE_DLY_SUSPENDED:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break; case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
p_tcb->TickRemain = p_tcb->TickCtrMatch /* Compute time remaining of current TCB */
- OSTickCtr;
if (OSTickCtr == p_tcb->TickCtrMatch) { /* Process each TCB that expires */
#if (OS_MSG_EN > 0u)
p_tcb->MsgPtr = (void *)0;
p_tcb->MsgSize = (OS_MSG_SIZE)0u;
#endif
p_tcb->TS = OS_TS_GET();
OS_PendListRemove(p_tcb); /* Remove from wait list */
OS_TickListRemove(p_tcb); /* Remove from current wheel spoke */
p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
p_tcb->PendStatus = OS_STATUS_PEND_TIMEOUT; /* Indicate pend timed out */
p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
} else {
done = DEF_TRUE; /* Don't find a match, we're done! */
}
break; default:
break;
}
p_tcb = p_tcb_next;
} else {
done = DEF_TRUE;
}
}
ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
if (OSTickTaskTimeMax < ts_end) {
OSTickTaskTimeMax = ts_end;
}
OS_CRITICAL_EXIT();
}
void OS_TickListUpdate (void)
整个时钟节拍相关的大致流程如下:

μC/OS-III---I笔记2---实钟节拍的更多相关文章
- uc/os iii移植到STM32F4---IAR开发环境
也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...
- 基于μC/OS—III的CC1120驱动程序设计
基于μC/OS—III的CC1120驱动程序设计 时间:2014-01-21 来源:电子设计工程 作者:张绍游,张贻雄,石江宏 关键字:CC1120 嵌入式操作系统 STM32F103ZE ...
- OS考研复习笔记——操作系统的定义、目标、作用和发展的主要动力
计算机系统由硬件和软件两部分组成.操作系统(OS,Operating System)是配置在计算机硬件上的第一层软件,是对硬件系统的首次补充. 硬件:计算机物理设备,即各种处理机存储器.输入/输出设备 ...
- os模块常用方法笔记
os模块是程序和系统文件之间的交互接口,可以实现对文件的创建.删除等功能,以下对os模块的功能做一个笔记,方便以后学习和查找. import os os.getcwd() #获取当前工作目录,即当前p ...
- STM32F40G-EVAL_UC/OS III
micrum官网下载uc/os程序包: 包含文件cotex_M4.h:
- golang os包使用笔记
zhangsan os.Stidn 标准输入 os.Stdout 标准输出 os.Stderr 标准错误输出
- python os模块使用笔记(更新)
import os 添加os模块 walk方法: os.walk(path) path是string形式的目标目录 生成一个某目录下递归树形目录迭代器,方便递归访问子目录,访问目录就能够轻松访问子文件 ...
- os模块。笔记
os 模块提供了很多允许你的程序与操作系统直接交互的功能 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() ...
- python os库学习笔记
os.getcwd(): 获取当前目录 os.name: 获取当前使用的操作系统 eg: print os.name os.remove(): 删除指定文件 eg: os.remove('test.t ...
- Python3 os.path() 模块笔记
os.path 模块主要用于获取文件的属性. 以下是 os.path 模块的几种常用方法: 方法 说明 os.path.abspath(path) 返回绝对路径 os.path.basename(pa ...
随机推荐
- EL&Filter&Listener:EL表达式和JSTL,Servlet规范中的过滤器,Servlet规范中的监听器,观察着设计模式,监听器的使用,综合案例学生管理系统
EL&Filter&Listener-授课 1 EL表达式和JSTL 1.1 EL表达式 1.1.1 EL表达式介绍 *** EL(Expression Language):表达式语言 ...
- 在vCenter Server中添加ESXi 主机失败的问题
报错:出现了常规系统错误: Timed out waiting for vpxa to start 报错是这个,我看了下vcenter的版本是6.5,如图右上,这个报错是因为我ESXI主机是6.7的, ...
- API服务接口签名代码与设计,如果你的接口不走SSL的话?
在看下面文章之前,我们先问几个问题 rest 服务为什么需要签名? 签名的几种方式? 我认为的比较方便的快捷的签名方式(如果有大神持不同意见,可以交流!)? 怎么实现验签过程 ? 开放式open ap ...
- 在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态.这些都是计算属性无法做到的.
- cms_文章管理
文章管理 文章管理前端页面 把引入的多个布局抽成了公共代码 <%@ page language="java" contentType="text/html; cha ...
- loj10005数列极差
题目描述 佳佳的老师在黑板上写了一个由 n个正整数组成的数列,要求佳佳进行如下操作:每次擦去其中的两个数 a 和 b,然后在数列中加入一个数 a*b+1,如此下去直至黑板上剩下一个数为止,在所有按这 ...
- 无刷电调基础知识以及BLHeli固件烧录和参数调整
标题: 无刷电调基础知识以及BLHeli固件烧录和参数调整 作者: 梦幻之心星 sky-seeker@qq.com 标签: [#基础知识,#电调,#BLHeli,#固件,#烧录,#调参] 目录: [电 ...
- Tomcat 核心组件 Connector
Connector是Tomcat的连接器,其主要任务是负责处理浏览器发送过来的请求,并创建一个Request和Response的对象用于和浏览器交换数据,然后产生一个线程用于处理请求,Connecto ...
- Docker及其使用思维导图
学习Docker的使用. 包括Docker的一些命令,Docker容器的使用,Docker镜像的使用,Docker容器连接等内容. 各种思维导图下载地址 Docker使用思维导图及各各种命令 Dock ...
- cassandra权威指南读书笔记--数据建模
没有join操作.有轻量级事务和批处理,但是没有外键等.反规范化.3.0支持物化视图,允许在一个表上创建数据的多个物化视图.使用cassandra要从查询入手,而不是先从数据模型开始.先对查询建模,然 ...