物联网操作系统学习笔记——系统信号量

tech2024-10-25  22

信号量概念及其应用

信号量定义:信号量(semaphore),多任务环境下使用的一种设施,负责协调多个任务,以保证任务能够正确,合理的使用公共资源。

FreeRTOS信号量介绍 FreeRTOS信号量工作原理 二值信号量工作原理 计数信号量工作原理 二值信号量函数应用 功能需求

API详解 xSemaphoreCreateBinary() xSemaphoreGive() xSemaphoreGiveFromISR() xSemaphoreTake() xSemaphoreTakeFromISR() 功能实现: 业务流程 创建信号量

osSemaphoreDef(CpuPrintfBinarySem); CpuPrintfBinarySemHandle = osSemaphoreCreate(osSemaphore(CpuPrintfBinarySem), 1);

在中断中释放信号量

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ xSemaphoreGiveFromISR(CpuPrintfBinarySemHandle, NULL); }

在任务中获取信号量

if(xSemaphoreTake(CpuPrintfBinarySemHandle,portMAX_DELAY) == pdPASS)

计数信号量函数应用

实验操作: 功能需求 1、修改按键功能,模拟停车位出入功能 2、当按键K3按下获取车位 3、当按键K4按下释放车位

API详解: xSemaphoreCreateCounting() uxSemaphoreGetCount() 功能实现 步骤,配置按键 将PF11-设置为GPIO中断输入模式,上下沿触发 使能按键中断

使能USE_COUNTING_SEMAPHORES,置位1

创建计数信号量

osSemaphoreDef(KEYCountingSem); KEYCountingSemHandle = osSemaphoreCreate(osSemaphore(KEYCountingSem), 4); void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ //是不是Key3 if(Key3_Pin == GPIO_Pin){ //Key3是否按下 if(HAL_GPIO_ReadPin(Key3_GPIO_Port,Key3_Pin) == GPIO_PIN_RESET){ //软件去抖动 HAL_Delay(10); if(HAL_GPIO_ReadPin(Key3_GPIO_Port,Key3_Pin) == GPIO_PIN_RESET){ //建立一个标志位 printf("Key3 is down!\r\n"); KeyStatus = KEY_DOWN; if(xSemaphoreTakeFromISR(KEYCountingSemHandle, NULL) == pdPASS){ printf("获取车位成功!\r\n"); }else{ printf("获取车位失败 !车位已经放满\r\n"); } } } }else{ //软件去抖动 HAL_Delay(10); if(HAL_GPIO_ReadPin(Key3_GPIO_Port,Key3_Pin) == GPIO_PIN_SET){ //建立一个标志位 printf("Key3 is up!\r\n"); KeyStatus = KEY_UP; } } //是不是KEY4 if(KEY4_Pin == GPIO_Pin){ //KEY4是否按下 if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin) == GPIO_PIN_RESET){ //软件去抖动 HAL_Delay(10); if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin) == GPIO_PIN_RESET){ //建立一个标志位 printf("KEY4 is down!\r\n"); KeyStatus = KEY_DOWN; if(xSemaphoreGiveFromISR(KEYCountingSemHandle, NULL) == pdPASS){ printf("释放车位成功!\r\n"); }else{ printf("释放车位失败 !车位为空!\r\n"); } } }else{ //软件去抖动 HAL_Delay(10); if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin) == GPIO_PIN_SET){ //建立一个标志位 printf("KEY4 is up!\r\n"); KeyStatus = KEY_UP; } } }

信号量实现原理

信号量创建删除 信号量释放 信号量获取

/* 二值信号量的创建 */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateBinary() /* 1、队列的长度 = 1;二值信号的值 无非就是0和1 2、队列项的长度 = semSEMAPHORE_QUEUE_ITEM_LENGTH = ( ( uint8_t ) 0U ) 消息空间没有意义 3、队列的类型 = queueQUEUE_TYPE_BINARY_SEMAPHORE = ( ( uint8_t ) 3U ) 只用于调试使用 */ xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #endif #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) /* 内部调用消息队列计数信号量的创建,重点分析 */ #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) #endif /* 1、计数信号量的最大值 2、计数信号量的初始值 */ QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) { QueueHandle_t xHandle; //调用消息队列的创建 xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); if( xHandle != NULL ) { //uxMessagesWaiting:将要处理的消息的个数,这个去接收,是不会进入阻塞态的 //赋值为计数信号量的初始值的目的,创建之后,就可以获取信号量,代表可用的资源 ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; traceCREATE_COUNTING_SEMAPHORE(); } else { traceCREATE_COUNTING_SEMAPHORE_FAILED(); } return xHandle; } /* 消息队列的发送和接收,都有阻塞任务的功能 信号量的释放,却没有阻塞参数 参数: 1、信号量的句柄 2、发送的缓冲区 3、阻塞等待时间 = semGIVE_BLOCK_TIME -= ( ( TickType_t ) 0U ) 信号量释放是一个紧急的时间,当信号量资源已经到达最大值时,,就不需要再等待其他任务使用 所以不需要阻塞 4、队列插入方式 = queueSEND_TO_BACK 队尾 */ #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) /* 1、再次封装了消息队列在中断中的发送接口xQueueGiveFromISR 2、区别就是 give没有COPY的功能 ------ 因为信号量不占用内存空间 */ #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) /* 1、句柄 2、接收缓冲区 = NULL 3、阻塞等待时间 4、是否允许 删除消息空间 */ #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) /* 1、句柄 2、接收缓冲区 = NULL 3、NULL */ #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
最新回复(0)