RTOS笔记--任务通知+软件定时器

任务通知的本质

        对于之前使用过的几种互斥操作方式队列,互斥量,信号量,事件组,他们都是黑箱操作,对于写入和读取的任务来说并不知道对方是哪个任务,只是操作环形缓冲区和链表。

        而任务通知的方式就是通知方任务知道要通知具体哪个任务,所以在得到数据或者中断后直接通知接收任务,不需要使用环形缓冲区。

        每个任务都有一个结构体:TCB(Task Control Block),里面有 2 个成员:

                一个是 uint8_t 类型,用来表示通知状态 

                一个是 uint32_t 类型,用来表示通知值

typedef struct tskTaskControlBlock
{....../* configTASK_NOTIFICATION_ARRAY_ENTRIES = 1 */volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];......
} tskTCB;

通知状态有3种取值:

taskNOT_WAITING_NOTIFICATION:任务没有在等待通知,默认状态 

taskWAITING_NOTIFICATION:任务在等待通知

taskNOTIFICATION_RECEIVED:任务接收到了通知,也被称为 pending(有数据了,待处理)

例:有任务AB,当任务B设置为没有等待通知时,即使B在阻塞同时A发来通知也不能唤醒B,但是会将状态置为已经接收到通知,假如后续任务B运行过程中将自己设置为等待通知状态那将不会阻塞直接获取数据并置回默认状态

但当B设置为等待通知的状态后就会进入阻塞状态,此时A发送通知就会唤醒B并更改Value值,在B处理完数据后就会恢复默认状态 。

任务通知操作函数

任务通知有 2 套函数,简化版、专业版,列表如下:

        简化版函数的使用比较简单,它实际上也是使用专业版函数实现的

        专业版函数支持很多参数,可以实现很多功能

使用简化版时:

任务A向任务B发送通知就会将value值累加1并唤醒正在等待通知而阻塞的任务B(调用ulTaskNotifyTake函数进入等待状态),唤醒后value--。

任务B没有在等待,任务A只会将value++但没办法唤醒B

使用专业版时

首先我们需要了解专业版的参数:

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyActio
n eAction );BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify,uint32_t ulValue,eNotifyAction eAction,
BaseType_t *pxHigherPriorityTaskWoken );BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,uint32_t ulBitsToClearOnExit,uint32_t *pulNotificationValue,TickType_t xTicksToWait );

eNotifyAction参数说明: 

 

在任务A调用xTaskNotify函数后一定会将任务B的状态修改为已经接收到的状态

ulBitsToClearOnEntry,
 uint32_t ulBitsToClearOnExit,
 uint32_t *pulNotificationValue,
 TickType_t xTicksToWait

在任务B调用xTaskNotifyWait函数参数ulBitsToClearOnEntry表示任务B不在pending状态下将会清除value中某些位,ulBitsToClearOnExit表示如果是因为收到数据而退出则可以清除value的某些位,在清除前先将通知值赋给value,pulNotificationValue参数表示在收到通知时保存的通知值。

软件定时器

软件定时器的本质

        在freertos系统中有tick线,在线上会产生tick中断,在中断服务函数中就会处理软件定时器。

使用定时器跟使用手机闹钟是类似的,定时器会有一个结构体:

        指定时间:启动定时器和运行回调函数,两者的间隔被称为定时器的周期 (period)。

        指定类型,定时器有两种类型: ◼ 一次性(One-shot timers): 这类定时器启动后,它的回调函数只会被调用一次; 可以手工再次启动它,但是不会自动启动它。 ◼ 自动加载定时器(Auto-reload timers ): 这类定时器启动后,时间到之后它会自动启动它; 这使得回调函数被周期性地调用。

        指定要做什么事,就是指定回调函数

定时器运行方式:

1.每一个定时器都有一个结构体,而这些结构体会放入一个调用的链表中,这些定时器按照到达排列在链表中,在每一次tick中断触发时就会对链表中的定时器进行判断是否有已到达,如果有则调用其函数

2.同样也是tick中断判断是否到达定时器,但是在判断成功后将会通过写队列的方式通知一个timer任务,告知有需要处理的定时器函数,由这个任务进行调用。

对于FreeRTOS来说使用的就是第二种方法。

不仅是定时器回调函数,用户操作定时器的函数也是通过操作队列使得timer运作的,因此定时器timer任务需要有极高的优先级,其优先级可以在cubemx中调节

定时器函数

创建

/* 使用动态分配内存的方法创建定时器
* pcTimerName:定时器名字, 用处不大, 尽在调试时用到
* xTimerPeriodInTicks: 周期, 以 Tick 为单位
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE 表示一次性
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
* pxCallbackFunction: 回调函数
* 返回值: 成功则返回 TimerHandle_t, 否则返回 NULL
*/
TimerHandle_t xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );/* 使用静态分配内存的方法创建定时器
* pcTimerName:定时器名字, 用处不大, 尽在调试时用到
* xTimerPeriodInTicks: 周期, 以 Tick 为单位
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE 表示一次性
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
* pxCallbackFunction: 回调函数
* pxTimerBuffer: 传入一个 StaticTimer_t 结构体, 将在上面构造定时器
* 返回值: 成功则返回 TimerHandle_t, 否则返回 NULL
*/
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer );

修改周期

/* 修改定时器的周期
* xTimer: 哪个定时器
* xNewPeriod: 新周期
* xTicksToWait: 超时时间, 命令写入队列的超时时间
* 返回值: pdFAIL 表示"修改周期命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,TickType_t xNewPeriod,
TickType_t xTicksToWait );/* 修改定时器的周期
* xTimer: 哪个定时器
* xNewPeriod: 新周期
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"修改周期命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,TickType_t xNewPeriod,
BaseType_t *pxHigherPriorityTaskWoken )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/25097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CS.AL】算法复杂度分析 —— 时间复杂度详解

文章目录 1 概述2 时间复杂度的详细分析2.1 常数时间复杂度(O(1))2.2 对数时间复杂度(O(log n))2.3 线性时间复杂度(O(n))2.4 线性对数时间复杂度(O(n log n))2.5 平方时…

程序的基本结构、cout语句(c++语言)

一、如何下载Dev C 登录网站&#xff1a;ht.51goc.com 二、安装Dev C 一、启动Dev C 双击桌面的图标 二、新建一个程序 三、复制一个程序 请你复制以下代码到“程序编辑区” #include<bits/stdc.h> using namespace std; int main() { cout<<"Hell…

计网仿真综合实验 实验十二

实验十二 综合网络实验 实验过程 IP配置说明参考连线配置OSPF使公司内部联通 路由器R1的OSPF配置路由器R2的OSPF配置路由器R3的OSPF配置R1、R2、R3的相关解释路由器R4的OSPF配置路由器R5的OSPF配置路由器R6的OSPF配置R4、R5、R6解释: 路由器R2的RIP配置路由器R7的RIP配置 总结 …

MicroPython esp32 连接wifi 配网

整体流程&#xff1a; 1&#xff09;开启STA 和 AP 模式 2&#xff09;扫描周围wifi 保存在 变量 wifi_list&#xff08;后面要用到&#xff09; 3) 尝试STA模式连接Wifi&#xff0c;并查寻状态。 4) 如果STA 无法连网&#xff0c;就用AP模式&#xff0c;创建热点。 5&a…

【lesson1】第三方库(jsoncpp,bundle, httplib)的介绍和使用

文章目录 jsoncpp库json 认识jsoncpp 认识jsoncpp 实现序列化jsoncpp 实现反序列化 bundle库bundle库实现文件压缩bundle库实现文件解压缩 httplib 库httplib 库搭建简单服务器httplib库搭建简单客户端 jsoncpp库 json 认识 json 是一种数据交换格式&#xff0c;采用完全独立…

【Vscode配置java环境并配置stringboot】

1.VSCODE配置JAVA环境 参考这篇文章配置JAVA环境&#xff1a;连接 java版本&#xff0c;我是win11系统,我下载的JAVA安装版本是下面&#xff0c;是最新版的&#xff1a; 配置环境&#xff1a;步骤很简单&#xff0c;就是向系统环境变量中添加路径&#xff0c;参考上面文章中的…

基于学习模型的可学习小波变换方法(Pytorch)

首先以图像编码为例进行说明。 图像编码是一个复杂的系统&#xff0c;通常包含多个模块&#xff0c;其中变换模块具有重要作用。小波变换在图像编码领域得到了广泛的应用&#xff0c;例如著名的JPEG 2000就是一种小波图像编码方法。然而&#xff0c;现阶段的小波图像编码方法与…

htb-window-1-legacy-smb

nmap smb-vuln-ms08-067 py文件测试失败 msf 漏洞定位 反弹 获取flag

【Oracle篇】rman全库异机恢复:从单机环境到RAC测试环境的转移(第五篇,总共八篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

一文学会Spring 实现事务,事务的隔离级别以及事务的传播机制

目录 一.Spring (Spring Boot) 实现事务 1.通过代码的方式手动实现事务 (手动档的车) 2.通过注解的方式实现声明式事务 (自动挡的车) 二.事务的4大特性(ACID) 三.事务的隔离级别 ①Mysql的事务隔离级别: ②Spring的事务隔离级别: 四.事务的传播机制 ①事务传播机制的概…

验证码案例

目录 前言 一、Hutool工具介绍 1.1 Maven 1.2 介绍 1.3 实现类 二、验证码案例 2.1 需求 2.2 约定前后端交互接口 2.2.1 需求分析 2.2.2 接口定义 2.3 后端生成验证码 2.4 前端接收验证码图片 2.5 后端校验验证码 2.6 前端校验验证码 2.7 后端完整代码 前言…

基于可解释性深度学习的马铃薯叶病害检测

数据集来自kaggle文章&#xff0c;代码较为简单。 import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)# Input data files are available in the read-only "../input/" directory # For example, runni…

快团团供货大团长如何查看帮卖团长的订单?

一、功能说明 可以看到团购中每个帮卖团长帮卖产生的订单 二、具体设置方法 1、小程序端如何操作&#xff1f; 在团购页面中&#xff0c;点击订单管理&#xff0c;在这里可以选择全部团长订单&#xff0c;我的团订单&#xff0c;和帮卖团长的帮卖订单。 2、PC端如何操作&am…

ssm616基于vue.js的购物商场的设计与实现+vue【已测试】

前言&#xff1a;&#x1f469;‍&#x1f4bb; 计算机行业的同仁们&#xff0c;大家好&#xff01;作为专注于Java领域多年的开发者&#xff0c;我非常理解实践案例的重要性。以下是一些我认为有助于提升你们技能的资源&#xff1a; &#x1f469;‍&#x1f4bb; SpringBoot…

【基于C++与OpenCV实现魔方图像识别和还原算法】施工总览图

文章目录 主要效果展示思维导图魔方还原算法 本系列博客长期更新&#xff0c;分为两大部分 OpenCV实现魔方六面识别 C编写科先巴二阶段还原算法实现三阶魔方的还原 主要效果展示 摄像头识别六面 3D图像构建&#xff0c;提供还原公式 动画演示还原过程 思维导图 魔方还原算法 参…

达梦8 开启物理逻辑日志对系统的影响

物理逻辑日志&#xff0c;是按照特定的格式存储的服务器的逻辑操作&#xff0c;专门用于 DBMS_LOGMNR 包挖掘获取数据库系统的历史执行语句。当开启记录物理逻辑日志的功能时&#xff0c;这部分日志内 容会被存储在重做日志文件中。 要开启物理逻辑日志的功能&#xff0c;需要…

社区物资交易互助平台的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;论坛管理&#xff0c;公告信息管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;论坛&#xff0c;求助留言板&#xff0c;公…

SQL Chat:从SQL到SPEAKL的数据库操作新纪元

引言 SQL Chat是一款创新的、对话式的SQL客户端工具。 它采用自然语言处理技术&#xff0c;让你能够像与人交流一样&#xff0c;通过日常对话的形式对数据库执行查询、修改、创建及删除操作 极大地简化了数据库管理流程&#xff0c;提升了数据交互的直观性和效率。 在这个框…

反AI浪潮中的新机遇:Cara艺术社区异军突起

近日,一个名为Cara的艺术社区在网络上迅速走红,其独特的反AI定位吸引了大量创意人士。在AI技术日益普及的今天,Cara社区反其道而行之,致力于打造一个无AI侵害的创作和交流环境。这一创新模式不仅赢得了艺术家的青睐,也为国内创业者提供了新的思考角度。 一、精准定位,守…

C++ list链表的使用和简单模拟实现

目录 前言 1. list的简介 2.list讲解和模拟实现 2.1 默认构造函数和push_back函数 2.2 迭代器实现 2.2.1 非const正向迭代器 2.2.2 const正向迭代器 2.2.3 反向迭代器 2.3 插入删除函数 2.3.1 insert和erase 2.3.2 push_back pop_back push_front pop_front 2.4 构…