FreeRTOS互斥量

目录

一、互斥量的概念

二、优先级翻转和优先级继承

1、优先级翻转

2、优先级继承

三、互斥量相关API

四、优先级实操

1、优先级翻转演示

1.1 CubeMX配置

1.2 代码实现

2、使用互斥量优化优先级翻转问题

2.1 CubeMX配置

2.2 代码实现


一、互斥量的概念

在多数情况下,互斥型信号量和二值型信号量非常相似,但是从功能上二值型信号量用于同步,而互斥型信号量用于资源保护,同时具有“优先级继承”的特性。(注:互斥量不能用于中断服务函数

我们在学习二值信号量的时候知道,该类型信号量的计数值只有0和1,但是他有个特点是:任何任务都可以生产信号量和拿走信号量。举个不太恰当的例子:假设有一个停车位,现在有一辆车停在车位上,按理来说肯定是停车的人自己把车开走后别人才可以停在这吧?但如果把车位看作二值信号量的话,这时候别的车可以把停在车位的车推走,自己将车位空出来,然后给自己停或给别人停。此时就需要引入互斥量。

互斥量有一个特性,谁拿走这个互斥量只能由他释放,也就是只有进行take的任务才可以give互斥量别的任务不能give

互斥量也被称为互斥锁,使用过程如下:
  1.在创建一个互斥量时,初始值为1
  2.当任务A想访问临界资源,先获得并占有互斥量,然后开始访问
  3.如果任务B也想访问临界资源,也要先获得互斥量。但已经被别人占有了,于是只能进行阻塞
  4.当任务A使用完毕,释放互斥量。这时任务B被唤醒、得到并占有互斥量,然后开始访问
  5.任务B使用完毕,释放互斥量

二、优先级翻转和优先级继承

1、优先级翻转

以上图为例,系统中有3个不同优先级的任务H/M/L,最高优先级任务H和最低优先级任务L通过信号量机制,共享资源。目前任务L占有资源,锁定了信号量,Task H运行后将被阻塞直到Task L释放信号量后,Task H才能够退出阻塞状态继续运行。但是Task H在等待Task L释放信号量的过程中,中等优先级任务M抢占了任务L,也就是高优先级任务反而比中等优先级任务更晚执行,从而延迟了信号量的释放时间,导致Task H阻塞了更长时 间,这种现象称为优先级倒置或优先级反转(翻转)。(这里信号量翻转发生于二值信号量,所以后面的实操所创建的信号量应该是二值信号量)

2、优先级继承

当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任 务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。

优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响。

这样做的目的是:

  1. 减少阻塞时间:确保低优先级任务可以快速完成对共享资源的使用,并释放互斥量。
  2. 让高优先级任务尽快执行:一旦低优先级任务释放了互斥量,高优先级任务就可以立即执行。

三、互斥量相关API

互斥信号量不能用于中断服务函数中!

函数描述
xSemaphoreCreateMutex()使用动态方式创建互斥量
xSemaphoreCreateMutexStatic()使用静态方式创建互斥量
xSemaphoreGive()释放互斥量
xSemaphoreTake()获取互斥量
SemaphoreHandle_t xSemaphoreCreateMutex( void )

参数:

返回值:

  • 成功,返回对应互斥量的句柄;
  • 失败,返回 NULL 。

四、优先级实操

1、优先级翻转演示

1.1 CubeMX配置

这里已经将FreeRTOS移植到STM32F103C8T6,具体操作流程看前面的文章。

创建三个任务

优先级选项从上到下一次升高!

创建信号量

1.2 代码实现

 uart.c 重定向printf

#include "stdio.h"
int fputc(int ch,FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;
}

需要打开魔术棒勾上红框内选项实现串口打印

打开freertos.c并添加代码

void StartTaskH(void const * argument)
{
  for(;;)
  {
		xSemaphoreTake(myBinarySemHandle,portMAX_DELAY);
		printf("高优先级获得二值信号量,开始工作\r\n");
		HAL_Delay(1000);
		printf("工作完毕后,释放二值信号量\r\n");
		xSemaphoreGive(myBinarySemHandle);
		osDelay(1000);
  }
}
 
void StartTaskM(void const * argument)
{
  for(;;)
  {
		printf("占用cpu资源,不工作\r\n");
    osDelay(1000);
  }
}
 
void StartTaskL(void const * argument)
{
  for(;;)
  {
		xSemaphoreTake(myBinarySemHandle,portMAX_DELAY);
		printf("低优先级获得二值信号量,开始工作\r\n");
		HAL_Delay(3000);
		printf("工作完毕后,释放二值信号量\r\n");
		xSemaphoreGive(mmyBinarySemHandle);
		osDelay(1000);
  }
}

可见低优先级任务获得信号量时,高优先级想要获得信号量会进入阻塞状态,但此时中优先级会比高优先级先运行,会打断低优先级运行从而使得高优先级阻塞时间增长,当中优先级运行完毕,低优先级才继续运行,当低优先级释放信号量时,高优先级立刻获得信号量;同时当高优先级运行时(获取信号量时),中优先级或者低优先级无法打断。

注意:这里二值信号量的创建用的是CubeMX配置的内置函数,其中已经释放了信号量,所以低优先级任务和高优先级任务可以直接获取信号量再释放。(若是调用二值信号量原本的创建函数,则需要先释放再获取)

2、使用互斥量优化优先级翻转问题

2.1 CubeMX配置

复制上面的文件打开CubeMX配置

删除二值信号量

创建互斥量

2.2 代码实现
void StartTaskH(void const * argument)
{
  for(;;)
  {
		xSemaphoreTake(myMutexHandle,portMAX_DELAY);
		printf("高优先级获得互斥量,开始工作\r\n");
		HAL_Delay(1000);
		printf("工作完毕后,释放互斥量\r\n");
		xSemaphoreGive(myMutexHandle);
		osDelay(1000);
  }
}
 
void StartTaskM(void const * argument)
{
  for(;;)
  {
		printf("占用cpu资源,不工作\r\n");
    osDelay(1000);
  }
}
 
void StartTaskL(void const * argument)
{
  for(;;)
  {
		xSemaphoreTake(myMutexHandle,portMAX_DELAY);
		printf("低优先级获得互斥量,开始工作\r\n");
		HAL_Delay(3000);
		printf("工作完毕后,释放互斥量\r\n");
		xSemaphoreGive(myMutexHandle);
		osDelay(1000);
  }
}

可见低优先级的任务工作后高优先级再进行工作,不会被中优先级打断。

注意:这里是调用CubeMX内置函数,其中已经存在互斥量,所以低优先级和高优先级可以直接获取,不需要先释放再获取。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化训练第6天(美国人口调查获得关于收入与教育背景的数据,并且可视化)

数据来源 https://archive.ics.uci.edu/dataset/2/adult 过程 首先;关于教育背景的部分翻译有问题。 本次使用字典嵌套记录数据,并且通过lambda在sorted内部进行对某个字典的排序,最后用plotly进行绘图 本次提取数据的时候,用到…

Cocos Creator 3.8.x 透明带滚动功能的容器

ScrollView 是一种带滚动功能的容器 1、删除ScrollView下Sprite组件的SpriteFrame 2、ScrollView下scrollBar的Sprite组件的Color设为:FFFFFF00 3、ScrollView下view的Graphics组件的FillColor设为:FFFFFF00

华火5.0台嵌式喷火电燃单灶,更懂未来生活需求

在厨电技术不断革新的今天,第五代华火电燃灶以其独特的技术升级和卓越性能,成功吸引了市场的广泛关注。作为华火品牌的最新力作,第五代电燃灶不仅继承了前代产品的优点,更在多个方面进行了显著的升级和创新。下面,我们…

Unity自定义动画-Animation动画数据-How is “fileIDToRecycleName“ generated

一般美术和程序分工明确的项目 fbx确实是和动画一一对应的; 但一些独立,或者小工作室的项目,就没法保证了,关键还是在于 Unity的 .meta 目录 查找和对比了一下 .fbx 和 .meta: 缓存和不缓存Animation 具体的Animat…

【Python】使用PyTorch训练一个手写数字识别模型(MNIST)

文章目录 1. 准备工作2. 训练网络3. 测试网络4. 训练和测试循环5. 模型保存6. 最终完整代码7. 结果截图使用PyTorch训练一个手写数字识别模型(MNIST) 在这篇博客中,使用了PyTorch构建一个简单的神经网络来识别手写数字。将使用MNIST数据集,这是一个经典的机器学习基准数据集…

电子学会C/C++编程等级考试2024年03月(一级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:倒序输出 依次输入4个整数a、b、c、d,将他们倒序输出,即依次输出d、c、b、a这4个数。 时间限制:1000 内存限制:65536 输入 一行4个整数a、b、c、d,以空格分隔。 0 < a,b,c,d < 108 输出 一行4个整数d、c、b、a,整数之间以…

白话机器学习5:卷积神经网络(CNN)原理

1.神经元 激活函数f(z)的种类&#xff1a; 2.卷积方法种类 https://mp.weixin.qq.com/s/FXzTbMG64jr93Re31Db2EA 标准卷积&#xff08;Standard Convolution&#xff09;: 特点&#xff1a;每个卷积核在输入数据的整个深度上滑动&#xff0c;计算输出特征图的一个元素。应用场…

SQL_hive的连续开窗函数

SQL三种排序&#xff08;开窗&#xff09;第几名/前几名/topN 1三种排序&#xff08;开窗&#xff09;第几名/前几名/topN思路 4种排序开窗函数 1三种排序&#xff08;开窗&#xff09;第几名/前几名/topN 求每个学生成绩第二高的科目-排序思路 t2表&#xff1a;对每个学生 的…

python数据分析——seaborn绘图1

参考资料&#xff1a;活用pandas库 matplotlib库是python的和兴绘图工具&#xff0c;而seaborn基于matplotlib创建&#xff0c;它为绘制统计图提供了更高级的接口&#xff0c;使得只用少量代码就能生成更美观、更复杂的可视化效果。 seaborn库和pandas以及其他pydata库&#xf…

防火请技术基础篇:令牌桶机制的剖析与应用

防火墙中的令牌桶机制&#xff1a;深度剖析与应用 在现代网络通信中&#xff0c;防火墙技术发挥着至关重要的作用&#xff0c;它不仅能够实现网络安全防御&#xff0c;还能通过诸如令牌桶算法等机制来有效管理网络流量&#xff0c;保证网络服务的质量。本文将全面深入地探讨防…

Vue从入门到实战Day05

一、自定义指令 自定义指令&#xff1a;自己定义的指令&#xff0c;可以封装一些dom操作&#xff0c;扩展额外功能 需求&#xff1a;当页面加载时&#xff0c;让元素将获得焦点 (autofocus在safari浏览器有兼容性) 操作dom&#xff1a;dom元素.focus() mounted() {this.$ref…

深度剖析深度神经网络(DNN):原理、实现与应用

目录 引言 一、DNN基本原理 二、DNN核心算法原理 三、DNN具体操作步骤 四、代码演示 引言 在人工智能和机器学习的浪潮中&#xff0c;深度神经网络&#xff08;Deep Neural Network&#xff0c;简称DNN&#xff09;已经成为了一种非常重要的工具。DNN模仿人脑神经网络的结…

SqlServer2016安装

1、下载 下载地址&#xff1a; https://www.microsoft.com/en-us/server-cloud/products/sql-server-2016/ 或者 MSDN, 我告诉你 - 做一个安静的工具站 开发版下载地址&#xff1a;https://myprodscussu1.app.vssubscriptions.visualstudio.com/downloads KB2919442下载地址…

【JVM基础篇】双亲委派机制介绍

文章目录 双亲委派机制简介案例&#xff1a;自底向上查找案例&#xff1a;自顶向下加载案例&#xff1a;C类在当前程序的classpath中 双亲委派机制的作用如何指定加载类的类加载器&#xff1f;面试题如果一个类重复出现在三个类加载器的加载位置&#xff0c;应该由谁来加载&…

Java入门基础学习笔记20——三元运算符、运算符优先级

1、三元运算符介绍&#xff1a; 格式&#xff1a; 条件表达式 ? 值1: 值2 执行流程&#xff1a;首先计算关系表达式的值&#xff0c;如果值为true&#xff0c;就返回值1&#xff0c;如果值为false&#xff0c;就返回值2。 例1&#xff1a; package cn.ensource.operator;p…

【数据结构】详解栈且实现

一.栈 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&#xff1a;…

C--贪吃蛇

目录 前言 简单的准备工作 蛇的节点 开始前 void GameStart(pSnake ps) void WelcomeToGame() void CreateMap() void InitSnake(pSnake ps) void CreateFood(pSnake ps) 游戏进行 void GameRun(pSnake ps) int NextIsFood(pSnakeNode psn, pSnake ps) void NoFood(pSnak…

深入学习指针5,与数组和指针相关的笔试题1(C语言)

前言 Hello,亲爱的小伙伴们&#xff0c;我又来了&#xff0c;&#xff0c;今天呢我们一起来学习一下C语言关于数组和指针的部分经典题目。如果觉得不错的话不要忘了点赞&#xff0c;收藏、关注&#xff0c;你的支持就是我更新的最大动力&#xff01;&#xff01; 好&#xff0…

深度求索推出DeepSeek-V2:经济高效的多专家语言模型

AI苏妲己 深度求索发布了DeepSeek-V2混合专家&#xff08;MoE&#xff09;语言模型&#xff0c;每百万tokens&#xff0c;2元人民币价格&#xff0c;简直便宜到令人发指&#xff08;而且不是活动价格噢&#xff09;&#xff0c;可以说是继Groq以后&#xff0c;AI领域最惊艳的新…

[力扣题解] 96. 不同的二叉搜索树

题目&#xff1a;96. 不同的二叉搜索树 思路 动态规划 f[i]&#xff1a;有i个结点有多少种二叉搜索树 状态转移方程&#xff1a; 以n3为例&#xff1a; 以1为头节点&#xff0c;左子树有0个结点&#xff0c;右子树有2个结点&#xff1b; 以2为头节点&#xff0c;左子树有1个…