cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F2 Timer / Interrupt Help

ckern
Associate II
Posted on March 19, 2015 at 14:10

STM32F2 Timer / Interrupt Help

I have an HS USB project that reads information at a high data rate from a serial bus (upwards of 4MBd) and then sends it to a server. Everything is working fine, except....

I run into some timing issues from time to time, and I *think* I have narrowed it down to an IRQ issue.

I have set my project up with NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2) because I have 3 main areas that need servicing at different levels. I have this call at the very beginning of my program, and it is only called once.

My understanding is that with NVIC_PriorityGroup_2, I have 4 groups (0-3) of IRQ priority levels, and each level has 4 sub-priorities (0-3) with each level having '0' as the highest priority. So an interrupt with 0,0 has the highest priority while an interrupt with 3,3 is the lowest.

In my project, I have to have polling intervals for different devices on the serial bus. I have set up TIM3 for a specific period (it actually changes depending on what i am expected to talk to on the serial bus, but that is immaterial at this point). I have an IRQ set up on this timer to check for TIM_IT_Update. I have set TIM3_IRQn priority to be 0,0. Once the timer hits the specified time, my IRQ handler toggles a bit (an LED), resets the counter, and away the timer goes. This works beautifully until I actually start doing USB and/or serial communications. 

From the oscilloscope, I can see the LED bit toggle perfectly at the right time (again, when nothing is happening on the communications buses). Once the comms begin, the LED bit edges are no longer on their mark (in this case, 50 ms). The period shrinks, expands, stays the same; there does not seem to be any pattern that I can ascertain. 

I have gone through the code, and verified that my highest priority IRQ is for TIM3, and it is the only IRQ set for 0,0. 

So my question is, if this is the highest priority IRQ, then there should be nothing to prevent the LED bit from toggling exactly when it should. Here is some code snippets:

int main(void)

{

    /* Configure the Priority Group */

    NVIC_PriorityGroupConfig(USB_NVIC_PriorityGroup);

.

.

.

.

.

.

.

    LCD_LED_Init();

    Initialize_Variables();

    MCU_IO_Init();

    Protocol_Line_Init();

    TIM2_Configuration(time1); 

    TIM4_Configuration(time2);

    TIM3_Configuration(poll_time); 

    TIM5_Configuration(time4); 

.

.

.

.

.

.

.

.

    RCC_Configuration();

    GPIO_Configuration();

.

.

.

.

.     

    

  /* Infinite loop */

  while (1)

  {  

.   

.

.

.

<<comms program>>

  }   

}

void MCU_IO_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    FSMC_NORSRAMInitTypeDef SRAMInitS;

    FSMC_NORSRAMTimingInitTypeDef p;

  

    //UART FLOW CONTROL --> PF7

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 ; 

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOF, &GPIO_InitStructure);

    // Set to 'Receive'

    Enable_Receiver_Disable_Transmitter();    

}

void RCC_Configuration(void)

{

  /* --------------------------- System Clocks Configuration -----------------*/

  /* USART3 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

 

  /* GPIOD clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

 

  /* DMA1 clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

}

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

 

  /*-------------------------- GPIO Configuration ----------------------------*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; // PC.10 USART3_TX, PC.11 USART3_RX

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

 

  /* Connect USART pins to AF */

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);

}

void TIM3_Configuration (uint16_t Time_In_Microseconds) 

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    

    // Enable the TIM3 Interrupt 

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 

    NVIC_Init(&NVIC_InitStructure);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x00;

    TIM_TimeBaseStructure.TIM_Period = Time_In_Microseconds - 1;

    TIM_TimeBaseStructure.TIM_Prescaler = (MCU_OSC / 1000000) - 1;

    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure );

    TIM_Cmd( TIM3, ENABLE );

    TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE );

void TIM3_IRQHandler(void)

{

    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)

    {    

        ready_to_poll = TRUE;

ToggleLED(LED1);

        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

    }

}

I agree that my code could use some cleanup, but that is always happening... Maybe some of my initializations are out of order??

Any help would be appreciated. As my serial data is streaming into the USART, i am pulling it out of the buffer and putting it into memory. Once the packet has ended, I pull it out of memory and then send it along to the USB port. The only thing I can think of that might be messing up my IRQ timing is the transfer to and from external memory. From the vector table, I see that ''MemManage'' is set to priority '0', but that it is settable. If you think that the memory I/O is affecting my TIM3 IRQ timing, then could you please inform me how to change the ''MemManage'' Interrupt Vector priority? 

Thank you very much for your assistance in this matter. It is driving me nuts!

#stm32f2-timer-interrupt-irq
4 REPLIES 4
Posted on March 19, 2015 at 17:00

Isn't it more probable that the USB library code (usb_bsp.c, or whatever) is changing the priority level?

The code you have presented isn't where you're problem lies. Review all the source in your project, grep, or find-in-files

Confirm that SCB->AIRCR has the value expected, initially and when you observe the problem.

Using the MMU? If not assume you won't get MemManager Faults.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ckern
Associate II
Posted on March 19, 2015 at 18:55

Clive,

Thanks for the quick response. It is a relief that it isnt anything in the code I posted. I am not explicitly using the MMU, but I did start this project from an example way back when. 

I will do as you suggested and see if the USB code is changing priorities on me. If that is the case, I am assuming it will not be in the form of 

'' NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = '', or will it? 

What other syntax might I search for that could be changing the priorities around?

Thanks again.

Posted on March 19, 2015 at 19:12

Randomly greping STM32F4-Discovery_FW_V1.1.0\Project\FW_upgrade, I see

/**
* @brief USB_OTG_BSP_EnableInterrupt
* Configures USB Global interrupt
* @param None
* @retval None
*/
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable USB Interrupt */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the Overcurrent Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = HOST_OVRCURR_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
...
/**
* @brief USB_OTG_BSP_TimeInit
* Initializes delay unit using Timer2
* @param None
* @retval None
*/
static void USB_OTG_BSP_TimeInit (void)
{
#ifdef USE_ACCURATE_TIME
NVIC_InitTypeDef NVIC_InitStructure;
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00);
/* Configure the Priority Group to 2 bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
#endif
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ckern
Associate II
Posted on March 22, 2015 at 22:42

Clive, thanks. Found the problem. As in most cases (and per your suggestion), it was another NVIC setting that was overlooked. Not in the USB section, but a different one of my own creation. I was using variables to set the values for all other NVIC device settings but this one that was overlooked. As always, thanks again.