【Freertos】外部中断&高优先级级任务&任务通知

外部中断&高优先级级任务

前言:在外部中断种发送一个任务通知,引起任务切换到高优先级任务,在任务中运行耗时长的函数 BMI088_read(gyro, accel, &temp);

ulTaskNotifyTake(pdTRUE, portMAX_DELAY)

当任务调用 ulTaskNotifyTake 函数时,它将进入阻塞状态,等待接收任务通知。ulTaskNotifyTake 函数的第一个参数是一个布尔值,用于指定是否要清除任务通知的计数值。在这种情况下,参数 pdTRUE 意味着在接收到任务通知后,将自动清除计数值。

ulTaskNotifyTake 函数的第二个参数是一个超时值,用于指定任务在等待任务通知时的最长等待时间。在这里,portMAX_DELAY 表示任务将一直等待,直到接收到任务通知。

如果任务在等待任务通知期间没有被其他地方发送的任务通知唤醒,那么任务将一直保持阻塞状态。只有当任务通知被发送,并且任务成功接收到通知(返回值为 pdPASS),任务才会从 ulTaskNotifyTake 函数中解除阻塞并继续执行。

在给定的代码中,任务可能在 ulTaskNotifyTake(pdTRUE, portMAX_DELAY) != pdPASS 这一行卡住的原因可能是任务没有接收到任务通知。这可能是由于其他地方没有发送任务通知,或者发送的任务通知没有成功到达该任务。你可以检查任务通知的发送代码,确保任务通知被正确发送,并且任务通知的接收者正确处理了接收任务通知的逻辑。

portYIELD_FROM_ISR(xHigherPriorityTaskWoken)

在 FreeRTOS 中,中断服务函数通常不能直接调用任务切换函数(如 taskYIELD()),因为它们运行在中断上下文中,具有较高的优先级。为了在中断服务函数中触发任务切换,可以将任务切换请求传递给 FreeRTOS 内核,由内核在适当的时候进行任务切换。

portYIELD_FROM_ISR(xHigherPriorityTaskWoken) 宏的作用是将任务切换请求传递给 FreeRTOS 内核,并根据参数 xHigherPriorityTaskWoken 的值来确定是否进行任务切换。如果 xHigherPriorityTaskWoken 的值为 pdTRUE,则表示有更高优先级的任务需要立即执行,内核将在退出中断服务函数后立即进行任务切换。如果 xHigherPriorityTaskWoken 的值为 pdFALSE,则表示没有更高优先级的任务需要立即执行,内核将在合适的时机进行任务切换。

在给定的代码中,xHigherPriorityTaskWoken 是在 vTaskNotifyGiveFromISR 函数中传递的指针,用于指示是否有更高优先级的任务需要立即执行。如果 xHigherPriorityTaskWoken 的值为 pdTRUE,则任务切换请求将被触发。如果 xHigherPriorityTaskWoken 的值为 pdFALSE,则任务切换请求将被忽略。

这段代码来自RobomasterC板示例
void StartTask02(void *argument)
{
  osDelay(500);
  PID_init(&imu_temp_pid, PID_POSITION, imu_temp_PID, TEMPERATURE_PID_MAX_OUT, TEMPERATURE_PID_MAX_IOUT);
  uint8_t i = BMI088_init();
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {

    Error_Handler();
  }
  printf("%d", i);
  HAL_TIM_PWM_Start(&htim10, TIM_CHANNEL_1);
  INS_task_local_handler = xTaskGetHandle(pcTaskGetName(NULL));
  imu_start_flag = 1;
  // printf("ok?");
  for (;;)
  {
     while (ulTaskNotifyTake(pdTRUE, portMAX_DELAY) != pdPASS)
     {
       printf("ok?");
       vTaskDelay(300);
    }
     printf("ok?");
    BMI088_read(gyro, accel, &temp);

    vTaskDelay(20);
    PID_calc(&imu_temp_pid, temp, 40.0f);
    if (imu_temp_pid.out < 0.0f)
    {
      imu_temp_pid.out = 0.0f;
    }
    tempPWM = (uint16_t)imu_temp_pid.out;
    imu_pwm_set(tempPWM);
    printf("l:%f,%d\n",temp,tempPWM);
  }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == INT1_ACCEL_Pin)
  {

    if (imu_start_flag)
    {
      // wake up the task
      // 唤醒任务
      if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
      {
        static BaseType_t xHigherPriorityTaskWoken;
        vTaskNotifyGiveFromISR(INS_task_local_handler, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
      }
    }
  }
  else if (GPIO_Pin == INT1_GYRO_Pin)
  {
  }
}

你可能感兴趣的:(嵌入式硬件,单片机)