AnsweredAssumed Answered

Timer ISR return procedure

Question asked by plehotko.gleb on Feb 11, 2013
Latest reply on Feb 13, 2013 by plehotko.gleb
Hello to everyone.


I have just started to study STM32 microcontrolles (using STM32F4 Discovery kit) and can't understand one thing.


Test task is simple — set up Timer 7 to generate 100000 update events per second, and in the interrupt service routine toggle one pin of the port to check settings of the timer.


So, here is my code (IAR Embedded Wokbench for ARM):


#include <stdio.h>
#include <stdint.h>
#include "stm32f4xx.h"


void initiazliation(void);


void initiazliation(void)
{
  RCC->AHB1ENR|=0x09;               // Enable clock on PORTA and PORTD


  GPIOA->MODER|=0x00000004;           // PA1 is output
  GPIOA->OTYPER|=0x00000000;            // Push pull output
  GPIOA->OSPEEDR|=0x00000004;         // 25 MHz output
  GPIOA->PUPDR|=0x00000000;          // No pull-up, no pull-down
  GPIOA->IDR|=0x0000;                        // Input register
  GPIOA->ODR|=0x0000;                      // Output register      
  
  DBGMCU->APB1FZ|=DBGMCU_APB1_FZ_DBG_TIM7_STOP;


  RCC->APB1ENR|=0x00000020;           // Enale clock on Timer/Counter 7
  
  TIM7->ARR=79;                         // Fsclk=8MHz, Fuev=8000000/(79+1)=100KHz
  TIM7->PSC=0;                                      // No clock prescaling
  TIM7->DIER=0x0001;                          // Enable update interrupt
  TIM7->CR1=0x0001;                           // Enable Timer
  NVIC_EnableIRQ(TIM7_IRQn);          // NVIC interrupt enable
}


void TIM7_IRQHandler(void)
{
//  if (TIM7->SR&0x0001)
//  {
         GPIOA->ODR^=0x0002;
         TIM7->SR&=0xFFFE;
//  }
}




void main(void)
{
  initiazliation();
  __enable_irq();
  while(1);
}


As you can see, I use Timer 7 to generate Update Events and PA1 pin to toggle. MCU uses HSE as a main system clock (8MHz crystal), AHB, APB1 and APB 2 prescalers are set to 1, prefetch for instructions is enabled and flash latency is zero.


I thought, that this code will output squarewave pulses at PA1, and its frequency and duty cycle have to be 50 KHz and 0.5 (50 %) correspondingly. But in reality I have squrewave at 100 KHz, and duty cycle 0.41 (41 %). 


When I uncomment commented lines, everything is OK — frequency is 50 kHz and duty cycle is 50 %.


I can't understand, why it happens? Does such behaviour means, that ISR is entered again, after it was executed once? But why? I clear UIF flag in the Status Register of the Timer... And NVIC registers say's, that there is no pending interrupts from this source. Disassembler doesn't show difference betwee two variants of the ISR — both of them finish with BX LR instruction and there is no pending requests.

Please, help me to understand, what actually happens in this case.

P.S.
Sorry for my bad English.

Outcomes