所谓时钟节拍,就是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---实钟节拍的更多相关文章

  1. uc/os iii移植到STM32F4---IAR开发环境

    也许是先入为主的原因,时钟用不惯Keil环境,大多数的教程都是拿keil写的,尝试将官方的uc/os iii 移植到IAR环境. 1.首先尝试从官网上下载的官方移植的代码,编译通过,但是执行会报堆栈溢 ...

  2. 基于μC/OS—III的CC1120驱动程序设计

    基于μC/OS—III的CC1120驱动程序设计 时间:2014-01-21 来源:电子设计工程 作者:张绍游,张贻雄,石江宏 关键字:CC1120   嵌入式操作系统   STM32F103ZE   ...

  3. OS考研复习笔记——操作系统的定义、目标、作用和发展的主要动力

    计算机系统由硬件和软件两部分组成.操作系统(OS,Operating System)是配置在计算机硬件上的第一层软件,是对硬件系统的首次补充. 硬件:计算机物理设备,即各种处理机存储器.输入/输出设备 ...

  4. os模块常用方法笔记

    os模块是程序和系统文件之间的交互接口,可以实现对文件的创建.删除等功能,以下对os模块的功能做一个笔记,方便以后学习和查找. import os os.getcwd() #获取当前工作目录,即当前p ...

  5. STM32F40G-EVAL_UC/OS III

    micrum官网下载uc/os程序包: 包含文件cotex_M4.h:

  6. golang os包使用笔记

    zhangsan os.Stidn 标准输入 os.Stdout 标准输出 os.Stderr 标准错误输出

  7. python os模块使用笔记(更新)

    import os 添加os模块 walk方法: os.walk(path) path是string形式的目标目录 生成一个某目录下递归树形目录迭代器,方便递归访问子目录,访问目录就能够轻松访问子文件 ...

  8. os模块。笔记

    os 模块提供了很多允许你的程序与操作系统直接交互的功能 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir()  ...

  9. python os库学习笔记

    os.getcwd(): 获取当前目录 os.name: 获取当前使用的操作系统 eg: print os.name os.remove(): 删除指定文件 eg: os.remove('test.t ...

  10. Python3 os.path() 模块笔记

    os.path 模块主要用于获取文件的属性. 以下是 os.path 模块的几种常用方法: 方法 说明 os.path.abspath(path) 返回绝对路径 os.path.basename(pa ...

随机推荐

  1. Mysql 中写操作时保驾护航的三兄弟!

    这期的文章主要是讲述写操作过程中涉及到的三个日志文件,看过前几期的话可能你或多或少已经有些了解了(或者从别的地方也了解过).比如整个写操作过程中用到的两阶段提交,又或者是操作过程中涉及到的日志文件,但 ...

  2. day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  3. XA Transactions

    XA Transactions XA is a two-phase commit protocol that is natively supported by many databases and t ...

  4. java.lang.IllegalStateException Unable to find a @SpringBootConfiguration错误解决方案

    问题描述:java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @Co ...

  5. P5686 和积和

    写在前面 数学题接触的少,卡了半下午,愣是没想到直接往前缀和上考虑,按元素强推莽了半下午 Description 直接跳转到题目去啊 Solution 记 \(A,B\) 的前缀和序列分别为 \(sA ...

  6. nginx 配置文件解读

    参考:链接 在微服务的体系之下,Nginx正在被越来越多的项目采用作为网关来使用,配合 Lua 做限流.熔断等控制 --源自 nginx Lua 脚本语言,用标准C语言编写并以源代码形式开放, 其设计 ...

  7. 不要在nodejs中阻塞event loop

    目录 简介 event loop和worker pool event loop和worker pool中的queue 阻塞event loop event loop的时间复杂度 Event Loop中 ...

  8. Java执行Dos-Shell脚本

    Java执行Dos-Shell脚本 1.介绍 2.调用shell脚本 2.1 获取键盘输入 2.2 构建指令 2.3 Java代码 3.Java调用Shell并传入参数 4.Java调用远程的Shel ...

  9. Java——I/O入门相关练习代码

    流的概念 读取文件 读取文件1 读取文件2 读取文件3 读取文件4 skip跳过n个字节后再开始读取 读取过程中暂停给当前位置做一个标记下一次从标记位置开始读取 序列流集合流 把三个流添加到集合中合并 ...

  10. 读取EXCEL文档解析工具类

    package test;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException ...