目录
快速体验FreeRTOS所有常用API(1)工程创建
快速体验FreeRTOS所有常用API(2)任务管理
快速体验FreeRTOS所有常用API(3)同步与互斥
快速体验FreeRTOS所有常用API(4)队列
快速体验FreeRTOS所有常用API(5)信号量、互斥量
快速体验FreeRTOS所有常用API(6)事件组
快速体验FreeRTOS所有常用API(7)任务通知
快速体验FreeRTOS所有常用API(8)软件定时器
快速体验FreeRTOS所有常用API(9)中断管理
快速体验FreeRTOS所有常用API(10)资源管理
快速体验FreeRTOS所有常用API(11)打印空闲栈、CPU占用比
五、信号量、互斥量
该部分在上份代码基础上修改得来,代码下载链接:
https://wwzr.lanzout.com/iez6S1l8ldmh 信号量
密码:g3xq
https://wwzr.lanzout.com/iMDz11l8ldbg 互斥量
密码:6i4f
该代码尽量做到最简,不添加多余的、不规范的代码。
内容主要包括:
(1)信号量的概念、创建、获取、释放。
(2)互斥量的概念、创建、获取、释放。
最终实现效果:
(1)信号量:使用计数型信号量,设置初值为2,同时只允许2个任务的运行。因为任务创建顺序,1、3先执行,先获得信号量,等任务1或3 释放信号量后,任务2才能执行。
(2)互斥****量:使用互斥量,对OLED这个共享资源进行互斥保护,替换之前用全局变量做的简陋互斥。
5.1 信号量基本概念
信号量是一种用于在任务之间进行同步和通信的机制。信号量主要用于控制对共享资源的访问,防止多个任务同时访问导致的竞态条件。
使用场景:
- 保护共享资源:信号量常用于保护共享资源,确保一次只有一个任务能够访问该资源。任务在访问共享资源之前必须获取信号量,使用完后释放信号量。
- 同步任务:信号量可用于同步多个任务的执行顺序。一个任务可能需要等待另一个任务完成某个操作,通过信号量的等待和释放机制,可以实现任务的同步。
- 有限资源控制: 计数信号量可以用于限制对某个有限资源的访问。例如,控制同时访问某个共享设备的任务数量。
5.2.1 信号量-创建
使用 xSemaphoreCreateBinary
或 xSemaphoreCreateCounting
函数来创建信号量。
二进制信号量(Binary Semaphore):
SemaphoreHandle_t xSemaphore = xSemaphoreCreateBinary();
计数型信号量(Counting Semaphore):
SemaphoreHandle_t xSemaphore = xSemaphoreCreateCounting(uxMaxCount, uxInitialCount);
/*
uxMaxCount:信号量的最大计数值。
uxInitialCount:信号量的初始计数值。
*/
示例:
// 定义信号量句柄
static SemaphoreHandle_t g_xSemaphoreTest;
// 创建计数型信号量,初始计数为2,最大计数为3
g_xSemaphoreTest = xSemaphoreCreateCounting(3, 2);
5.2.2 信号量-获取
使用 xSemaphoreTake
函数获取信号量。如果信号量的计数大于零,则计数减一,并继续执行。如果计数为零,任务将被阻塞等待信号量。
BaseType_t xResult = xSemaphoreTake(xSemaphore, xTicksToWait);
/*
xTicksToWait:等待的时钟节拍数,若为0,则立即返回;若为portMAX_DELAY,则无限等待。
*/
示例:
/* 获得信号量 如果计数值为0,则阻塞*/
xSemaphoreTake(g_xSemaphoreTest, portMAX_DELAY);
5.2.3 信号量-释放
使用 xSemaphoreGive
函数释放信号量。如果有任务在等待该信号量,则其中一个将被唤醒。
BaseType_t xResult = xSemaphoreGive(xSemaphore);
示例:
/* 释放信号量 */
xSemaphoreGive(g_xSemaphoreTest);
5.2.4 实例
定义
获取、释放
5.3.1 互斥量-创建
互斥量是一种特殊的信号量。
互斥量是一种用于确保在任意时刻只有一个任务能够访问共享资源的同步机制。
在多任务系统中,任务A正在使用某个资源,还没用完的情况下任务B也来使用的话,就可能导致问题。
比如对于串口,任务A正使用它来打印,在打印过程中任务B也来打印,客户看到的结果就是A、B的信息混杂在一起。
比如OLED,任务1正在用,任务2也来用,就会出错,之前用的是全局变量的方式来实现的OLED这个共享资源的保护。现在改用正规的互斥量。
使用 xSemaphoreCreateMutex
函数来创建互斥量。
/* 创建一个互斥量,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateMutex( void );
示例:
// 定义互斥量句柄
static SemaphoreHandle_t g_xMutexTest;
// 创建互斥量
g_xMutexTest= xSemaphoreCreateMutex();
5.3.2 互斥量-获取
各类操作函数,跟一般是信号量是一样的。
/* 等待一个互斥量 */
xSemaphoreTake(g_xMutexTest, portMAX_DELAY);
5.3.3 互斥量-释放
各类操作函数,跟一般是信号量是一样的。
/* 释放互斥量 */
xSemaphoreGive(g_xMutexTest);
5.3.4 实例
创建
获取、释放