5.FreeRTOS学习笔记- 互斥量
基本概念
- 互斥量又称互斥信号量(本质是信号量),是一种特殊的二值信号量
- 互斥量 支持互斥量所有权、递归访问以及防止优先级翻转的特性,用于实现对临界资源(如显示器、打印机)的独占式访问。
- 任意时刻互斥量的状态只有两种,开锁或闭锁。
- 持有该互斥量的任务也能够重复获得这个锁而不被挂起,这就是递归访问,也就是递归互斥量的特性,信号量重复获取则会被挂起
- 互斥量与二值信号量最大的不同是:互斥量具有优先级继承机制,而信号量没有
优先级继承机制
- 优先级继承算法是指,暂时提高某个占有某种资源的低优先级任务的优先级,使之和所有等待该资源的任务中优先级最高那个任务的优先级相等,而当这个低优先级任务执行完毕释放该资源时,优先级重新回到初始设定值
- 优先级提升的过程叫做优先级继承
优先级翻转
高优先级任务无法运行而低优先级任务可以运行的现象称为“优先级翻转”
互斥量应用场景
- 可能会引起优先级翻转的情况
- 任务可能会多次获取互斥量的情况下。这样可以避免同一任务多次递归持有而造成死锁的问题
- 多任务环境下往往存在多个任务竞争同一临界资源的应用场景,互斥量可被用于对临界资源的保护从而实现独占式访问
- 例如串口资源的保护
函数
头文件
#include <semphr.h>
互斥量句柄
和消息队列一样
QueueHandle_t
控制块
互斥量控制块结构体与消息队列结构体是一模一样的,只不过结构体中某些成员变量代表的含义不一样而已
typedef struct QueueDefinition
{int8_t *pcHead; int8_t *pcTail; int8_t *pcWriteTo; union {int8_t *pcReadFrom; UBaseType_t uxRecursiveCallCount; //当结构体用于互斥量时,uxRecursiveCallCount 用于计数,记录递归互斥量被“调用”的次数} u;List_t xTasksWaitingToSend; List_t xTasksWaitingToReceive; volatile UBaseType_t uxMessagesWaiting;/* 这个值就表示有效互斥量个数,这个值是 1则表示互斥量有效,如果是 0 则表示互斥量无效*/UBaseType_t uxLength; /*
如果控制块结构体被用于互斥量的时候,uxLength 表示最大的信号量可用个数,uxLength 最大为 1,因为信号量要么是有效的,要么是无效的*/UBaseType_t uxItemSize; /*如果控制块结构体被用于互斥量的时候,则无需存储空间,为 0 即可。 */volatile int8_t cRxLock; volatile int8_t cTxLock; #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated; #endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;
函数接口
创建互斥量xSemaphoreCreateMutex()
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
递归互斥量创建函数 xSemaphoreCreateRecursiveMutex()
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
互斥量删除函数 vSemaphoreDelete()
和信号量一样的函数
互斥量获取函数 xSemaphoreTake()
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
参数 | 说明 |
---|---|
xSemaphore | 信号量句柄 |
xBlockTime | 等待信号量可用的最大超时时间,单位为 tick(即系统节拍周期)。如果宏 INCLUDE_vTaskSuspend 定义为 1 且形参xTicksToWait 设置为 portMAX_DELAY ,则任务将一直阻塞在该信号量上(即没有超时时间) |
返回值 | 获 取 成 功 则 返 回 pdTRUE , 获取失败 返 回 errQUEUE_EMPTY。 |
递归互斥量获取函数 xSemaphoreTakeRecursive()
#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
/*。返回值 获取成功则返回 pdTRUE,在超时之前没有获取成功则返回 errQUEUE_EMPTY。*/
参数 | 说明 |
---|---|
xMutex | 信号量句柄 |
xBlockTime | 如果不是持有互斥量的任务去获取无效的互斥量,那么任务将进行等待用户指定 超时时间,单位 为 tick(即系统节拍周期) 。如果宏 INCLUDE_vTaskSuspend 定义为 1 且形参 xTicksToWait 设置为portMAX_DELAY ,则任务将一直阻塞在该递归互斥量上(即没有超时时间)。 |
返回值 | 获 取 成 功 则 返 回 pdTRUE , 获取失败 返 回 errQUEUE_EMPTY。 |
互斥量释放函数 xSemaphoreGive()
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore ) #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
/*
如果信号量满,则返回错误代码(err_QUEUE_FULL)
*/
递归互斥量释放函数 xSemaphoreGiveRecursive()
#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
示例:
之前2个任务的优先级一样,导致就是发送信号任务要打印,接收信号端不打印,引入锁后问题解决
#include "FreeRTOS.h"
#include "task.h"
#include<bsp_key.h>
#include "semphr.h"
#include <stdio.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static TaskHandle_t send_Task_Handle = NULL;
static TaskHandle_t recv_Task_Handle = NULL;
static SemaphoreHandle_t xsem=NULL;
static SemaphoreHandle_t xlock=NULL;static void recv_Task(void * param)
{uint32_t data1;while (1){if(pdTRUE==xSemaphoreTake(xsem,portMAX_DELAY)){xSemaphoreTake(xlock,portMAX_DELAY );printf("take sem\r\n");xSemaphoreGive(xlock);HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);}}}static void send_Task(void * param)
{uint32_t data1=10;while (1){if(Key_Scan(KEY1_GPIO_Port,KEY1_Pin)==KEY_ON){xSemaphoreGive(xsem);xSemaphoreTake(xlock,portMAX_DELAY );printf("give sem\r\n");xSemaphoreGive(xlock);}vTaskDelay(100);}}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */printf("hello FreeRTOS\r\n");//xqueue = xQueueCreate(10, 4);xsem = xSemaphoreCreateBinary();xlock = xSemaphoreCreateMutex();if(xsem==NULL){printf("create queue fail\r\n");}BaseType_t xReturn;xReturn = xTaskCreate((TaskFunction_t) recv_Task, /* 任务入口函数 */(const char *) "recv_Task", /* 任务名字 */(uint16_t) 512, /* 任务栈大小 */(void *) NULL, /* 任务入口函数参数 */(UBaseType_t) 2, /* 任务的优先级 */(TaskHandle_t *) &recv_Task_Handle); /* 任务控制块指针 */xReturn = xTaskCreate((TaskFunction_t) send_Task, /* 任务入口函数 */(const char *) "send_Task", /* 任务名字 */(uint16_t) 512, /* 任务栈大小 */(void *) NULL, /* 任务入口函数参数 */(UBaseType_t) 2, /* 任务的优先级 */(TaskHandle_t *) &send_Task_Handle); /* 任务控制块指针 */if (pdPASS == xReturn)vTaskStartScheduler(); /* 启动任务,开启调度 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);HAL_Delay(50);}/* USER CODE END 3 */
}
5.FreeRTOS学习笔记- 互斥量相关推荐
- FreeRTOS个人笔记-互斥量
根据个人的学习方向,学习FreeRTOS.由于野火小哥把FreeRTOS讲得比较含蓄,打算在本专栏尽量细化一点.作为个人笔记,仅供参考或查阅. 配套资料:FreeRTOS内核实现与应用开发实战指南.野 ...
- FreeRTOS学习笔记——互斥型信号量
来自:http://blog.csdn.net/xukai871105/article/details/43456985 0.前言 在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段.下面结合一 ...
- freertos 创建互斥量_STM32CubeMX+FreeRTOS学习[6] 互斥量(Lu)
FreeRTOS 学习之六:互斥量 前提:默认已经装好 MDK V5 和 STM32CubeMX ,并安装了 STM32F1xx 系列的支持包. 硬件平台: STM32F1xx 系列. 目的:学习互斥 ...
- RT-Thread学习笔记——互斥量
前言 前面学习了RT-Thread的信号量,但信号量在一些场合使用会存在优先级翻转问题,接下来我们学习互斥量,在 RT-Thread 操作系统中,互斥量可以解决优先级翻转问题,实现的是优先级继承算法. ...
- C++11学习笔记-----互斥量以及条件变量的使用
在多线程环境中,当多个线程同时访问共享资源时,由于操作系统CPU调度的缘故,经常会出现一个线程执行到一半突然切换到另一个线程的情况.以多个线程同时对一个共享变量做加法运算为例,自增的汇编指令大致如下, ...
- FreeRTOS学习笔记
FreeRTOS学习笔记 (这是我自己学习FreeRTOS整理的笔记,仅供参考) 第一部分:实现FreeRTOS内核 变量名: 定义变量时往往会把变量的类型当作前缀加在变量上 变量类型 前缀 char ...
- 1、野火freertos学习笔记
野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...
- freeRtos学习笔记 (7)信号量
freeRtos学习笔记 freeRtos信号量 信号量种类 信号量分为四种:二值信号量,互斥信号量,计数信号量和递归互斥信号量,其中计数信号量用于管理系统多个共享资源,用计数值表示可用资源数目;二值 ...
- FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析
FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析 怎么查找就绪任务中优先级最高的? tasks.c中声明了一个全局变量 uxTopReadyPriority,任务从其他状态进入就绪 ...
最新文章
- 在Simulink中创建库
- guava_使用Google Guava Cache进行本地缓存
- js怎么实现对html代码加密解密,javascript脚本加密解密及HTML转JS
- SQL 连接字符串的说明(转)
- 咋样查mysql的url_eclipse用jdbc连接mysql数据库时,url是填什么?怎样找出地址?
- python pyquery安装_win7下python安装pyquery
- 01-02 Linux常用命令-文件处理
- 微软MCITP系列课程(十)WSUS服务器搭建
- 图论 - 寻找fly真迹
- IPOP下的tcl脚本
- vs2010 sp1安装
- Qt数据库应用3-数据打印到pdf
- 支付宝芝麻信用分申请
- 解决UWP应用无法使用本地代理
- 一线互联网互联网架构师自述:GitHub标星10w+,2021最新Android笔经
- veu +Apipost下拉框选项绑定数据库
- Unity 2018升级2020后XR报错error CS0619: ‘XRDevice.isPresent‘ is obsolete
- 计算机网络序号是什么,Excel序号是什么 Excel序号详细介绍
- Excel:批量将某字符替换为“换行符”
- MT4自定义指标导入方法
热门文章
- dlsym 如何查看一个so里面的_如何查看并且使用android系统本身包含的so库?
- php 中间表统计,多对多中间表详解
- SpringCloud Consul Config 配置中心 (二)
- 解决appium-inspector连接后在Appium中报错:No route found for /sessions
- linux nohup后台执行管道操作
- python json转dict(dict转json)
- flink java生成流式数据
- java对csv格式的读写操作
- python filter函数 字符串_Python实现filter函数实现字符串切分
- mysql df_DF学Mysql(一)——数据库基本操作