Search code examples
timerinterruptstm32pwmbluepill

stm32f103 internal interrupt can not reach the wanted frequency (350ns) (lowest reached is 4us)


i am trying to generate a PWM signal by turning a GPIO pin high and low using an interrupt generated by TIMER1, why i am doing it this way is a whole different story, so i need to generate an interrupt every 350ns, i calculated prescaler and the ARR for 72MHz and i found out that i need a prescaler of 1 and an ARR of 25 so i set the parameters according to these values, now i have 25 clock cycle to do what i want before the next interrupt triggers, so at each interrupt the specified pin has to change state (High to Low or Low to High), i am looking at the output signal using an oscilloscope and i am stuck with an output of 8us (which means an interrupt every 4 us), how can i fix this? where am i failing? what am i possibly doing wrong? Here is what i am doing in the interrupt function:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if ((GPIOC->ODR & GPIO_PIN_13) != 0x00u)
    {
        GPIOC-> ODR = 0x0000;
    }
    else
    {
        GPIOC-> ODR = 0x2000;
    }
  }

Here is a photo of the output signal : Oscilloscope output

is it possible that the code inside the interrupt exceeds 25 clock cycle? if so how can i do it without exceeding ? thanks


Solution

  • is it possible that the code inside the interrupt exceeds 25 clock cycle? if so how can i do it without exceeding ? thanks

    If you use HAL stop counting clocks :)

    So firstly we have the original handler: interrupt entry takes about 12 clocks + FLASH wait states

    void TIMx_IRQHandler(void)
    {
      HAL_TIM_IRQHandler(&TimHandle);
    }
    

    Then we call HAL handler + min 3 clocks + waitstates as the pipeline is flushed.

    Then we have HAL function - a lots of clock cycles:

    void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
    {
      /* Capture compare 1 event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET)
        {
          {
            __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
            htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
    
            /* Input capture event */
            if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
            {
              HAL_TIM_IC_CaptureCallback(htim);
            }
            /* Output compare event */
            else
            {
              HAL_TIM_OC_DelayElapsedCallback(htim);
              HAL_TIM_PWM_PulseFinishedCallback(htim);
            }
            htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
          }
        }
      }
      /* Capture compare 2 event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
          htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
          /* Input capture event */
          if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
          {
            HAL_TIM_IC_CaptureCallback(htim);
          }
          /* Output compare event */
          else
          {
            HAL_TIM_OC_DelayElapsedCallback(htim);
            HAL_TIM_PWM_PulseFinishedCallback(htim);
          }
          htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
        }
      }
      /* Capture compare 3 event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
          htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
          /* Input capture event */
          if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
          {
            HAL_TIM_IC_CaptureCallback(htim);
          }
          /* Output compare event */
          else
          {
            HAL_TIM_OC_DelayElapsedCallback(htim);
            HAL_TIM_PWM_PulseFinishedCallback(htim);
          }
          htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
        }
      }
      /* Capture compare 4 event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
          htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
          /* Input capture event */
          if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
          {
            HAL_TIM_IC_CaptureCallback(htim);
          }
          /* Output compare event */
          else
          {
            HAL_TIM_OC_DelayElapsedCallback(htim);
            HAL_TIM_PWM_PulseFinishedCallback(htim);
          }
          htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
        }
      }
      /* TIM Update event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
          HAL_TIM_PeriodElapsedCallback(htim);
        }
      }
      /* TIM Break input event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
          HAL_TIMEx_BreakCallback(htim);
        }
      }
      /* TIM Trigger detection event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
          HAL_TIM_TriggerCallback(htim);
        }
      }
      /* TIM commutation event */
      if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
      {
        if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET)
        {
          __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
          HAL_TIMEx_CommutationCallback(htim);
        }
      }
    }
    

    and eventually call to your function which execution will take between 8 and 15 clocks.

    So if you have 25clocks in total you are a really lucky man.