一.信号量定义
信号量(semaphore),多任务环境下使用的一种设施,负责协调多个任务,以保证任务能够正确,合理的使用公共资源。
二.二值信号量应用函数
函数原型 | #include “FreeRTOS.h” #include “semphr.h” SemaphoreHandle_t xSemaphoreCreateBinary( void ); |
功能概述 | 创建二值信号量,并返回信号量句柄。 创建完成后,信号量状态为空。 |
参数 | None |
返回值 | NULL:堆空间不足 Any other value :信号量句柄 |
注意事项 | configSUPPORT_DYNAMIC_ALLOCATION必须置为1 |
函数原型 | #include “FreeRTOS.h” #include “semphr.h” BaseType_t xSemaphoreGive( SemaphoreHandle_t ① xSemaphore ); |
功能概述 | 任务间释放信号量 |
参数 | ①:信号量句柄 |
返回值 | pdPASS:信号量释放成功 pdFAIL: 此信号量,拥有者不是任务,任务需获取到信号量,才可以释放信号 |
注意事项 | None |
函数原型 | #include “FreeRTOS.h” #include “semphr.h” BaseType_t xSemaphoreGiveFromISR( ①SemaphoreHandle_t xSemaphore, ②BaseType_t *pxHigherPriorityTaskWoken ); |
功能概述 | 中断,任务间释放信号量 |
参数 | ①:信号量句柄 ②:表示在释放信号量成功后,是否进行上下文切换,保证高优先级任务立刻执行,FreeRTOS V7.3.0以后变为可选参数,直接设置为NULL |
返回值 | pdTRUE:信号量释放成功 errQUEUE_FULL:信号量已经可用 |
注意事项 | None |
函数原型 | #include “FreeRTOS.h” #include “semphr.h” BaseType_t xSemaphoreTake( ①SemaphoreHandle_t xSemaphore, ②TickType_t xTicksToWait ); |
功能概述 | 任务间获取信号量 |
参数 | ①:信号量句柄 ②:如果信号量不是立即可用,任务则进入阻塞状态,传入的等待多少个tick值,传入portMAX_DELAY任务将无限期等待中 |
返回值 | pdPASS:信号量获取成功 pdFAIL:信号量获取失败 |
注意事项 | 只能在执行的任务中调用 |
函数原型 | #include “FreeRTOS.h” #include “semphr.h” BaseType_t xSemaphoreTakeFromISR( ①SemaphoreHandle_t xSemaphore, ②signed BaseType_t *pxHigherPriorityTaskWoken ); |
功能概述 | 中断中获取信号量 |
参数 | ①:信号量句柄 ②:表示在获取信号量成功后,是否进行上下文切换,保证高优先级任务立刻执行,FreeRTOS V7.3.0以后变为可选参数,直接设置为NULL |
返回值 | pdPASS:信号量获取成功 pdFAIL:信号量获取失败 |
注意事项 | 只能在中断中调用,没有阻塞功能 |
三.任务
3.1CubeMX生成二值信号量
在FreeRTOS中找到Times and Semaphore
在Binary Semaphores中添加
四.代码实现
gpio.c
中断回调函数在gpio中实现
extern osSemaphoreId CPUPrintfBinarySemHandle;
//按键检测回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(Key1_Pin == GPIO_Pin) //判断按下的GPIO
{
if ( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_RESET) //按下按键,导通
{
// HAL_Delay(10); //软件去抖动
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_RESET)
{
// HAL_GPIO_WritePin(GPIOB,Led_Red_Pin,GPIO_PIN_RESET);
// HAL_GPIO_WritePin(GPIOB,Led_Green_Pin,GPIO_PIN_SET);
/*建立标志位*/
keyStatus = Key_down;
printf("按键已按下/r/n");
xSemaphoreGiveFromISR(CPUPrintfBinarySemHandle,NULL);
}
}
else
{
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_SET) // 高电平,未准备好
{
// HAL_Delay(10); //软件去抖动
if( HAL_GPIO_ReadPin(GPIOA,GPIO_Pin) == GPIO_PIN_SET)
{
// HAL_GPIO_WritePin(GPIOB,Led_Red_Pin,GPIO_PIN_SET); //关闭红灯
// HAL_GPIO_WritePin(GPIOB,Led_Green_Pin,GPIO_PIN_RESET); //开启绿灯
/*建立标志位*/
keyStatus = Key_up;
printf("按键已抬起/r/n");
}
}
}
}
}
FreeRTOS.c
void Key_Task(void const * argument)
{
/* USER CODE BEGIN Key_Task */
keyStatus = Key_reset;
/* Infinite loop */
for(;;)
{
if(xSemaphoreTake(CPUPrintfBinarySemHandle,portMAX_DELAY) == pdPASS)
{
//挂起LED任务
memset(u8TaskListBuff,0,400);
vTaskGetRunTimeStats((char*)u8TaskListBuff);
printf("Name Abs Time Time\r\n");
printf("******************************************************\r\n");
printf("%s",u8TaskListBuff);
printf("******************************************************\r\n");
keyStatus = Key_reset;
}
}
/* USER CODE END Key_Task */
}
vTaskGetRunTimeStats
vTaskGetRunTimeStats() 来协助分析操作系统当前 task CPU 占用状态,以帮助优化 task 优先级
函数原型为:
voidvTaskGetRunTimeStats( char *pcWriteBuffer )
CubeMX配置
等待信号量到,才开始执行任务。提高CPU占有利用率