目录
概述
1 使用STM32Cube 配置信号量
1.1 引子
1.2 STM32Cube中配置FreeRTOS
1.3 STM32Cube生成Project
2 cmsis_os中信号量接口函数
2.1 函数:osSemaphoreNew
2.2 函数:osSemaphoreGetName
2.3 函数:osSemaphoreAcquire
2.4 函数:osSemaphoreRelease
2.5 函数:osSemaphoreGetCount
2.6 函数:osSemaphoreDelete
3 使用信号量方法
3.1 定义信号量的变量
3.1.1 数据结构: osSemaphoreAttr_t
3.1.2 数据结构:StaticSemaphore_t
3.1.3 数据结构:osSemaphoreId_t
3.2 一个Demo
3.2.1 定义信号量参数
3.2.2 创建信号量
3.2.3 Task中使用信号量
4 总结
概述
本文主要介绍Free RTOS中Semaphore的使用方法,包括使用STM32Cube中配置FreeRTOS,并且使能Semaphore,还介绍了Free RTOS中Semaphore中相关的函数。还通过一个简单的实例,来介绍Semaphore的使用方法。
1 使用STM32Cube 配置信号量
1.1 引子
笔者使用硬件平台为STM32H750,本文使用STM32CubeMX配置工程代码,并用该工具生成FreeRTOS的相关的Task和Semaphore相关的代码。关于嵌入式实时操作系统中的信号量的概念,笔者已经在其他文章中做了介绍,这里仅仅介绍如何使用FreeRTOS提供的接口,来实现功能。
1.2 STM32Cube中配置FreeRTOS
step-1: 使能FreeRTOS
step-2: 配置信号量参数,笔者配置了3个信号量
1)2个二值信号量
2)一个计数信号量
step-3:配置Task,用于测试信号量的功能,配置3个Task,每个task的优先级相互之间不同
1.3 STM32Cube生成Project
完成Semaphore和Task参数配置后,就可以点击GENERATE生成Project,完成GENERATE之后,打开工程,其项目文件结构如下:
1) 和FreeRTOS相关的代码已经被加载项目中
2) STM32Cube生成的和FreeRTOS相关的应用代码
2 cmsis_os中信号量接口函数
2.1 函数:osSemaphoreNew
函数功能: 创建并初始化一个信号量对象。
函数原型:
osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
参数介绍:
参数名称 | 描述 |
---|---|
max_count | 可用令牌的最大数量 |
initial_count | 可用令牌的初始数量 |
attr | 信号量属性; 默认值: NULL。 |
返回值:
供其他函数参考的信号量ID,如果发生错误则为NULL。
2.2 函数:osSemaphoreGetName
函数功能:获取信号量对象的名称
函数原型:
const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id);
参数介绍:
参数名称 | 描述 |
---|---|
semaphore_id | 获取的信号量ID,这个ID是由osSemaphoreNew创建的 |
返回值:
状态码,表示函数的执行状态。
2.3 函数:osSemaphoreAcquire
函数功能: 获取信号量令牌,如果当前没有令牌,则超时放弃。
函数原型:
osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
参数介绍:
参数名称 | 描述 |
---|---|
semaphore_id | 获取的信号量ID,这个ID是由osSemaphoreNew创建的 |
timeout | CMSIS_RTOS_TimeOutValue,如果没有超时,则为0。 |
返回值:
状态码,表示函数的执行状态
2.4 函数:osSemaphoreRelease
函数功能:释放一个信号量令牌,直到初始最大计数。
函数原型:
osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id);
参数介绍:
参数名称 | 描述 |
---|---|
semaphore_id | 获取的信号量ID,这个ID是由osSemaphoreNew创建的 |
返回值:
状态码,表示函数的执行状态
2.5 函数:osSemaphoreGetCount
功能介绍:获取当前信号量令牌计数。
函数原型:
uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id);
参数介绍:
参数名称 | 描述 |
---|---|
semaphore_id | 获取的信号量ID,这个ID是由osSemaphoreNew创建的 |
返回值:
可用令牌的数量。
2.6 函数:osSemaphoreDelete
功能介绍:删除信号量对象。
函数原型:
osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id);
参数介绍:
参数名称 | 描述 |
---|---|
semaphore_id | 获取的信号量ID,这个ID是由osSemaphoreNew创建的 |
返回值:
状态码,表示函数的执行状态
3 使用信号量方法
3.1 定义信号量的变量
3.1.1 数据结构: osSemaphoreAttr_t
数据结构参数说明
参数名称 | 描述 |
---|---|
name | 信号量的名称 |
attr_bits | 属性位 |
cb_mem | 控制块存储器 |
cb_size | 为控制块提供的内存大小 |
/// Attributes structure for semaphore.
typedef struct {const char *name; ///< name of the semaphoreuint32_t attr_bits; ///< attribute bitsvoid *cb_mem; ///< memory for control blockuint32_t cb_size; ///< size of provided memory for control block
} osSemaphoreAttr_t;
3.1.2 数据结构:StaticSemaphore_t
了解嵌入式实时操作系统中信号的相关知识,就知道每一个信号必须有一个controlBlock,其数据结构定义如下:
信号controlBlock数据结构定义如下:
3.1.3 数据结构:osSemaphoreId_t
在cmsis_os2.h 文件中定义了osSemaphoreId_t的数据类型为 void
3.2 一个Demo
3.2.1 定义信号量参数
代码第16行: 重新定义信号量控制块类型
代码第19行: 定义信号量ID
代码第21行: 定义信号量控制块
代码第23~27行:初始化信号参数簇
源代码
typedef StaticSemaphore_t osStaticSemaphoreDef_t;/* Definitions for myBinarySem01 */
osSemaphoreId_t myBinarySem01Handle;osStaticSemaphoreDef_t myBinarySem01ControlBlock;const osSemaphoreAttr_t myBinarySem01_attributes = {.name = "myBinarySem01",.cb_mem = &myBinarySem01ControlBlock,.cb_size = sizeof(myBinarySem01ControlBlock),
};/* Definitions for myBinarySem02 */
osSemaphoreId_t myBinarySem02Handle;
osStaticSemaphoreDef_t myBinarySem02ControlBlock;
const osSemaphoreAttr_t myBinarySem02_attributes = {.name = "myBinarySem02",.cb_mem = &myBinarySem02ControlBlock,.cb_size = sizeof(myBinarySem02ControlBlock),
};/* Definitions for myCountingSem01 */
osSemaphoreId_t myCountingSem01Handle;
osStaticSemaphoreDef_t myCountingSem01ControlBlock;
const osSemaphoreAttr_t myCountingSem01_attributes = {.name = "myCountingSem01",.cb_mem = &myCountingSem01ControlBlock,.cb_size = sizeof(myCountingSem01ControlBlock),
};
3.2.2 创建信号量
代码第50~53行:创建两个二值信号量
代码第56行:创建一个计数信号量
源代码:
void initTask( void )
{myBinarySem01Handle = osSemaphoreNew(1, 1, &myBinarySem01_attributes);/* creation of myBinarySem02 */myBinarySem02Handle = osSemaphoreNew(1, 1, &myBinarySem02_attributes);/* creation of myCountingSem01 */myCountingSem01Handle = osSemaphoreNew(2, 2, &myCountingSem01_attributes);
}
3.2.3 Task中使用信号量
代码第79行: 申请信号量myBinarySem01Handle
代码第65行: 释放信号量myBinarySem01Handle
详细代码:
void mainTask(void *argument)
{ osStatus_t sem_osStatus;for(;;){ sem_osStatus = osSemaphoreRelease(myBinarySem01Handle);if( sem_osStatus == osOK ){printf("myBinarySem01Handle: osSemaphoreRelease \r\n"); }osDelay(30);}
}void monitorTask(void *argument)
{osStatus_t sem_osStatus;for(;;){sem_osStatus = osSemaphoreAcquire(myBinarySem01Handle, 100);if( sem_osStatus == osOK ){printf("myBinarySem01Handle: osSemaphoreAcquire \r\n");}osDelay(10);}
}
4 总结
1)FreeRTOS的源代码cmsis_os2.h定义了所有的和信号量相关的接口函数
2)使用二值信号量时,需要定义和信号量相关的参数,包括信号量ID,控制块和参数族
3)通过osSemaphoreAcquire函数申请信号
4)通过osSemaphoreRelease释放信号量