Free RTOS中Semaphore(计数信号量)的使用介绍

目录

 概述

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 数据结构: osSemaphoreAttr_t

3.2 数据结构:StaticSemaphore_t

3.3 数据结构:osSemaphoreId_t

4 计数信号量的使用Demo

4.1 实现功能

4.2 编写测试函数

5 测试


 概述

本文主要介绍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创建的
timeoutCMSIS_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 数据结构: osSemaphoreAttr_t

数据结构参数说明

参数名称描述
name信号量的名称
attr_bits属性位
cb_mem控制块存储器
cb_size为控制块提供的内存大小
/// Attributes structure for semaphore.
typedef struct {
  const char                   *name;   ///< name of the semaphore
  uint32_t                 attr_bits;   ///< attribute bits
  void                      *cb_mem;    ///< memory for control block
  uint32_t                   cb_size;   ///< size of provided memory for control block
} osSemaphoreAttr_t;

3.2 数据结构:StaticSemaphore_t

了解嵌入式实时操作系统中信号的相关知识,就知道每一个信号必须有一个controlBlock,其数据结构定义如下:

信号controlBlock数据结构定义如下:

3.3 数据结构:osSemaphoreId_t

在cmsis_os2.h 文件中定义了osSemaphoreId_t的数据类型为 void

4 计数信号量的使用Demo

4.1 实现功能

代码第39行:定义信号量ID句柄

代码第41行:定义控制块数据结构

代码第43~47行:初始化信号量参数簇

详细代码:
 

/* Definitions for myCountingSem01 */
osSemaphoreId_t myCountingSem01Handle;

osStaticSemaphoreDef_t myCountingSem01ControlBlock;

const osSemaphoreAttr_t myCountingSem01_attributes = {
  .name = "myCountingSem01",
  .cb_mem = &myCountingSem01ControlBlock,
  .cb_size = sizeof(myCountingSem01ControlBlock),
};

代码第58行:创建信号量句柄

详细代码:

void initTask( void )
{
	//myBinarySem01Handle = osSemaphoreNew(1, 1, &myBinarySem01_attributes);

	/* creation of myBinarySem02 */
  //myBinarySem02Handle = osSemaphoreNew(1, 1, &myBinarySem02_attributes);

	/* creation of myCountingSem01 */
	myCountingSem01Handle = osSemaphoreNew(3, 3, &myCountingSem01_attributes);	
}

4.2 编写测试函数

代码第68行:释放计数信号量

代码第71行:获取当前的计数值

代码第85行:获取计数信号量

代码第88行:获取当前的计数值

详细代码:

 void mainTask(void *argument)
{  
    int cnt;
	osStatus_t sem_osStatus;
	
    for(;;)
    {	 
			sem_osStatus = osSemaphoreRelease(myCountingSem01Handle);
			if( sem_osStatus == osOK ){
				  printf("mainTask: osSemaphoreRelease \r\n");	 
				  cnt = osSemaphoreGetCount(myCountingSem01Handle);
				  printf("mainTask osSemaphoreGetCount: %d  \r\n", cnt);
			}
			osDelay(30);
    }
}

void monitorTask(void *argument)
{
	osStatus_t sem_osStatus;
	int cnt;
	
    for(;;)
    {
			sem_osStatus = osSemaphoreAcquire(myCountingSem01Handle, 100);
			if( sem_osStatus == osOK ){
				  printf("monitorTask: osSemaphoreAcquire  \r\n");
				  cnt = osSemaphoreGetCount(myCountingSem01Handle);
				  printf("monitorTask osSemaphoreGetCount: %d  \r\n", cnt);
			}
           osDelay(10);
    }
}

5 测试

编译代码,然后将代码下载到板卡上,运行log如下:

根据计数信号的定义,

1)当Task获取到信号时,count值会减一

2)当Task释放到信号时,count值会加一

结论:

log 打印出来的信息符合信号量使用的要求

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值