FreeRTOS学习之路,以STM32F103C8T6为实验MCU(2-6:信号量)

news2024/11/27 22:31:14

学习之路主要为FreeRTOS操作系统在STM32F103(STM32F103C8T6)上的运用,采用的是标准库编程的方式,使用的IDE为KEIL5。

注意!!!本学习之路可以通过购买STM32最小系统板以及部分配件的方式进行学习,也可以通过Proteus仿真的方式进行学习。

后续文章会同时发表在个人博客(jason1016.club)、CSDN;

视频会发布在bilibili(UID:399951374)

信号量概念

信号量常常用于控制对共享资源的访问和任务同步,我的理解是:信号量就是全局定义的存储数据,任何任务以及中断都可以对其进行访问以及写入操作。实现一个资源的共享。

一、二值信号量

1、概念

二值信号量通常用于互斥访问或同步。二值信号量,顾名思义他的状态只有1和0,即他的状态只有接收到信号和未接收到信号。我的理解是:把他理解成一个标志位。他的作用在于在中断标志二值信号,然后再任务中释放信号量,实现中断标志事件(告诉系统,这个要执行了),在由任务执行事件(由任务进行执行操作)。大大避免了因此中断过久导致的系统冗余。

二值信号量的使命就是同步,完成任务与任务或中断与任务之间的同步

2、二值信号量的创建

//动态创建方案(新版)
SemaphoreHandle_t xSemaphoreCreateBinary( void ) //xSemaphore:保存创建成功的二值信号量句柄。
/*返回值
    NULL: 二值信号量创建失败。
    其他值: 创建成功的二值信号量的句柄。*/    

3、释放(发送)和获取信号量

释放信号量

//任务级
BaseType_t xSemaphoreGive( xSemaphore ) //xSemaphore:要释放的信号量句柄。
/*返回值: 
    pdPASS: 释放信号量成功。
    errQUEUE_FULL: 释放信号量失败。*/

//中断级
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, // xSemaphore: 要释放的信号量句柄。
                                  BaseType_t * pxHigherPriorityTaskWoken) //pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之前一定要进行一次任务切换。
/*返回值:
    pdPASS: 释放信号量成功。
    errQUEUE_FULL: 释放信号量失败。*/

获取信号量

//任务级
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, //xSemaphore:要获取的信号量句柄。
                          TickType_t xBlockTime) //xBlockTime: 阻塞时间。
/*返回值:
    pdTRUE: 获取信号量成功。
    pdFALSE: 超时,获取信号量失败。*/
    
//中断级
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore, //xSemaphore: 要获取的信号量句柄。
                                 BaseType_t * pxHigherPriorityTaskWoken) //pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这三个函数来设置的,用户不用进行设置,用户只需要提供一个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退出中断服务函数之前一定要进行一次任务切换。
/*返回值
    pdPASS: 获取信号量成功。
    pdFALSE: 获取信号量失败。*/

二、计数型信号量

1、概念

同二值信号量一样,用户不需要关心队列中存储了什么数据,只需要关心队列是否为空即可

1、事件计数

在这个场合中,每次事件发生的时候就在事件处理函数中释放信号量(增加信号量的计数值),其他任务会获取信号量(信号量计数值减一,信号量值就是队列结构体成员变量uxMessagesWaiting)来处理事件。在这种场合中创建的计数型信号量初始计数值为 0。

2、资源管理

在这个场合中,信号量值代表当前资源的可用数量,比如停车场当前剩余的停车位数量。一个任务要想获得资源的使用权,首先必须获取信号量,信号量获取成功以后信号量值就会减一。当信号量值为 0 的时候说明没有资源了。当一个任务使用完资源以后一定要释放信号量,释放信号量以后信号量值会加一。在这个场合中创建的计数型信号量初始值应该是资源的数量,比如停车场一共有 100 个停车位,那么创建信号量的时候信号量值就应该初始化为 100。

我的理解是:计数型信号量同样是作为一个标志位的类型存在于系统当中的,而计数型与二值信号的不同之处为:二值信号只能释放(挂起)一次,之后就要等待获取(消除)了;而计数型可以释放多次并且叠加计数,然后再慢慢获取信号量实现(消除)操作。

 2、计数型信号量的创建

//动态的方法
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, //uxMaxCount: 计数信号量最大计数值,当信号量值等于此值的时候释放信号量就会失败。
                                           UBaseType_t uxInitialCount ) //uxInitialCount: 计数信号量初始值。
/*返回值
    NULL: 计数型信号量创建失败。
    其他值: 计数型信号量创建成功,返回计数型信号量句柄。*/

3、信号量的释放和获取

同上

uxSemaphoreGetCount()

获取数值信号量的信号值

//获取数值信号量的信号值
uxSemaphoreGetCount(SemaphoreHandle_t xSemaphore)//xSemaphore:要获取的信号量句柄
/*返回值:
    数值信号量值*/

三、优先级翻转

在使用二值信号量的时候会遇到很常见的一个问题——优先级翻转,优先级翻转在可剥夺内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能会导致严重的后果。

当一个低优先级任务和一个高优先级任务同时使用同一个信号量,而系统中还有其他中等优先级任务时。如果低优先级任务获得了信号量,那么高优先级的任务就会处于等待状态,但是,中等优先级的任务可以打断低优先级任务而先于高优先级任务运行(此时高优先级的任务在等待信号量 ,所以不能运行),这是就出现了优先级翻转的现象。

既然优先级翻转是个很严重的问题,那么有没有解决方法呢?有!这就要引出另外一种信号量——互斥信号量

四、互斥信号量(解决优先级翻转问题)

1、概念

互斥信号量其实就是一个拥有优先级继承的二值信号量量,在同步的应用中(任务与任务或中断与任务之间的同步)二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中。在互斥访问中互斥信号量相当于一个钥匙,当任务想要使用资源的时候就必须先获得这个钥匙,当使用完资源以后就必须归还这个钥匙,这样其他的任务就可以拿着这个钥匙去使用资源。

互斥信号量也可以设置阻塞时间,不同于二值信号量的是互斥信号量具有优先级继承的特性。当一个互斥信号量正在被一个低优先级的任务使用,而此时有个高优先级的任务也尝试获取这个互斥信号量的话就会被阻塞。不过这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级,这个过程就是优先级继承。优先级继承尽可能的降低了高优先级任务处于阻塞态的时间,并且将已经出现的“优先级翻转”的影响降到最低。优先级继承并不能完全的消除优先级翻转,它只是尽可能的降低优先级翻转带来的影响。硬实时应用应该在设计之初就要避免优先级翻转的发生。互斥信号量不能用于中断服务函数中,原因如下:

● 互斥信号量有优先级继承的机制,所以只能用在任务中,不能用于中断服务函数

● 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。

2、互斥信号量的创建

//动态创建
SemaphoreHandle_t xSemaphoreCreateMutex( void )
/*返回值
    NULL: 互斥信号量创建失败。
    其他值: 创建成功的互斥信号量的句柄。*/

3、互斥信号的释放和获取

同上

五、递归互斥信号量

1、概念

递归互斥信号量可以看作是一个特殊的互斥信号量,已经获取了互斥信号量的任务就不能再次获取这个互斥信号量,但是递归互斥信号量不同,已经获取了递归互斥信号量的任务可以再次获取这个递归互斥信号量,而且次数不限!一个任务使用函数 xSemaphoreTakeRecursive()成功的获取了多少次递归互斥信号量就得使用函数 xSemaphoreGiveRecursive()释放多少次!比如某个任务成功的获取了 5 次递归信号量,那么这个任务也得同样的释放 5 次递归信号量。递归互斥信号量也有优先级继承的机制,所以当任务使用完递归互斥信号量以后一定要记得释放。

同互斥信号量一样,递归互斥信号量不能用在中断服务函数中。

● 由于优先级继承的存在,就限定了递归互斥信号量只能用在任务中,不能用在中断服务函数中

● 中断服务函数不能设置阻塞时间。要使用递归互斥信号量的话宏 configUSE_RECURSIVE_MUTEXES 必须为 1!

2、递归互斥信号量的创建

//动态方法
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )

/*返回值: 
    NULL: 互斥信号量创建失败。
    其他值: 创建成功的互斥信号量的句柄。*/

3、递归互斥信号量的释放与获取

递归互斥信号量_释放函数

xSemaphoreGiveRecursive()

递归互斥信号量_获取函数

xSemaphoreTakeRecursive()

//释放函数
xSemaphoreGiveRecursive(SemaphoreHandle_t xSemaphore)//xSemaphore:要释放的信号量句柄
/*返回值:
     pdPASS:递归互斥信号量释放成功
     pdFAIL:递归互斥信号量释放未成功*/
     
//获取函数
xSemaphoreTakeRecursive(SemaphoreHandle_t xSemaphore,//xSemaphore:要释放的信号量句柄
                        TickType_t xBlockTime) //xBlockTime: 阻塞时间。
/*返回值:
    pdPASS:递归互斥信号量获取成功
    pdTRUE: 从队列中读取数据成功。//第一次获取递归互斥信号量
    pdFALSE: 从队列中读取数据失败。//第一次获取递归互斥信号量 */

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

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

相关文章

Spring Boot 改版如何解决?使用阿里云创建项目、使用IDEA进行创建

接上次博客:JavaEE进阶(2)SpringBoot 快速上手(环境准备、Maven:核心功能,Maven仓库、第⼀个SpringBoot程序:Spring介绍,Spring Boot介绍、创建项目)-CSDN博客 目录 使…

ESP32和ESP8266的ESP-MESH

ESP32和ESP8266的ESP-MESH 功能介绍一、介绍ESP-MESH二、安装painlessMesh库三、ESP-MESH基本示例(广播消息)四、示范 功能介绍 了解如何使用ESP-MESH网络协议通过ESP32和ESP8266 NodeMCU板构建网状网络。 ESP-MESH允许多个设备(节点&#x…

[Java] 阿里一面~说一下ArrayList 与 LinkedList 区别

文章目录 是否保证线程安全底层数据结构插入和删除是否受元素位置的影响是否支持快速随机访问内存空间占用: 是否保证线程安全 ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 底层数据结构 ● ArrayList 底层使用的是 Obje…

windows安装yarn

1、不要用npm装,因为npm安装的没有配置环境变量; 2、 用github搜yarn,点击排名第一的,然后点击releases 3、往下拉找到msi这几个字母的,然后就是下一步,下一步就行

深度学习第3天:CNN卷积神经网络

☁️主页 Nowl 🔥专栏《机器学习实战》 《机器学习》 📑君子坐而论道,少年起而行之 ​ 文章目录 介绍 CNN的主要结构 卷积层 激励层 池化层 Kears搭建CNN 搭建代码 直观感受卷积的作用 结语 介绍 卷积神经网络(Convol…

单片机学习2——流水灯的实现

#include<reg52.h>sbit LED P1^0; unsigned char i;void main() {while(1){LED 0;for(i0;i<100;i);LED 1;for(i0;i<100;i);} } RST是复位按钮&#xff0c;单击一下之后&#xff0c;程序就会跑到最开始的位置运行。 右侧的按钮是RUN按钮&#xff0c;单击下&…

【华为OD】B\C卷真题:100%通过:找城市 C/C++实现

【华为OD】B\C卷真题&#xff1a;100%通过&#xff1a;找城市 C/C实现 题目描述&#xff1a; 一张地图上有n个城市&#xff0c;城市和城市之间有且只有一条道路相连&#xff1a;要么直接相连&#xff0c;要么通过其它城市中转相连&#xff08;可中转一次或多次&#xff09;。…

项目去除git版本控制

我 | 在这里 &#x1f575;️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 &#x1f3e0; 工作 | 广州 ⭐ Java 全栈开发&#xff08;软件工程师&#xff09; &#x1f383; 爱好 | 研究技术、旅游、阅读、运动、喜欢流行歌曲 ✈️已经旅游的地点 | 新疆-乌鲁木齐、新疆-吐鲁番、广东-广州…

【深度学习】DAMO-YOLO,阿里,701类通用检测模型,目标检测

https://github.com/tinyvision/DAMO-YOLO/blob/master/README_cn.md DAMO-YOLO是由阿里巴巴达摩院智能计算实验室TinyML团队开发的一个兼顾速度与精度的目标检测框架,其效果超越了目前的一众YOLO系列方法&#xff0c;在实现SOTA的同时&#xff0c;保持了很高的推理速度。DAMO…

中伟视界:创新解决方案,搭建自适应的AI算法模型训练平台

搭建AI算法模型自训练平台是当今人工智能领域的热门话题&#xff0c;但是其中存在着许多技术难点需要克服。 自训练平台需要具备高效的算法模型&#xff0c;这就要求能够处理庞大的数据量并进行高速计算。 平台需要具备强大的数据管理及存储能力&#xff0c;以满足训练过程中的…

Typescript基础面试题 | 02.精选 ts 面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

串口通信基础知识介绍

一、串行通讯与并行通讯 在通信和计算机科学中&#xff0c;串行通信(Serial Communication)是一个通用概念&#xff0c;泛指所有的串行的通信协议&#xff0c;如RS232、RS422、RS485、USB、I2C、SPI等。 串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行传输的一种…

2023年网络安全比赛--综合渗透测试②(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 1.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将扫描开放的所有端口当作flag提交(例:21,22,23); 2.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将初…

智能优化算法应用:基于海鸥算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于海鸥算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于海鸥算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.海鸥算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

智能优化算法应用:基于斑点鬣狗算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于斑点鬣狗算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于斑点鬣狗算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.斑点鬣狗算法4.实验参数设定5.算法结果6.参考…

2018年4月26日 Go生态洞察:Go新品牌形象及标识发布

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

电子画册制作,谁能拒绝有这么好用的模板平台!

电子画册是我们生活中经常见到的&#xff0c;但很多人不知道电子画册是如何制作的&#xff0c;总觉得只有专业人士才能创作出来。其实不然&#xff0c;电子画册制作也可以很简单&#xff0c;就算是零基础小白也可以轻松上手&#xff0c;关键是找到一款可靠的制作工具。 在这方…

我的创作纪念日-----MySql服务

MySql服务 1.什么是数据库 1.1.数据 描述事物的符号记录&#xff0c;可以是数字文字、图形、图像、声音、语言等&#xff0c;数据有多种形式&#xff0c;它们都可以经过数字化后存入计算机。 1.2.数据库 存储数据的仓库&#xff0c;是长期存放在计算机内、有组织、可共享的大…

<JavaEE> Java中线程有多少种状态(State)?状态之间的关系有什么关系?

目录 一、系统内核中的线程状态 二、Java中的线程状态 一、系统内核中的线程状态 状态说明就绪状态线程已经准备就绪&#xff0c;随时可以接受CPU的调度。阻塞状态线程处于阻塞等待&#xff0c;暂时无法在CPU中执行。 二、Java中的线程状态 相比于系统内核&#xff0c;Java…

C++局域网从服务器获取已连接用户的列表(linux to linux)

目录 服务器端 代码 客户端 代码解析 服务器端 原理 遇到的阻碍以及解决办法 客户端 原理 遇到的阻碍以及解决办法 运行结果截图 总结 服务器端 代码 #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet…