FreeRTOS-互斥信号量

2023-05-16

原文地址:http://blog.csdn.net/xukai871105/article/details/43456985


0.前言

    在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段。下面结合一个具体例子说明FreeRTOS中的互斥型信号量如何使用。

1.基本说明
    互斥型信号量的使用方法如图1所示。在多数情况下,互斥型信号量和二值型信号非常相似,但是从功能上二值型信号量用于同步,而互斥型信号量用于资源保护。互斥型信号量和二值型信号量还有一个最大的区别,互斥型信号量可以有效解决优先级反转现象。
图1 互斥型信号量使用方法

(1)互斥信号量的简介
在互斥访问中互斥信号量相当于一个钥匙,当任务想要使用资源的时候就必须先获得这个钥匙,当使用完资源以后就必须归还这个钥匙,这样其他的任务就可以拿着这个钥匙去使用资源.
(2)优先级继承
当一个互斥信号量正在被一个低优先级的任务使用,而此时有个高优先级的任务也尝试获取这个这个互斥信号量的话就会被阻塞。不过这个高优先级的任务会将低优先级的任务的优先级提升到与自己相同优先级,这个过程就是优先级继承。
优先级继承尽可能降低了高优先级任务处于阻塞态的时间,并将已经出现的“优先级翻转的影响降低到最低.
(3)互斥信号量不能用在中断服务函数中,原因如下:
互斥信号量具有优先级继承机制,所以只能用在任务中,不能用在中断服务函数中。
中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。
(4)二值信号量 与 互斥信号量的区别
互斥信号量拥有优先级继承机制,二值信号量没有优先级继承机制
二值信号量更加适合用于任务同步,互斥信号量更加适合用于互斥访问

2.参考代码

    本例具有两个任务,两个任务都试图通过串口打印内容,此时串口就好比一个“资源”,某个任务使用串口资源时必须保护该资源,使用完串口之后在释放资源。保护和释放动作便对应互斥型信号量的两个基本操作,xSemaphoreTake和xSemaphoreGive。
    【代码】
/* Standard includes. */
#include <stdio.h>
#include <string.h>

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

/* Library includes. */
#include "stm32f10x.h"

#define LED0_ON()   GPIO_SetBits(GPIOB,GPIO_Pin_5);
#define LED0_OFF()  GPIO_ResetBits(GPIOB,GPIO_Pin_5);

static void Setup(void);
void TaskA( void *pvParameters );
void TaskB( void *pvParameters );

void LedInit(void);
void UART1Init(void);

/* 互斥信号量句柄 */
SemaphoreHandle_t xSemaphore = NULL;

int main(void)
{
    /* 初始化硬件平台 */
    Setup();
    /* 创建互斥信号量 */
    xSemaphore = xSemaphoreCreateMutex();
    /* 建立任务 */
    xTaskCreate( TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+3, NULL );
    xTaskCreate( TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+4, NULL );
    /* 启动OS */
    vTaskStartScheduler();
    
    return 0;
}

void TaskA( void *pvParameters )
{
    for( ;; )
    {
        xSemaphoreTake( xSemaphore, portMAX_DELAY );
        {
            printf("Task A\r\n");
        }
        xSemaphoreGive( xSemaphore );
        vTaskDelay( 2000/portTICK_RATE_MS );
    }
}

void TaskB( void *pvParameters )
{
    for( ;; )
    {
        xSemaphoreTake( xSemaphore, portMAX_DELAY );
        {
            printf("Task B\r\n");
        }
        xSemaphoreGive( xSemaphore );
        vTaskDelay( 1000/portTICK_RATE_MS );
    }
}

static void Setup( void )
{
    LedInit();
    UART1Init();
}

void LedInit( void )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    /*LED0 @ GPIOB.5*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOB, &GPIO_InitStructure );    
}

void UART1Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    /* 第1步:打开GPIO和USART时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
    
    /* 第2步:将USART1 Tx@PA9的GPIO配置为推挽复用模式 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* 第3步:将USART1 Rx@PA10的GPIO配置为浮空输入模式 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* 第4步:配置USART1参数
    波特率   = 9600
    数据长度 = 8
    停止位   = 1
    校验位   = No
    禁止硬件流控(即禁止RTS和CTS)
    使能接收和发送
    */
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    
    /* 第5步:使能 USART1, 配置完毕 */
    USART_Cmd(USART1, ENABLE);
    
    /* 清除发送完成标志 */
    USART_ClearFlag(USART1, USART_FLAG_TC);
    
    /* 使能USART1发送中断和接收中断,并设置优先级 */
    NVIC_InitTypeDef NVIC_InitStructure;
    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    /* 设定USART1 中断优先级 */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    /* 使能接收中断 */
    // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
}

int fputc(int ch, FILE *f)
{
    /* 写一个字节到USART1 */
    USART_SendData(USART1, (uint8_t) ch);
    /* 等待发送结束 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
    {}
    return ch;
}

3.简单说明
SemaphoreHandle_t xSemaphore = NULL;
    申明互斥型信号量,在FreeRTOS中二值型信号量和互斥型信号量类型完全相同。
xSemaphore = xSemaphoreCreateMutex();
    创建互斥型信号量。
xSemaphoreTake( xSemaphore, portMAX_DELAY );
    获得资源的使用权,此处的等待时间为 portMAX_DELAY(挂起最大时间),如果任务无法获得资源的使用权,任务会处于挂起状态。
 xSemaphoreGive( xSemaphore );
    释放资源的使用权。
4.总结
    互斥型信号量和二值型信号量使用方法相似,但二值型信号量用于同步而互斥型信号量用于资源保护。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS-互斥信号量 的相关文章

  • 【FreeRtos学习笔记】STM32 CubeMx——Timers(定时器)

    目录 1 软件定时器 2 示例程序 2 1 例程功能 2 2 步骤 2 3 实验结果 2 4 函数讲解 1 软件定时器 定时器是MCU常用的外设 我们在学习各种单片机时必然会学习它的硬件定时器 但是 MCU自带的硬件定时器资源是有限的 而且
  • FreeRTOS软件定时器创建、复位、开始和停止(备忘)

    目录 一 简介 1 1 开发环境 1 2 摘要 二 STM32CubeIDE配置 三 创建定时器 3 1 头文件声明 3 2 工程文件定义 3 3 创建定时器 3 4 开启 复位 和关闭定时器 四 定时器回调函数 一 简介 1 1 开发环境
  • 解决错误“ #error “include FreeRTOS.h“ must appear in source files before “include event_groups.““例子分享

    今天来给大家分享一下 关于之前自己在学习FreeRTOS过程中遇到的一个错误提示 话不多说 我们直接来看 错误分析 首先 我们看一下错误的提示 error 35 error directive include FreeRTOS h must
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • STM32移植FreeRTOS的Tips

    转自 http bbs armfly com read php tid 7140 1 在FreeRTOS的demo文件夹中拷贝对应的FreeRTOSConfig h文件后 需要加入一行 define configUSE MUTEXES 1
  • ZYNQ中FreeRTOS中使用定时器

    使用普通的Timer中断方式时 Timer中断可以正常运行 但是UDP通信进程无法启动 其中TimerIntrHandler是中断服务程序 打印程序运行时间与从BRAM中读取的数据 void SetupInterruptSystem XSc
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS笔记(十)中断

    中断 当CPU在执行某一事件A时 发生另外一个更重要紧急的事件B请求CPU去处理 产生了中断 于是CPU暂时中断当前正在执行的事件A任务而对对事件B进行处理 CPU处理完事件B后再返回之前中断的位置继续执行原来的事件A 这一过程统称为中断
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • RT-Thread记录(五、RT-Thread 临界区保护与FreeRTOS的比较)

    本文聊聊临界区 以及RT Thread对临界区的处理 通过源码分析一下 RT Thread 对临界区保护的实现以及与 FreeRTOS 处理的不同 目录 前言 一 临界区 1 1 什么是临界区 1 2 RTOS中的临界区 二 RT Thre
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

    关于任务栈和系统栈的基础知识 可以参考之前的随笔 FreeRTOS 任务栈大小确定及其溢出检测 这里再次说明 define configTOTAL HEAP SIZE size t 17 1024 这个宏 官方文档解释 configTOTA
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • C++ freeRTOS任务,非静态成员函数的无效使用

    哪里有问题 void MyClass task void pvParameter while 1 this gt update void MyClass startTask xTaskCreate this gt task Task 204

随机推荐

  • 使用imu_utils工具生成IMU的Allan方差标定曲线

    1 首先 安装ceres依赖项 然后下载编译安装ceres git clone https github com ceres solver ceres solver cd ceres mkdir build cd build cmake m
  • 多线程FutureTask的使用方法和使用实例

    FutureTask是一种可以取消的异步的计算任务 它的计算是通过Callable实现的 xff0c 它等价于可以携带结果的Runnable xff0c 并且有三个状态 xff1a 等待 运行和完成 完成包括所有计算以任意的方式结束 xff
  • Be careful while using autoremove! !

    慎用 apt get autoremove 发表于 2011 年 08 月 01 日 由 淡白色 http www danbaise com 69 html apt get 提供了一个用于下载和安装软件包的简易命令行界面 卸载软件包主要有这
  • 网易面试题(社招)

    转自http blog csdn net zhangpengju999 article details 11818941 时间 xff1a 2013年9月18日 地点 xff1a 网易大厦门户事业部 先是笔试题 xff0c 1小时 一 算法
  • Fast planner 基本原理学习(一)

    一 主题 xff1a Fast planner 基本原理学习 二 目标 xff1a 理解Fast planner轨迹规划处理流程理解hybrid A 的改进点B样条曲线定义 性质 以及所带来的便利 三 正文 xff1a 1 Fast pla
  • 阿里研发一面经历

    人生第一次找工作笔试 面试 xff0c 都碰上了阿里 9月暑假来了 xff0c 才开始准备找工作 xff0c 今年的宣讲来的早 所以现在有点措手不及 xff0c 只能边准备边找 废话不多了 xff0c 进入正题 笔试题 xff0c 下期再论
  • 腾讯2014校园招聘软件后台开发类笔试题

    转http www itmian4 com forum php mod 61 viewthread amp tid 61 3572
  • 2014暴风影音校招技术笔试题(长春站)

    转http www itmian4 com forum php mod 61 viewthread amp tid 61 3622 1 升序排列下列数值 xff1a 2 写出下列函数的返回值 int func int x 61 300 in
  • 计算100以内的素数的个数

    以下代码是用来计算100以内的素数的个数 xff0c 请把相应的空填上 struct prime number node int prime number prime number node next int calc prime numb
  • C语言除法运算符“/”和求余运算符“%”

    看似两个很简单的运算符 xff0c 却也真要掌握用好它也不容易 xff0c 本文作为关于此类运算符的各方面的问题的汇总 xff0c 希望对你我都有一些帮助 除法运算符 二元运算符 xff0c 具有左结合性 参与运算的量均为整型时 xff0c
  • 冒泡排序

    include lt stdio h gt define LENGTH 8 void main int tmp number LENGTH 61 95 45 15 78 84 51 24 12 for i 61 0 i lt LENGTH
  • 金山词霸C++笔试(北邮11月23号)

    金山词霸笔试题 xff08 北邮11月23号 xff09 xff08 一 xff09 以下输出什么 xff1f char ptr 61 34 hello world 34 cout lt lt ptr h ptr指向字符串的首地址 xff0
  • 关于计算机研究和写作的链接收集

    研究相关的资源 What is Research in Computer Science 计算科学的研究是什么 xff1f 翻译 Basic Research Skills in Computer Science 计算科学的基本研究方法 R
  • 实战笔记之C++里面双冒号和冒号及点号引用符

    标题党了额 xff0c mark一下 xff0c 有时间再整理 以下节选自多人博客 推荐博文一篇http blog csdn net gyymen article details 4962873 箭头 xff08 gt xff09 xff1
  • 在Linux中如何修改root帐户的登录用户名

    vi etc passwd 按i键进入编辑状态 修改第1行第1个root为新的用户名 按esc键退出编辑状态 xff0c 并输入 x保存并退出 vi etc shadow 按i键进入编辑状态 修改第1行第1个root为新的用户名 按esc键
  • Linux elasticsearch 安装超详细教程

    1 下载elasticsearch 7 11 2 linux x86 64 tar gz 之所以下载7 11 2版本是因为我使用了中文分词器 xff0c 对应中文分词器的版本号 2 可以官方下载 xff0c 会比较慢 xff0c 这里提供我
  • 程序员做一辈子?

    首先 xff0c 程序员真有必要干一辈子吗 xff1f 如果你是个搬砖的 xff0c 你会考虑一辈子搬砖吗 xff1f 你肯定会想着过几年挣钱了 xff0c 买个车跑运输 xff0c 或者自己做工头 对程序员来说 xff0c 真心没有必要干
  • ubuntu系统怎么使用ifconfig和开启远程连接

    在ubuntu系统刚安装好之后ifconfig命令和开启远程连接都是不起作用的 xff0c 如果需要使ifconfig起作用需要安装一个小工具 xff0c 如果想开启远程连接的话也需要安装open ssh工具 开启ifconfig xff1
  • LDMIA、LDMIB、LDMDB、LDMDA、STMIA、LDMFD、LDMFA、LDMED、LDMEA等指令详解

    关于多寄存器加载存储指令 1 LDMIA指令 LDMIB指令 LDMDB指令 LDMDA指令 xff08 1 xff09 LDMIA指令 xff0c IA表示每次传送后地址加4 xff08 2 xff09 LDMIB指令 xff0c 每次传
  • FreeRTOS-互斥信号量

    原文地址 xff1a http blog csdn net xukai871105 article details 43456985 0 前言 在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段 下面结合一个具体例子说明FreeRTO