二进制信号量在创建后解锁?

时间:2015-12-22 12:19:11

标签: stm32 freertos

尝试在带有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应该在创建后阻止。

2 个答案:

答案 0 :(得分:1)

阅读更多文档显示问题,vSemaphoreCreateBinary()与xSemaphoreCreateBinary()函数具有不同的语义。

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

http://www.freertos.org/xSemaphoreCreateBinary.html

http://www.freertos.org/a00121.html

答案 1 :(得分:0)

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