尝试在带有FreeRTOS的STM32F4发现板上使用二进制信号量会产生一些奇怪的(甚至是错误的)结果。
首先,FreeRTOS的文档说:
SemaphoreHandle_t xSemaphoreCreateBinary(void);
创建二进制信号量的函数。二进制信号量也是 可用,或不可用,因此二进制。
信号量是在“空”状态下创建的,意思是信号量 首先必须先给出,然后才能使用 xSemaphoreTake()函数。
哪个好,因为在这种情况下,一些Thread1等待先前创建的信号量,直到它解除阻塞(Thread2给出信号量),所以听起来很棒!!
首先从stm32f4发现板开始运行FreeRTOS和下面的代码,人们会期望调用osSemaphoreWait(myBinarySem01Handle,osWaitForever)会阻塞线程,直到另一个线程用osSemaphoreRelease解除阻塞,但它不起作用。 似乎在信号量创建之后,需要调用osSemaphoreWait两次以使其工作。
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"
/* USER CODE BEGIN Includes */
#include "gpio.h"
/* USER CODE END Includes */
/* Variables -----------------------------------------------------------------*/
osThreadId defaultTaskHandle;
osThreadId myTask02Handle;
osSemaphoreId myBinarySem01Handle;
osSemaphoreId myBinarySem02Handle;
osSemaphoreId myCountingSem01Handle;
osSemaphoreId myCountingSem02Handle;
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
/* Function prototypes -------------------------------------------------------*/
void StartDefaultTask(void const * argument);
void StartTask02(void const * argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
/* Hook prototypes */
/* Init FreeRTOS */
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* Create the semaphores(s) */
/* definition and creation of myBinarySem01 */
osSemaphoreDef(myBinarySem01);
myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
/* definition and creation of myBinarySem02 */
osSemaphoreDef(myBinarySem02);
myBinarySem02Handle = osSemaphoreCreate(osSemaphore(myBinarySem02), 1);
/* definition and creation of myCountingSem01 */
osSemaphoreDef(myCountingSem01);
myCountingSem01Handle = osSemaphoreCreate(osSemaphore(myCountingSem01), 2);
/* definition and creation of myCountingSem02 */
osSemaphoreDef(myCountingSem02);
myCountingSem02Handle = osSemaphoreCreate(osSemaphore(myCountingSem02), 2);
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* definition and creation of myTask02 */
osThreadDef(myTask02, StartTask02, osPriorityNormal, 0, 128);
myTask02Handle = osThreadCreate(osThread(myTask02), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
}
/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
HAL_GPIO_TogglePin(LD6_GPIO_Port,LD6_Pin);
osSemaphoreWait(myBinarySem01Handle,osWaitForever);
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(LD6_GPIO_Port,LD6_Pin);
osDelay(1000);
}
/* USER CODE END StartDefaultTask */
}
/* StartTask02 function */
void StartTask02(void const * argument)
{
HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin);
osDelay(5000);
osSemaphoreRelease(myBinarySem01Handle);
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin);
osDelay(2000);
}
/* USER CODE END StartTask02 */
}
/* USER CODE BEGIN Application */
/* USER CODE END Application */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
那么这种行为的原因是什么?它在文档中明确指出,sempahore应该在创建后阻止。
答案 0 :(得分:1)
阅读更多文档显示问题,vSemaphoreCreateBinary()宏与xSemaphoreCreateBinary()函数具有不同的语义。
vSemaphoreCreateBinary()宏在第一次调用xSemaphoreTake()时不会阻塞,这与第一次调用xSemaphoreTake()时阻塞的xSemaphoreCreateBinary()大不相同。
答案 1 :(得分:0)
发生这种情况是因为osSemaphoreCreate()函数正在调用vSemaphoreCreateBinary()函数,并且如上所述,该函数创建了一个非空的二进制信号量。