FreeRTOS-04-内核控制函数+时间管理函数
说明
本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正。
FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式、合作式和时间片调度。适用于微处理器或小型微处理器的实时应用。
本文档使用的FreeRTOS版本:FreeRTOS Kernel V10.4.1
参考文档:《FreeRTOS_Reference_Manual_V10.0.0.pdf》《FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf》《STM32F4 FreeRTOS开发手册_V1.1.pdf》
参考视频:正点原子FreeRTOS手把手教学-基于STM32_哔哩哔哩_bilibili
6 内核控制函数
内核控制函数就是FreeRTOS内核所使用的函数,一般情况下应用程序不使用这些函数。
官网API说明:FreeRTOS - Task Control Functions and Macros for the Free Open Source RTOS FreeRTOS
6.1 任务切换
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void taskYIELD( void );
函数描述:任务切换函数。如果没有与当前任务同等优先级或高优先级的任务,则任务调度器会选择当前任务继续运行。必须在调度器初始化之后使用。
函数参数:无
返回值:无
测试代码:创建两个任务,任务task0优先级为2,任务函数中每次从0计数到2进行一次任务切换;任务task1优先级也为2,任务函数中每次打印之后就挂起自己。
configSTACK_DEPTH_TYPE Task0_STACK_SIZE = 5;
UBaseType_t Task0_Priority = 2;
TaskHandle_t Task0_xhandle;
configSTACK_DEPTH_TYPE Task1_STACK_SIZE = 5;
UBaseType_t Task1_Priority = 2;
TaskHandle_t Task1_xhandle;
void task0_code(void *para)
{
unsigned int i = 0;
for (;;)
{
for (i = 0; i < 4; i++) {
PRINT(" task0 cnt %u...", i);
if (i == 2) {
vTaskResume(Task1_xhandle);
taskYIELD();
}
}
vTaskDelay(2000);
}
}
void task1_code(void *para)
{
static unsigned int cnt = 0;
for (;;)
{
PRINT(" task1 cnt %u...", cnt);
cnt++;
vTaskSuspend(Task1_xhandle);
}
}
void creat_task(void)
{
taskENTER_CRITICAL();
if (xTaskCreate(task0_code, "task0 task",
Task0_STACK_SIZE, NULL, Task0_Priority,
&Task0_xhandle) != pdPASS)
{
PRINT("creat task failed!\n");
}
if (xTaskCreate(task1_code, "task1 task",
Task1_STACK_SIZE, NULL, Task1_Priority,
&Task1_xhandle) != pdPASS)
{
PRINT("creat task failed!\n");
}
taskEXIT_CRITICAL();
vTaskStartScheduler();
}
编译、运行,结果符合预期,每次调度taskYIELD()之后执行一次任务切换,结果如下:
$ ./build/freertos-simulator
task0 cnt 0...
task0 cnt 1...
task0 cnt 2...
task1 cnt 0...
task0 cnt 3...
task0 cnt 0...
task0 cnt 1...
task0 cnt 2...
task1 cnt 1...
task0 cnt 3...
现在将任务task0的优先级改为3,大于任务task1的优先级:
UBaseType_t Task0_Priority = 3;
编译、运行,结果符合预期,每次调度taskYIELD()之后不会任务切换,结果如下:
$ ./build/freertos-simulator
task0 cnt 0...
task0 cnt 1...
task0 cnt 2...
task0 cnt 3...
task1 cnt 0...
task0 cnt 0...
task0 cnt 1...
task0 cnt 2...
task0 cnt 3...
task1 cnt 1...
task0 cnt 0...
6.2 进入临界区
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void taskENTER_CRITICAL( void );
函数描述:进入临界区,不能在中断服务函数中调用。中断服务函数中调用taskENTER_CRITICAL_FROM_ISR()进入临界区。
函数参数:无
返回值:无
6.3 退出临界区
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void taskEXIT_CRITICAL( void );
函数描述:退出临界区,不能在中断服务函数中调用。中断服务函数中调用taskEXIT_CRITICAL_FROM_ISR()退出临界区。
函数参数:无
返回值:无
taskENTER_CRITICAL()和taskEXIT_CRITICAL()函数用于临界段代码保护(任务级)。
taskENTER_CRITICAL_FROM_ISR()和taskEXIT_CRITICAL_FROM_ISR()函数用于中断级临界段代码保护。
临界段代码:也叫做临界区,指那些必须完整运行,不能被打断的代码。比如某些外设的初始化。FreeRTOS在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。
6.4 关闭可屏蔽中断
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void taskDISABLE_INTERRUPTS( void );
函数描述:关闭可屏蔽中断。不可嵌套使用。
函数参数:无
返回值:无
6.4 打开可屏蔽中断
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void taskENABLE_INTERRUPTS( void );
函数描述:关闭可屏蔽中断。不可嵌套使用。
函数参数:无
返回值:无
6.5 启动任务调度器
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void vTaskStartScheduler( void );
函数描述:启动任务调度器。典型应用为:main()函数先于调度器使用,调度器启动之后,执行任务及中断函数。调度器启动之后将选择优先级最高的任务进行执行。调度器启动之后,空闲任务(Idle task)将自动被创建。
函数参数:无
返回值:无
6.5 关闭任务调度器
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void vTaskEndScheduler( void );
函数描述:关闭任务调度器。仅支持x86架构处理器。关闭任务调度器之后,内核时钟将停止计数,所有创建的任务都会自动删除。
函数参数:无
返回值:无
7 时间管理
FreeRTOS延时函数分为相对模式和绝对模式。vTaskDelay()是相对延时函数。vTaskDelayUntil()是绝对延时函数。
7.1 相对延时
函数原型:
#include "FreeRTOS.h"
#include "task.h"
void vTaskDelay( const TickType_t xTicksToDelay );
函数描述:调用该函数的任务将进入阻塞态,中断一段固定的时钟周期。使用这个函数必须将宏INCLUDE_vTaskDelay置1。
函数参数:xTicksToDelay表示调用函数的任务的阻塞态保持时间,单位为时钟节拍数。真正的延时时间取决于时钟节拍频率。宏 portTICK_PERIOD_MS被用来根据时钟节拍数来计算一个时钟节拍的延时周期。
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define configTICK_RATE_HZ ( 1000 )
可以看出,单个时钟节拍计数时间为1ms,比如参数xTicksToDelay设为100,就表示延时100ms。
延时达到之后将进入就绪态。例如:当时钟计数到10000时,函数调用了vTaskDelay(100),然后任务进入阻塞态,并且保持阻塞态直到时钟计数到10100。
宏pdMS_TO_TICKS()可以被使用来延时毫秒。例如:调用vTaskDelay( pdMS_TO_TICKS(100) ),任务将进入阻塞态100毫秒。
如果参数xTicksToDelay为0,则等同于调用了一次taskYIELD()函数进行了一次任务切换。
返回值:无
7.2 绝对延时
函数原型:
#include “FreeRTOS.h”
#include “task.h”
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, TickType_t xTimeIncrement );
函数描述:调用该函数的任务将进入阻塞态直到一个绝对的时间到来。周期任务可以调用这个函数来实现一个固定的执行频率。使用这个函数必须将宏INCLUDE_vTaskDelayUntil置1。
函数参数:pxPreviousWakeTime:上一次任务延时结束被唤醒的时间点,任务中第一次调用函数vTaskDelayUntil()需要将pxPreviousWakeTime初始化为进入任务的while()循环体的时间点值。在以后的运行中函数vTaskDelayUntil()会自动更新pxPreviousWakeTime。
xTimeIncrement:任务需要延时的节拍数(相对于pxPreviousWakeTime本次延时的节拍数),也就是任务在pxPreviousWakeTime+xTimeIncrementpd时钟计数时从阻塞态恢复。MS_TO_TICKS()宏可用于延时毫秒。
(1)为任务主体,也就是任务执行的工作;(2)为任务调用vTaskDelayUntil()函数;(3)为其它任务执行。任务延时时间为xTimeIncrement,可看出任务总的执行时间一定小于任务的延时时间,也就是说使用vTaskDelayUntil()函数任务的执行周期永远是xTimeIncrement,而任务一定要在这个时间内完成,这个延时值就是绝对延时时间。
上面图中,xConstTickCount和xTimeToWake可能溢出,这些情况暂不讨论,这里仅说明函数的用法。
测试代码:创建一个任务,使用绝对延时函数延时50ms。
configSTACK_DEPTH_TYPE Task1_STACK_SIZE = 5;
UBaseType_t Task1_Priority = 2;
TaskHandle_t Task1_xhandle;
void task1_code(void *para)
{
unsigned int cnt = 0;
TickType_t xLastWakeTime;
const TickType_t xPeriod = pdMS_TO_TICKS(500);
xLastWakeTime = xTaskGetTickCount();
for (;;)
{
vTaskDelayUntil(&xLastWakeTime, xPeriod);
PRINT(" task1 cnt %u...", cnt);
cnt++;
}
}
void creat_task(void)
{
if (xTaskCreate(task1_code, "task1 task",
Task1_STACK_SIZE, NULL, Task1_Priority,
&Task1_xhandle) != pdPASS)
{
PRINT("creat task failed!\n");
}
}
7.3 系统时钟节拍
xTickCount是FreeRTOS系统时钟节拍计数器,每个滴答定时器中断中xTickCount就会加1。xTickCount具体操作过程在xTaskIncrementTick()函数中进行,这个函数在时钟计数器中断函数中调用。
FreeRTOS-04-内核控制函数+时间管理函数的更多相关文章
- μC/OS-Ⅲ系统的时间管理函数和定时器
一.时间管理函数 μC/OS-Ⅲ系统提供一些列时间管理服务函数: 1.OSTimeDly():任务延时n个时钟节拍. 2.OSTimeDlyHMSM():任务延时指定的时间,采用“时:分:秒:毫秒”方 ...
- RTX——第12章 系统时钟节拍和时间管理
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 RTX 操作系统的时钟节拍和时间管理函数,其中时间管理函数是 RTX 的基本函数,初学 ...
- 【uTenux实验】时间管理(系统时间/周期性处理/警报处理)
1.系统时间管理 系统时间管理函数用来对系统时间进行操作,是OS的一个基础性的东西.个人认为,设置系统时间和获取系统时间对OS来说基本是可有可无的. uTenux提供了三个系统时间相关API.分别用于 ...
- (笔记)Linux内核学习(八)之定时器和时间管理
一 内核中的时间观念 内核在硬件的帮助下计算和管理时间.硬件为内核提供一个系统定时器用以计算流逝的时间.系 统定时器以某种频率自行触发,产生时钟中断,进入内核时钟中断处理程序中进行处理. 墙上时间和系 ...
- linux设备驱动归纳总结(七):1.时间管理与内核延时【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(七):1.时间管理与内核延时 xxxxxxxxxxx ...
- 《Linux内核设计与实现》读书笔记(十一)- 定时器和时间管理【转】
转自:http://www.cnblogs.com/wang_yb/archive/2013/05/10/3070373.html 系统中有很多与时间相关的程序(比如定期执行的任务,某一时间执行的任务 ...
- Linux内核——定时器和时间管理
定时器和时间管理 系统定时器是一种可编程硬件芯片.它能以固定频率产生中断.该中断就是所谓的定时器中断.它所相应的中断处理程序负责更新系统时间,还负责执行须要周期性执行的任务. 系统定时器和时钟中断处理 ...
- Linux内核入门到放弃-时间管理-《深入Linux内核架构》笔记
低分辨率定时器的实现 定时器激活与进程统计 IA-32将timer_interrupt注册为中断处理程序,而AMD64使用的是timer_event_interrupt.这两个函数都通过调用所谓的全局 ...
- 解析Linux内核的基本的模块管理与时间管理操作---超时处理【转】
转自:http://www.jb51.net/article/79960.htm 这篇文章主要介绍了Linux内核的基本的模块管理与时间管理操作,包括模块加载卸载函数的使用和定时器的用法等知识,需要的 ...
随机推荐
- ceph-csi组件源码分析(1)-组件介绍与部署yaml分析
更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi组件源码分析(1)-组件介绍与部署yaml分析 基于tag v3.0.0 ht ...
- match、vlookup、hlookup函数(结合index运用可以实现自动化填充)
1.match返回查找值位置: match(lookup_value, lookup_array, match_type) Match(目标值,查找区域,0/1/-1) 使用注意:返回值是基于选择区域 ...
- 关于Android Studio Emulator常见使用问题
Q:模拟器无法初始化声音相关设备 Emulator: dsound: Could not initialize DirectSoundCapture Emulator: dsound: Reason: ...
- vue 快速入门 系列 —— vue loader 下
其他章节请看: vue 快速入门 系列 vue loader 下 CSS Modules CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统.vue-loader 提供了与 CSS ...
- 工作3年,还不会写单元测试?新技能get!
历史遗留代码不敢重构? 每次改代码都要回归所有逻辑? 提测被打回? 在近期的代码重构的过程中,遇到了各式各样的问题.比如调整代码顺序导致bug,取反操作逻辑丢失,参数校验逻辑被误改等. 上线前需要花大 ...
- 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题
解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题 最近有个问题非常讨厌,我们的工程中使用自己的连接池连接mysql数据库,可mysql数据库每隔8小时就会自动断开所有链接, ...
- 在CentOS7环境下部署weblogic集群
一)环境准备 服务器操作版本系统 CentOS7 weblogic版本包 weblogic1036_generic.jar(weblogic11g) JDK jdk-8u191-linux-x64.t ...
- 计算机网络体系结构整理-第九单元移动IP
第九章 移动IP 什么是移动:移动指的是用户连接位置的改变,而不是设备物理位置的改变 移动可以是离散的或连续的 移动IP的基本要求:1.IP地址不变 2.宿地址路由 3.信息量和交互简化 4.安全 5 ...
- 各种学位&不同学段的表达
1.学士 B.S.=Bachelor of Science 2.硕士 Master MA.Sc(master of Science科学硕士) MA.Eng(master of engineer ...
- RWLock——一种细粒度的Mutex互斥锁
RWMutex -- 细粒度的读写锁 我们之前有讲过 Mutex 互斥锁.这是在任何时刻下只允许一个 goroutine 执行的串行化的锁.而现在这个 RWMutex 就是在 Mutex 的基础上进行 ...