freertos内部机制——队列

本文介绍了在并发编程中如何通过读写队列和使用中断机制实现任务的互斥,以及队列的创建、读写过程,包括休眠与唤醒操作,涉及环形缓冲区和定时唤醒机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、互斥的引出

        在两个同优先级的任务里共同对一个变量进行操作(a++)时,根据汇编可以知道:定义变量时a被存在栈中,对a操作a++时,首先需要LDR取出a,在a+1,然后STR存入栈中。两个任务都是如此操作,倘若两个任务谁没有完全执行完(即互斥),都不会使a连续++。在任务调度时,有一个固定时间片会转换任务,导致单个任务中不可能完全执行完,所以实现任务的互斥很重要。

        怎样实现呢?可以通过读写队列中的关闭tick中断实现任务无法调度来实现任务间的互斥。

2、队列的休眠与唤醒

        

3、队列的环形缓冲区

队列的创建:在创建队列的函数中有两个参数,一个是队列长度,一个是吸收项目大小,都是形容环形缓冲区的。在队列结构体中,与任务的唤醒和休眠相关的离不开两个链表变量。

队列的读:1、首先会关闭中断,2、然后判断队列里元素的个数,如果大于零,就会读。2_1、在2的条件下读完后,会判断链表waitingtoset里面是不是空,如果不是空,就唤醒,具体操作是把waitingtoset里的任务移除,并把此任务从delaylist移到readylist。3、如果队列里面没有元素,可以选择不等待,输出结果为erro,也可以选择等待,此时任务休眠,具体操作是任务有readylist移到delaylist,并在waitingtoreceive中添加此任务以等待唤醒。

队列读和写第一步都是读完判断写,写完判断读

队列的写:1、首先会关闭中断,2、判断队列里当前的元素和满载时元素的个数,如果符合,则写入2_1、写完后直接判断waitingtoreceive链表中有没有等待的任务,如果有,就把此任务从delaylist移到readylist,并从waitingtoreceive中删除。3、如果队列满了,要么不等待,输出error,要么等待,把此任务从readylist移到delaylist,在waitingtoset添加。

等待时长:可由自己设置,设置后在tick中断中比较是否到达唤醒时间

### FreeRTOS 定时器管理机制的原理与实现 #### 1. 软件定时器概述 FreeRTOS 中的软件定时器是一种基于系统节拍(Tick)的时间管理工具,它不需要额外的硬件资源即可完成周期性或一次性任务调度。这种机制的核心是由 **定时器服务任务(Timer Service Task)** 来驱动和维护。 #### 2. 工作原理 软件定时器的工作流程可以分为以下几个方面: - **系统节拍中断** FreeRTOS 使用一个全局变量 `TickCount` 记录当前系统的节拍次数,在每次发生系统节拍中断时会更新该变量[^1]。这个变量作为整个定时器框架的基础时间轴。 - **定时器列表结构** 所有已创建的软件定时器会被存储在一个双向链表中,这些定时器按照到期时间排序。当某个定时器被激活后,其到期时间将相对于当前的 `TickCount` 进行计算并插入到合适的位置[^2]。 - **超时检测逻辑** 在每个系统节拍到来时,定时器服务任务会对所有未过期的定时器进行扫描,判断是否有任何定时器已经到达设定的时间点。如果发现某定时器到期,则执行相应的回调函数,并根据配置决定是否重新加载计数值以支持自动重启模式[^1]。 #### 3. 关键数据结构 以下是 FreeRTOS 软件定时器的一些重要定义及其作用: ```c typedef struct xTIMER { List_t xGenericList; /* 链接至活动/挂起队列 */ uint8_t ucControlBits; /* 控制标志位 */ const char *pcTimerName; /* 名字指针用于调试目的 */ TickType_t xPeriod; /* 时间间隔单位为ticks */ UBaseType_t uxAutoReload; /* 自动重载标记 */ pdTASK_CODE pxCallbackFunction;/* 用户指定的回调方法地址 */ } Timer_t; ``` 这段代码展示了 `Timer_t` 结构体的主要成员字段以及它们的功能描述[^2]。 #### 4. 主要操作过程 下面详细介绍几个核心的操作环节: - **初始化阶段** 创建一个新的软件定时器实例之前需要调用 API 函数如 `xTimerCreate()` ,此过程中分配内存空间给新的对象并将初始参数赋值进去[^1]。 - **启动与停止** 利用命令消息通知方式来请求开启或者关闭特定编号下的计时进程;例如发送 START 或 STOP 类型的消息包进入专用通信管道以便后续处理[^2]。 - **动态调整行为** 支持在线修改某些属性比如延时期限长度等特性,这通常涉及到再次同步刷新内部状态信息的动作[^1]。 #### 5. 可靠性的保障措施 为了应对可能出现的各种异常状况,例如长时间运行期间可能发生整数类型的回绕现象等问题,采用了双缓冲区切换策略——即把即将到期的一组记录临时保存下来单独对待直到确认完毕后再放回去继续参与正常循环比较运算之中从而避免遗漏任何一个事件的发生时刻[^2]。 --- ### 示例代码片段 这里提供了一个简单的例子展示如何设置一个基本的 FreeRTOS 软件定时器: ```c void vTimerCallback(TimerHandle_t xTimer) { // 当前定时器触发后的动作写在这里... } int main(void){ TimerHandle_t xTimer; // 创建一个名为 "OneShotTimer" 的单发式定时期望持续时间为 100 ticks. xTimer = xTimerCreate( "OneShotTimer", // 定时器名称 100, // 周期 (Ticks) pdFALSE, // 单次触发而非重复触发 NULL, // 不传递附加参数 vTimerCallback ); // 设置回调函数 if( xTimer != NULL ){ // 启动刚刚建立好的那个定时装置。 xTimerStart(xTimer , 0 ); // 开始 RTOS 调度程序让一切运转起来! vTaskStartScheduler(); } return 0 ; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值