我启用了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 */
}
正如 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()。