Stm32 二进制信号量在创建后解除阻塞?

Stm32 二进制信号量在创建后解除阻塞?,stm32,freertos,Stm32,Freertos,尝试将STM32F4发现板上的二进制信号量与FreeRTOS一起使用会产生一些奇怪(甚至错误)的结果 首先,FreeRTOS的文档说明: 信号量handle_t xSemaphoreCreateBinary(void) 创建二进制信号量的函数。二进制信号量是 可用或不可用,因此为二进制 信号量是在“empty”状态下创建的,这意味着信号量 必须先给出,然后才能使用 xSemaphoreTake()函数 这很好,因为在这种情况下,一些Thread1会等待前面创建的信号量,直到它解除阻塞(Threa

尝试将STM32F4发现板上的二进制信号量与FreeRTOS一起使用会产生一些奇怪(甚至错误)的结果

首先,FreeRTOS的文档说明:

信号量handle_t xSemaphoreCreateBinary(void)

创建二进制信号量的函数。二进制信号量是 可用或不可用,因此为二进制

信号量是在“empty”状态下创建的,这意味着信号量 必须先给出,然后才能使用 xSemaphoreTake()函数

这很好,因为在这种情况下,一些Thread1会等待前面创建的信号量,直到它解除阻塞(Thread2提供信号量),所以听起来很好

所以,从运行FreeRTOS和下面代码的stm32f4发现板开始,人们会期望对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应该在创建后进行阻止。

阅读更多文档后发现了问题,vSemaphoreCreateBinary()的语义与xSemaphoreCreateBinary()函数不同

vSemaphoreCreateBinary()宏在第一次调用xSemaphoreTake()时不会阻塞,这与xSemaphoreCreateBinary()在第一次调用xSemaphoreTake()时阻塞大不相同


之所以发生这种情况,是因为osSemaphoreCreate()函数正在调用vSemaphoreCreateBinary()函数,如上所述,该函数创建一个非空的二进制信号量