如何在STM32H的FreeRTOS中获取信号量并从另一个任务中释放它?

问题描述 投票:0回答:1

我启用了TIM1并创建了3个任务,其中最高优先级任务将获取信号量并休眠10秒,之后普通优先级任务将休眠10秒并释放信号量,之后较低优先级任务将获取信号量信号量并闪烁 LED 但这并没有发生,只有较高优先级的任务正在获取信号量,等待 10 秒,然后它再次获取信号量

问题出在哪里??

我已在此处附上代码片段

void StartHighTask(void *argument)
{
  /* USER CODE BEGIN StartHighTask */
  /* Infinite loop */
  for(;;)
  {
      if ( osSemaphoreAcquire(BinSemHandle, osWaitForever)== osOK){
                    char *s1 = " Semaphore Acquired by High Task\n\r";
                    HAL_UART_Transmit(&huart3, (uint8_t*)s1, strlen(s1), 1000);
                    HAL_Delay(10000);


                  }

                  else {
                    char *s3 = " Waiting for the Semaphore \n\r";
                HAL_UART_Transmit(&huart3, (uint8_t*)s3, strlen(s3), 1000);
                  }


    osDelay(1000);
  }
  /* USER CODE END StartHighTask */
}

/* USER CODE END Header_StartNormalTask */
void StartNormalTask(void *argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
      HAL_Delay(10000);
      osSemaphoreRelease(BinSemHandle);
      char *s2 = " Semaphore released by Normal Task\n\r";
      HAL_UART_Transmit(&huart3, (uint8_t*)s2, strlen(s2), 1000);

    osDelay(1000);
  }
  /* USER CODE END 5 */
}

/* USER CODE END Header_StartLowTask */
void StartLowTask(void *argument)
{
  /* USER CODE BEGIN StartLowTask */
  /* Infinite loop */
  for(;;)
  {
      if ( osSemaphoreAcquire(BinSemHandle, osWaitForever)== osOK){

                    char *s1 = " Semaphore Acquired by low Task\n\r";
                    HAL_UART_Transmit(&huart3, (uint8_t*)s1, strlen(s1), 1000);

                    osDelay(1000);
                    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 1);
                    HAL_Delay(500);
                    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 0);

                    char *s2 = " Semaphore released by low Task\n\r";
                    HAL_UART_Transmit(&huart3, (uint8_t*)s2, strlen(s2), 1000);
                osSemaphoreRelease(BinSemHandle);


                  }

                  else {
                    char *s3 = " Waiting for the Semaphore \n\r";
                HAL_UART_Transmit(&huart3, (uint8_t*)s3, strlen(s3), 1000);
                  }

    osDelay(1000);
  }
  /* USER CODE END StartLowTask */
}
stm32 stm stm32h7 stm32-hal
1个回答
0
投票

正如 HS2 所提到的,您必须将 HAL_Delay 调用替换为 osDelay 调用,这是一个 FreeRTOS 函数。

原因是osDelay内部使用了vTaskDelay()。操作系统将收到有关所请求的延迟(以刻度为单位)的通知,并将在该特定时间段内将任务状态更改为阻止。

osStatus osDelay (uint32_t millisec)
{
#if INCLUDE_vTaskDelay
  TickType_t ticks = millisec / portTICK_PERIOD_MS;

  vTaskDelay(ticks ? ticks : 1);          /* Minimum delay = 1 tick */

  return osOK;
#else
  (void) millisec;

  return osErrorResource;
#endif
}

另一方面,HAL_Delay是STM32 HAL(硬件抽象层)的一部分,而不是FreeRTOS的一部分。因此它无法通知操作系统。

__WEAK void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}

最后,附注,使用 FreeRTOS,您不能在空闲任务中使用 osDelay,如文档所述,因为:

必须始终至少有一项任务准备好运行。因此,钩子函数必须不调用任何可能导致空闲任务阻塞的 API 函数 (vTaskDelay() [...]

在这种特定情况下,您可以使用 HAL_Delay()。

© www.soinside.com 2019 - 2024. All rights reserved.