当前位置: 首页 > news >正文

2025最新超详细FreeRTOS入门教程:第五章 FreeRTOS信号量

2025最新超详细FreeRTOS入门教程:第五章 FreeRTOS信号量

摘要

在前一章中,我们学习了 消息队列(Queue),它主要用于任务之间传递数据。但在某些场景中,我们并不需要传递数据,只需要实现一种 同步机制(比如“有资源时允许访问”,“某事件发生后允许继续执行”),这时使用 信号量(Semaphore) 更加合适。

FreeRTOS 的信号量基于 队列机制 实现,是实现 任务同步、事件触发、共享资源访问保护 的重要工具。本章将带你全面理解 FreeRTOS 信号量的概念、类型、API 使用、常见应用场景以及和消息队列的区别。

2025最新超详细FreeRTOS入门教程

文章目录

  • 2025最新超详细FreeRTOS入门教程:第五章 FreeRTOS信号量
    • 摘要
    • 一、信号量的基本概念
      • 功能
    • 二、信号量的类型
    • 三、API 使用
      • 1. 创建信号量
      • 2. 获取信号量(Take)
      • 3. 释放信号量(Give)
    • 四、二值信号量的应用
      • 示例:中断通知任务
    • 五、计数型信号量的应用
      • 示例:任务统计事件次数
    • 六、互斥信号量的应用
      • 示例:串口输出保护
    • 七、信号量与队列的区别
    • 八、信号量状态监控
    • 九、常见问题与解决方法
    • 十、经验总结
    • 十一、总结


一、信号量的基本概念

📌 定义:信号量(Semaphore)是一种用于 多任务同步与互斥 的机制,它本质上是一个特殊的消息队列,容量为 1 或更大,但存储的不是数据,而是 一个计数值

功能

  • 任务间同步:一个任务通知另一个任务继续执行
  • 中断与任务同步:ISR 中发信号,任务收到后继续执行
  • 资源管理:实现类似操作系统的 P/V 操作,保证共享资源不会被同时访问

二、信号量的类型

FreeRTOS 提供了三种主要信号量:

类型特点典型应用
二值信号量值为 0 或 1,类似事件触发中断事件通知
计数型信号量可累加,允许多个事件存储事件计数、资源池
互斥信号量特殊的二值信号量,带优先级继承机制防止共享资源竞争
Give
Take
Give
Take
Take/Give
任务A
二值信号量
任务B
计数型信号量
任务C
任务D
互斥信号量

三、API 使用

1. 创建信号量

SemaphoreHandle_t xSemaphoreCreateBinary(void);   // 二值信号量
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount); // 计数信号量
SemaphoreHandle_t xSemaphoreCreateMutex(void);    // 互斥信号量

2. 获取信号量(Take)

BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,TickType_t xTicksToWait
);
  • xTicksToWait:阻塞等待时间
  • 返回值 pdPASS 表示获取成功

3. 释放信号量(Give)

BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);

ISR 中使用:

BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,BaseType_t *pxHigherPriorityTaskWoken
);

四、二值信号量的应用

示例:中断通知任务

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"SemaphoreHandle_t xBinarySemaphore;void vTaskHandler(void *pvParameters)
{for(;;){if(xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdPASS){printf("任务被中断唤醒!\n");}}
}void EXTI0_IRQHandler(void)  // 按键中断
{BaseType_t xHigherPriorityTaskWoken = pdFALSE;xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}int main(void)
{HAL_Init();SystemClock_Config();xBinarySemaphore = xSemaphoreCreateBinary();xTaskCreate(vTaskHandler, "Handler", 128, NULL, 2, NULL);vTaskStartScheduler();while(1) {}
}

运行结果

  • 当按键触发中断时,任务 Handler 被唤醒,执行相应逻辑

五、计数型信号量的应用

示例:任务统计事件次数

SemaphoreHandle_t xCountingSemaphore;void vTaskConsumer(void *pvParameters)
{for(;;){if(xSemaphoreTake(xCountingSemaphore, portMAX_DELAY) == pdPASS){printf("处理一个事件\n");}}
}void EXTI0_IRQHandler(void)
{BaseType_t xHigherPriorityTaskWoken = pdFALSE;xSemaphoreGiveFromISR(xCountingSemaphore, &xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}int main(void)
{HAL_Init();SystemClock_Config();xCountingSemaphore = xSemaphoreCreateCounting(10, 0);xTaskCreate(vTaskConsumer, "Consumer", 128, NULL, 2, NULL);vTaskStartScheduler();
}
  • 每次按键触发中断,信号量计数值 +1
  • 消费任务依次取出,处理事件

六、互斥信号量的应用

互斥信号量(Mutex)用于 资源保护,保证同一时刻只有一个任务访问共享资源。
其区别在于 支持优先级继承:当低优先级任务占有资源时,高优先级任务会暂时提升低优先级任务的优先级,避免“优先级反转”。

示例:串口输出保护

SemaphoreHandle_t xMutex;void vTaskA(void *pvParameters)
{for(;;){xSemaphoreTake(xMutex, portMAX_DELAY);printf("Task A 输出...\n");vTaskDelay(500);xSemaphoreGive(xMutex);vTaskDelay(1000);}
}void vTaskB(void *pvParameters)
{for(;;){xSemaphoreTake(xMutex, portMAX_DELAY);printf("Task B 输出...\n");vTaskDelay(500);xSemaphoreGive(xMutex);vTaskDelay(1000);}
}

七、信号量与队列的区别

特性队列信号量
传递数据
同步机制次要
ISR 使用支持支持
内部实现FIFO 缓冲区基于队列封装
典型应用生产者-消费者事件触发、资源互斥

八、信号量状态监控

FreeRTOS 提供 uxSemaphoreGetCount() 来查询信号量计数值:

UBaseType_t uxSemaphoreGetCount(SemaphoreHandle_t xSemaphore);

示例:

printf("当前信号量数量: %d\n", uxSemaphoreGetCount(xCountingSemaphore));

九、常见问题与解决方法

问题原因解决方法
任务无法被唤醒信号量未 Give确认 ISR 或任务正确释放信号量
死锁任务未释放信号量确保 xSemaphoreGive 在所有逻辑路径中调用
优先级反转使用普通二值信号量使用 Mutex
中断中报错使用了非 ISR API替换为 xSemaphoreGiveFromISR

十、经验总结

📌 开发建议

  1. 二值信号量 适合任务同步,特别是中断与任务之间的触发关系
  2. 计数信号量 适合事件计数,避免事件丢失
  3. 互斥信号量 适合资源保护,优先级继承机制能有效防止优先级反转
  4. 尽量避免在高频中断中频繁使用信号量,可能导致系统负担过重

十一、总结

通过本章学习,你已经掌握:

  • FreeRTOS 提供的三类信号量(Binary、Counting、Mutex)
  • 信号量的 API 使用与应用场景
  • 任务同步与共享资源保护的方法
  • 信号量与队列的区别

信号量是 RTOS 最常用的同步机制,后续我们会进一步学习 互斥量、事件组 等更复杂的同步方法。


🔗 FreeRTOS专栏👉 下一章:2025最新超详细FreeRTOS入门教程:第六章 FreeRTOS互斥量 ——进一步探讨多任务环境下的资源保护与并发访问。



文章转载自:

http://jYp6nHY4.Lstmg.cn
http://eCvIcRxW.Lstmg.cn
http://2BvJt6C1.Lstmg.cn
http://iTcdne5S.Lstmg.cn
http://UWA7xWYi.Lstmg.cn
http://7AkiHSTY.Lstmg.cn
http://S6VZECvL.Lstmg.cn
http://sIsipfFB.Lstmg.cn
http://kzxKvKx5.Lstmg.cn
http://SGsyou1x.Lstmg.cn
http://SyJTBArh.Lstmg.cn
http://WmBrPxA0.Lstmg.cn
http://Aq5Ba6OR.Lstmg.cn
http://I3Ghaqre.Lstmg.cn
http://BgPL5KDZ.Lstmg.cn
http://FTT4ONWU.Lstmg.cn
http://aez4UtD7.Lstmg.cn
http://365Y5zvy.Lstmg.cn
http://JHozSfDW.Lstmg.cn
http://QhNpRLOl.Lstmg.cn
http://28hQ8VWY.Lstmg.cn
http://AxOZsI38.Lstmg.cn
http://VLpFIoZ4.Lstmg.cn
http://RRXuUkKu.Lstmg.cn
http://vaOkioUW.Lstmg.cn
http://Ml9cQDXu.Lstmg.cn
http://Li7nZQ6m.Lstmg.cn
http://oHsmGL7r.Lstmg.cn
http://nKsxMRz6.Lstmg.cn
http://gF5IvD89.Lstmg.cn
http://www.dtcms.com/a/372614.html

相关文章:

  • 安卓逆向(二)相关问题及解决方案
  • 自学嵌入式第37天:MQTT协议
  • daily notes[11]
  • Qt中QProxyStyledrawControl函数4个参数的意义
  • AutoHotkey识别图片
  • 【数学建模】在烟雾导弹遮蔽模型中的实际参考文献
  • 快速了解word2vec模型
  • 关于高并发的一连串问题分析(未完成)
  • Ansible Playbook 核心配置实操指南:主机清单引用、并行执行与模块化组织
  • 2025年金融专业人士职业认证发展路径分析
  • NVM 使用指南(Node Version Manager)
  • 2025年体制内职业发展相关认证选择指南
  • 电脑提速之关于Edge优化
  • 图像纹理相似度评价——Gabor变换
  • [光学原理与应用-463]:波动光学 - AOM的0级光与1级光
  • SpringBoot 公共字段自动填充
  • 《计算》第一二章读书笔记
  • 多模态大模型---第1节
  • 删除字符串中的空格
  • STM32 开发(三十三)STM32F103 片内资源 —— 直接存储 DMA 实战 编码详解
  • MGSM:大模型多语言数学推理的“试金石”
  • 卫星直连服务:从稀疏星座到全球覆盖的未来通信革命
  • FastAPI:像搭建餐厅一样设计API
  • 基于CNN-SE Attention和SHAP可解释性分析的故障诊断matlab
  • 企业级 Django 日志配置示例
  • URL 重写机制深度解析
  • OneCode可视化动作参数类型详解(一):核心枚举类ActionTypeEnum深度解析
  • Proxychains 配置全解析:从入门到高级应用
  • 第13章 非参数检验【9】:非参数检验和参数检验
  • (二)蓝牙架构概述-通俗易懂