STM32 TIM回调引发标志

Posted

技术标签:

【中文标题】STM32 TIM回调引发标志【英文标题】:STM32 TIM callback to raise flag 【发布时间】:2020-11-14 17:16:02 【问题描述】:

我读过很多次,通常最好的做法是尽量减少在定时器中断上花费的时间,并且多次提出只提高标志的建议。

我正在使用计时器来运行一些代码(将传感器数据转换为可用数据)。在我的应用程序中,以相当高的速度 (8KHz) 读取和操作这些数据非常重要。

这是我解决问题的方法:

我正在使用 STM32 H743

我正在使用具有两个线程的 RTOS,优先级略有不同

在我的情况下,我使用了 2 个计时器(TIM2 和 TIM3)

TIM2 设置为在 1KHz 触发回调,并在我的主线程中启动(优先级略高于辅助线程)

TIM3 设置为在 8KHz 触发回调,并在辅助线程中启动

HAL_TIM_PeriodElapsedCallback 用于两个计时器,如下所示:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

/* USER CODE BEGIN Callback 0 */

/* USER CODE END Callback 0 */
    if (htim->Instance == TIM6) 
      HAL_IncTick();
    
/* USER CODE BEGIN Callback 1 */
else if (htim->Instance == TIM2) 
    TIM3_flag = 1;


else if (htim->Instance == TIM3) 
    TIM3_flag = 1;

/* USER CODE END Callback 1 */

然后 2 个线程中的每一个都对标志进行简单测试,这是辅助线程的样子:

void StartSecondaryThread(void *argument)

  /* USER CODE BEGIN StartSecondaryThread */
    HAL_TIM_Base_Start_IT(&htim3);
  /* Infinite loop */
  for(;;)
  
      if (TIM3_flag == 1) 
          runCALC();
          //MORE USER CODE HERE
          TIM3_flag = 0;
      
  
  /* USER CODE END StartSecondaryThread */

根据 CubeMX 自动生成的代码,mainThread 和 secondaryThread 无限 for(;;) 循环都有一个 osDelay(1)。

我应该保留这些天吗?在升旗的 if 语句之外?

我有些担心,如果我不这样做,它会导致 MCU 崩溃,因为在没有升起标志的情况下,外界无事可做。而且我担心保持 osDelay(1) 会“太长”(1ms vs 125 us)。有没有办法应用更短的延迟而不会减慢我的 8KHz 轮询?

当然,runCAL() 的内容将比 125 us 周期花费的时间要少得多。

将延迟全部消除对我来说是有意义的,但我感觉它会严重崩溃。

我该怎么办?

干杯

【问题讨论】:

【参考方案1】:

使用 RTOS 时,标志并不是线程同步的好方法。

在这种情况下,请使用信号量、互斥锁或直接任务通知。

比辅助线程的优先级略高

它在您显示的代码中没有任何区别不同优先级的 RTOS 任务不会被调度程序抢占,并且只有当您自己传递控制权时才会发生上下文切换。唯一真正会一直运行的任务是最后启动的任务,因为您的任务不会将控制权传递给 RTOS,而 ISR 也不会。您的代码实际上不是正确的 RTOS 代码。

您可以在一项任务中使用它。

void StartSecondaryThread(void *argument)

    /* USER CODE BEGIN StartSecondaryThread */
    HAL_TIM_Base_Start_IT(&htim3);
    HAL_TIM_Base_Start_IT(&htim2);
    /* Infinite loop */
    for(;;)
    
        switch(ulTaskNotifyTake(pdTRUE, portMAX_DELAY))
        
            case 3:
                runCALC();
                //MORE USER CODE HERE for timer 3
                break;
            case 2:
                //MORE USER CODE HERE for timer 2
                break;
            default:
                //MORE USER CODE HERE for other timers
                break;
        
    
    /* USER CODE END StartSecondaryThread */



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

    BaseType_t xHigherPriorityTaskWoken = pdFalse;
    switch((uint32_t)htim->Instance)
    
        case (uint32_t)TIM6:
            HAL_IncTick();
            break;
        case (uint32_t)TIM2:
            xTaskNotifyFromISR( xThreadHndl, 2, eSetValueWithOverwrite, &xHigherPriorityTaskWoken );
            break;
        case (uint32_t)TIM3:
            xTaskNotifyFromISR( xThreadHndl, 3, eSetValueWithOverwrite, &xHigherPriorityTaskWoken );
            break;
    
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

【讨论】:

默认情况下(configUSE_TIME_SLICING 定义为 1),FreeRTOS 调度程序在具有最高优先级的任务之间切换。如果您将系统设计为完全具有同等优先级的任务,这可能会很有用,但当然最好使用适当的同步原语。

以上是关于STM32 TIM回调引发标志的主要内容,如果未能解决你的问题,请参考以下文章

STM32 中定时器中断回调函数中加入adc采样轮换查询后,中断函数不执行?请问怎么解决?

基于HAL库的STM32定时器单脉冲控制

stm32 freertos 中回调函数需要做个任务么

使用STM32CubeIDE编写EC11 定时器中断方式

STM32CubeMX开发03——回调函数

STM32CubeMX开发03——回调函数