FreeRTOS资源管理

server/2024/9/22 17:59:09/

1.以前临界资源的保护方式

有使用过静态局部变量来保护临界资源,也有用队列,信号量,互斥量来保护临界资源。这些都是在多个任务会共同使用临界资源的情况下我们的保护方式。

问题提出:如果有个传感器在读取数据时有严格的时序,如果在读取数据中途被打断,就会读取错误,为了防止这一过程被打断我们会进行一些管理(关闭中断或调度器)。

1.2队列,信号量/互斥量,事件组,任务通知内部如何实现互斥的? 

核心就是谁跟我抢我就屏蔽谁,中断抢我就屏蔽中断,任务要抢我就进制调度器。什么意思呢?举两个例子。

1.2.1队列例子:

我们可以在中断里去写队列,也可以在任务里写队列,所以在写队列的函数里一定是去关闭中断的。我们要知道调度器切换任务也是基于中断的,我只关闭所有中断就可以达到防止任务和中断抢。因此写队列里一定是去关闭中断的。要注意的是关闭中断前先要记录当前中断的状态,再关闭中断,之后在根据记录的当前状态去恢复中断的状态。

写队列源码分析:

中断写队列

从图中可以看出在中断中写队列先记录当前中断状态,在返回中断状态的函数里执行了关闭中断的操作。在第二张图中是xQueueGenericSendFromISR()函数末尾执行的一个恢复中断的一个函数。 

任务写队列:

 

1.2.2事件组例子:

没有中断参与的我们只需要关闭调度器即可,比如事件组,事件组也有在中断中写事件组的函数为什么是关闭调度器呢?

在写事件组函数内部去写一个Timer队列,然后去守护任务会去唤醒定时器任务,在任务里去写事件值。虽然他是在中断中执行的,但是本质是去唤醒一个任务在任务中进行操作我们只需要停止调度器即可无需关中断。

​​

2.如何去关闭中断,如何去关闭调度器?

关闭中断:

关闭中断就是去操作某个寄存器。

关闭调度器:

设置一个变量,把这个变量++,根据这个变量是否为0,去判断是否要切换任务。

切换上下文, 加了之后这个变量就不等于0,就不进行切换。else才是执行任务切换。

2.1在任务中屏蔽中断

在任务中屏蔽中断的示例代码如下:

/* 在任务中,当前时刻中断是使能的* 执行这句代码后,屏蔽中断*/
taskENTER_CRITICAL();/* 访问临界资源 *//* 重新使能中断 */
taskEXIT_CRITICAL();

在 taskENTER_CRITICA()/taskEXIT_CRITICAL() 之间:

  • 低优先级的中断被屏蔽了:优先级低于、等于 configMAX_SYSCALL_INTERRUPT_PRIORITY
  • 高优先级的中断可以产生:优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY
    • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数
  • 任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

这套 taskENTER_CRITICA()/taskEXIT_CRITICAL() 宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用 taskEXIT_CRITICAL() 才会重新使能中断。

使用 taskENTER_CRITICA()/taskEXIT_CRITICAL() 来访问临界资源是很粗鲁的方法:

  • 中断无法正常运行
  • 任务调度无法进行
  • 所以,之间的代码要尽可能快速地执行

2.2 在ISR中屏蔽中断

要使用含有"FROM_ISR"后缀的宏,示例代码如下:

void vAnInterruptServiceRoutine( void )
{/* 用来记录当前中断是否使能 */UBaseType_t uxSavedInterruptStatus;/* 在ISR中,当前时刻中断可能是使能的,也可能是禁止的* 所以要记录当前状态, 后面要恢复为原先的状态* 执行这句代码后,屏蔽中断*/uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();/* 访问临界资源 *//* 恢复中断状态 */taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );/* 现在,当前ISR可以被更高优先级的中断打断了 */
}

在 taskENTER_CRITICA_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR() 之间:

  • 低优先级的中断被屏蔽了:优先级低于、等于 configMAX_SYSCALL_INTERRUPT_PRIORITY
  • 高优先级的中断可以产生:优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY
    • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数
  • 任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

2.3 暂停调度器

如果有别的任务来跟你竞争临界资源,你可以把中断关掉:这当然可以禁止别的任务运行,但是这代价太大了。它会影响到中断的处理。

如果只是禁止别的任务来跟你竞争,不需要关中断,暂停调度器就可以了:在这期间,中断还是可以发生、处理。

使用这2个函数来暂停、恢复调度器:

/* 暂停调度器 */
void vTaskSuspendAll( void );/* 恢复调度器* 返回值: pdTRUE表示在暂定期间有更高优先级的任务就绪了*        可以不理会这个返回值*/
BaseType_t xTaskResumeAll( void );

示例代码如下:

vTaskSuspendScheduler();/* 访问临界资源 */xTaskResumeScheduler();

这套 vTaskSuspendScheduler()/xTaskResumeScheduler() 宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用 taskEXIT_CRITICAL() 才会重新使能中断。

 3.总结

在使用临界资源时,需要严格的读取时序图时我们的管理方式为,在中断中我们就先关闭中断,在任务中我们就暂停调度器,除此之外互斥操作尽可能是使用信号量,互斥量来实现。


http://www.ppmy.cn/server/36030.html

相关文章

【Spring Security注解详解】

Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架,广泛用于Java应用程序中以确保安全。它提供了多种注解来简化安全控制的实现,特别是在方法级别的权限控制上。以下是几个核心的Spring Security注解及其用途的详细介绍: 1…

垂起固定翼+多旋翼无人机+集群组网:高低空域协同组网通信技术详解

垂起固定翼、多旋翼无人机与自组网的结合,为高低空域协同组网通信技术提供了创新的解决方案。这种结合充分利用了各种技术的优势,使得无人机在高低空域中的协同作业和通信更加高效和灵活。 首先,垂起固定翼无人机以其垂直起降能力和长航时的…

微搭低代码入门05文件的上传和下载

目录 1 创建数据源2 创建应用3 创建页面4 设置导航功能5 文件上传6 文件下载总结 小程序中,我们通常会有文件的上传和下载的需,在微搭中,文件是存放在云存储中,每一个文件都会有一个唯一的fileid,我们本篇就介绍如何通…

Kafka源码分析(五) - Server端 - 基于时间轮的延时组件

系列文章目录 Kafka源码分析-目录 一. 背景 Kafka内部涉及大量的"延时"操作,比如收到PRODUCE请求后可为副本等待一个timeout的时间后再响应客户端。 那我们讨论一个问题:Kafka为什么自己实现了一个延时任务组件,而不直接使用ja…

深度学习之基于Pytorch姿态估计的仰卧起坐计数系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 仰卧起坐作为一种常见的健身动作,被广泛用于腹部肌肉的锻炼。然而,对于仰卧起…

【SpringMVC 】什么是SpringMVC(二)?如何整合ssm框架以及使用mybatisPlus?

文章目录 SpringMVC第三章1、ssm整合1、基本步骤1-3步4-5步6步7步8-12步13步14-15步2、添加数据3、删除数据4、配置事务5、修改数据2、pageHelpe分页1、基本步骤第四章1、mybatisPlus1、基本步骤1-45-7892、基本方法的使用查询2、新ssm项目1、基本步骤1-5678-910-111213-15Spri…

SpringBoot-@Transactional注解失效

Transactional注解失效 Transactional失效场景 以下是一些常见导致Transactional注解失效的场景,配合相应的Java代码演示: 1、方法修饰符非公开(非public) Transactional注解失效的原因在于Spring事务管理器如何实现对事务的代…

【智能算法应用】麻雀搜索算法求解非线性方程组问题

目录 1.算法原理2.数学模型3.结果展示4.代码获取 1.算法原理 【智能算法】麻雀搜索算法(SSA)原理及实现 2.数学模型 非线性方程组为: 2 x 1 − x 2 e − x 1 − x 1 2 x 2 e − x 2 (1) \begin{aligned}&2x_1-x_2e^{-x_1}\\&-…