AnsweredAssumed Answered

Minimizing Interrupt Time, Maximizing Compiler Processing Speed, Reaching STM32F3 Operator Speed

Question asked by ozkaya.kamil_yunus on Aug 20, 2015
Latest reply on Aug 20, 2015 by karpavicius.linas
Hello
I am currently working on STM32F3 Discovery Board. I wrote a basic program in C to see if it works at 72 MHz which is about 14 ns in time. Hopefully it worked at this frequency, but when I want to toggle just one random pin on the device, turning it ON or OFF takes 660 ns in an infinite while loop. Then I checked with an oscilloscope, how much each command takes. Values might not be exact, Here is what I found;
a while loop(only for checking) = 120 ns, a "for" loop(only for checking) = 160 ns
One turn of a while loop = 280 ns, one turn of a for loop = 320 ns, which means each turn takes 160 ns.
asm("NOP") = 14 ns(which must be equal to operator frequency(72 MHz, as expected), an empty function call = 225 ns
I don't know if these values are different in other compilers, or other computers, but I am not even close to 72 MHz. Minimum interrupt I got was 2 microsecond. Is there any way to minimize these values? 
  
#include "stm32f30x.h"
#include <common.h>
 
void InitializeTimer(void) ;
void EnableTimerInterrupt(void);
void TIM2_IRQHandler(void);
GPIO_InitTypeDef configuration;
void dly(int dly_nmbr);
int main(void)
{
 
  GPIO_InitTypeDef GPIO_InitStructure;
//NVIC_InitTypeDef NVIC_InitStructure;
  RCC_ClocksTypeDef RCC_ClockFreq;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
   
  /* Configure PA10 in output pushpull mode */
  /*****I called init_pin function from common.c because it was easier
  but I guess it takes some time too*********/
  init_pin(GPIOA,GPIO_Pin_10,GPIO_Mode_OUT,GPIO_Speed_50MHz,GPIO_OType_PP,GPIO_PuPd_NOPULL);
   
/****I tried usual way to configure the pins too****/
//configuration.GPIO_Pin = GPIO_Pin_10;
//configuration.GPIO_Mode = GPIO_Mode_OUT;
//configuration.GPIO_OType = GPIO_OType_PP;
//configuration.GPIO_Speed = GPIO_Speed_50MHz;
//configuration.GPIO_PuPd = GPIO_PuPd_NOPULL;
//GPIO_Init(GPIOA, &configuration);
//InitializeTimer();
/*** This function fills the RCC_ClockFreq structure with the current
  frequencies of different on chip clocks (for debug purpose) **************/
  RCC_GetClocksFreq(&RCC_ClockFreq);
 
  /* Enable Clock Security System(CSS): this will generate an NMI exception
  when HSE clock fails *****************************************************/
  RCC_ClockSecuritySystemCmd(ENABLE);
 
  /* Enable and configure RCC global IRQ channel, will be used to manage HSE ready
     and PLL ready interrupts.
     These interrupts are enabled in stm32f0xx_it.c file **********************/
  /* I disabled the interrupts for the purpose of maximizing the program speed*/
//   NVIC_InitStructure.NVIC_IRQChannel = RCC_IRQn;
//   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//   NVIC_Init(&NVIC_InitStructure);
 
 
  /************* Output HSE clock on MCO1 pin(PA8) ************/
  /****************** Enable the GPIOA Clock ******************/
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
 
  /* MCO pin configuration: PA8 */
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
  /* Output System Clock on MCO pin */
  RCC_MCOConfig(RCC_MCOSource_SYSCLK);
   
  /************** This is the toggling part. I tried each command here ***************/
   
  while(1)
  {
//     volatile int i = 0;
//     dly(0);
       /*I called an empty function called dly before and after the toggle
       to see function call time*/
       GPIO_Toggle(GPIOA,GPIO_Pin_10);
//     dly(0);
//       while(i<=0)
//     {
//       i++;
//     }
//     for(i=0;i<=0;i++);
     
  }
}
/*Empty Function*/
void dly(int dly_nmbr)
{
}
 
/************** Interrupt Functions  **************/
// void TIM2_IRQHandler()
//  {
//      if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
//      {
//          TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//      }
//  }
  
//  void InitializeTimer()
//  {
//      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 
//      TIM_TimeBaseInitTypeDef timerInitStructure;
//      timerInitStructure.TIM_Prescaler = 0;
//      timerInitStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2;
//      timerInitStructure.TIM_Period = 2;
//      timerInitStructure.TIM_ClockDivision = 0x0000;                               
//      timerInitStructure.TIM_RepetitionCounter = 100;
//      TIM_TimeBaseInit(TIM2, &timerInitStructure);
//     
//      TIM_Cmd(TIM2, ENABLE);
//      TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
//      EnableTimerInterrupt();
//  }
  
//  void EnableTimerInterrupt()
//  {
//      NVIC_InitTypeDef nvicStructure;
//      nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
//      nvicStructure.NVIC_IRQChannelCmd = ENABLE;
// //      TIM2->ARR = 1;
// //      TIM2->PSC = 1;
//      NVIC_Init(&nvicStructure);
//     
//  }
/****************** EOF ********************/

Outcomes