AnsweredAssumed Answered

Reconfiguring a Timer within its interrupt handler

Question asked by rks1 on Aug 18, 2015
Latest reply on Aug 20, 2015 by oziom.dominik
On an STM32F4 Discovery (STM32F407)

I'm trying to set up a timer and then reconfigure it within its own interrupt handler. The idea is that I should be able to repeatedly trigger tasks from the ISR in an aperiodic fashion.


When I try to simply set up a periodic interrupt, I have no trouble, but when I try to change the period within the interrupt handler, the handler gets triggered immediately back to back until I disable the timer. 


I used the DWT_CYCCNT register to get some cycle count information, so I could have a better understanding of what was happening with my timing:


(gdb) p cycleCountDebugBuf 
$1 = {3999991120, 1672, 1672, 1672, 1672, 0 <repeats 15 times>}


I write the cycle count between enabling the timer and entering the ISR for each value. As you can see, after the first reconfiguration, the handler is repeatedly triggered without any real delay. I have confirmed that the delay that I provide when reconfiguring is a valid number.


I've played around with a few different variations of the handler, trying to disable and re-enable the NVIC, using TIM_DeInit() and then reenabling the clocks, and simply providing a TIM_CMD to disable and re-enable the timer, but nothing has worked. I also tried pulling the reconfiguration out of the ISR and placing it in a queue that is triggered by the ISR, but that didnt work either.


I'm sure I'm missing something simple here - any advice? Code for the timer initialization and ISR below.


Initialization:
// NEED TO SET UP THE TIMER FOR THE FIRST TIME
TIM_TimeBaseInitTypeDef Timer_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
 
 
//Get the first delay value, in ms
uint32_t delay = delaySequence->duration;
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
 
/*Set prescaler such that each timer tick takes 8400 clock ticks.
84000000/8400 = 10000 timer ticks per second - our timer has a resolution of 100 us*/
Timer_InitStruct.TIM_Prescaler = 8400;
//Timer_InitStruct.TIM_Prescaler = 40000;
 
Timer_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
//Set the timer period to the delay, in units of 100 us
Timer_InitStruct.TIM_Period = delay * 10;
//Timer_InitStruct.TIM_Period = 50;
 
Timer_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
Timer_InitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM9, &Timer_InitStruct);
TIM_Cmd(TIM9, ENABLE);
 
 
TIM_ITConfig(TIM9, TIM_IT_Update, ENABLE);
 
NVIC_InitStruct.NVIC_IRQChannel = TIM1_BRK_TIM9_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0xff;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0xff;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
 
startCycleCount();


Interrupt Handler:
void TIM1_BRK_TIM9_IRQHandler(){
  long lHigherPriorityTaskWoken = pdFALSE;
  if (TIM_GetITStatus(TIM9, TIM_IT_Update) != RESET)
  {
 
    my_queue_msg_t msg;
 
    //TIM_DeInit(TIM9);
    TIM_Cmd(TIM9, DISABLE);
 
    TIM_ClearITPendingBit(TIM9, TIM_IT_Update);
 
    returnCycleCount();
    startCycleCount();
 
    /*
      Removed msg population for simplicity's sake.
    */
    //Send the msg to queue
    xQueueSendToBackFromISR(myQueue, &msg, &lHigherPriorityTaskWoken);
 
    interruptCount++;
 
    if(interruptCount < maxInterruptCount){
 
      TIM_TimeBaseInitTypeDef Timer_InitStruct;
      NVIC_InitTypeDef NVIC_InitStruct;
 
      //Pull the next delay value
      uint8_t delay = delayArray[interruptCount];
 
      //re-enable the clock after doing the deinit
      //RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
 
      /*Set prescaler such that each timer tick takes 8400 clock ticks.
      84000000/8400 = 10000 timer ticks per second - our timer has a resolution of 100 us*/
      Timer_InitStruct.TIM_Prescaler = 8400;
      //Timer_InitStruct.TIM_Prescaler = 40000;
 
      Timer_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
      //Set the timer period to the delay, in units of 100 us
      Timer_InitStruct.TIM_Period = delay * 10;
      //Timer_InitStruct.TIM_Period = 50;
 
      Timer_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
      Timer_InitStruct.TIM_RepetitionCounter = 0;
      TIM_TimeBaseInit(TIM9, &Timer_InitStruct);
      TIM_Cmd(TIM9, ENABLE);
 
      TIM_ITConfig(TIM9, TIM_IT_Update, ENABLE);
 
/*
      NVIC_InitStruct.NVIC_IRQChannel = TIM1_BRK_TIM9_IRQn;
      NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0xff;
      NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0xff;
      NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStruct);
*/
    }
    else{
      //We should never reach here.
      //do something useless so we can break here
      msg.msgType = 0xDEADBEEF;
      TIM_Cmd(TIM9, DISABLE);
      TIM_ITConfig(TIM9, TIM_IT_Update, DISABLE);
    }
  }
 
  portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
}


Thanks!

Outcomes