0
votes

I've read multiple times that it is usually good practice to minimize the amount of time to spend in a timer interrupt, and the advice of only raising a flag came up several times.

I am using a timer to run a bit of code (conversion of sensor data into usable data). It is important in my application to read and manipulate this data at fairly high-speed (8KHz).

Here's how I am approaching the problem:

  • I am using an STM32 H743

  • I am using RTOS with two threads, with slightly different priority levels

  • I am using 2 timers (TIM2 and TIM3) in my case

  • TIM2 is set to trigger a callback at 1KHz, and is started in my main thread (slightly higher priority than the secondary thread)

  • TIM3 is set to trigger a callback at 8KHz, and is started in the secondary thread

  • the HAL_TIM_PeriodElapsedCallback is used for both Timers and is looking like this:

    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 */
    }
    

And then each of the 2 threads have a simple test on the flag, here's what it looks like for the secondary thread:

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 */
}

Per the autogenerated code from CubeMX, both the mainThread and secondaryThread infinite for(;;) loops had a osDelay(1).

am I supposed keep these days? outside of the if statement for the raised flag?

I have some concerns that if I don't it will crash the MCU because outside nothing to do when the flag isn't raised. And I am concerns that keeping the osDelay(1) will be "too long" (1ms vs 125 us). Is there a way to apply a shorter delay that would not slow down my 8KHz polling?

Of course the runCAL() stuff will take significantly less time than the 125 us period.

It would make sense for me to remove the delay all together but I have a feeling that it will crash severely.

What should I do?

cheers

1

1 Answers

0
votes

Flags not are net very good way of the thread synchronisation when you use RTOS.

In this case use semaphores, mutexes or direct task notifications.

slightly higher priority than the secondary thread

It does not make any difference in code you shown The different priorities RTOS tasks are not preempted by the scheduler and context switch happens only when you pass the control yourself. The only task which will actually run all the time is the last started one, as your task does not pass the control to the RTOS and the ISR also does not. Your code is not actually the correct RTOS code.

You can have it in one task.

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 );
}