前言
本文主要介绍什么是二值信号量和二值信号量的基本操作。
一、什么是二值信号量
信号量名副其实就是一个信号可以进行任务之前信息的交互,二值信号量通常用于互斥访问或同步。二值信号量就是一个只能保存一个数据的队列,这个队列要么是空要么是有他就只有两种状态。
二、cubeMX配置
1.选择添加一个二值信号量
2.设置二值信号量
这里比较简单我们只需要设置一下二值信号量的名字即可。
三、代码编写
1.创建二值信号量
这部分代码cubeMX会帮我们书写好
/* definition and creation of myBinarySem01 */ osSemaphoreDef(myBinarySem01); myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1); /* USER CODE BEGIN RTOS_SEMAPHORES */
2.产生二值信号量函数
本函数cubeMX对其进行了封装,其本质还是调用了xSemaphoreGiveFromISR和xSemaphoreGive两个函数。
/** * @brief Release a Semaphore token * @param semaphore_id semaphore object referenced with \ref osSemaphore. * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. */ osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) { osStatus result = osOK; portBASE_TYPE taskWoken = pdFALSE; if (inHandlerMode()) { if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } else { if (xSemaphoreGive(semaphore_id) != pdTRUE) { result = osErrorOS; } } return result; }
3.接收二值信号量函数
本函数cubeMX也对其进行了封装,其本质还是调用了xSemaphoreTakeFromISR和xSemaphoreTake两个函数。
当二值信号量接收成功的时候会返回osOK。
/** * @brief Wait until a Semaphore token becomes available * @param semaphore_id semaphore object referenced with \ref osSemaphore. * @param millisec timeout value or 0 in case of no time-out. * @retval number of available tokens, or -1 in case of incorrect parameters. * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. */ int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) { TickType_t ticks; portBASE_TYPE taskWoken = pdFALSE; if (semaphore_id == NULL) { return osErrorParameter; } ticks = 0; if (millisec == osWaitForever) { ticks = portMAX_DELAY; } else if (millisec != 0) { ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) { ticks = 1; } } if (inHandlerMode()) { if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) { return osErrorOS; } return osOK; }
四、二值信号量具体操作
osThreadId Task1TaskHandle; osThreadId Task2TaskHandle; void Task1Task(void const * argument); void Task2Task(void const * argument); osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128); Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL); osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128); Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL); //产生二值信号量任务 void Task1Task(void const * argument) { static u8 i=0; for(;;) { //调用10次再产生二值信号量 if(++i==10) { osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量 } osDelay(5);//调用延时才会释放资源 } } //接收二值信号量任务 void Task2Task(void const * argument) { for(;;) { if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式 { //等待二值信号量成功 } osDelay(5);//调用延时才会释放资源 } }
总结
二值信号量的大致操作和介绍就是这样了。