Skip to main content
MSERT
Associate II
February 18, 2019
Question

STM32F7xx is a 216 MHz ARM MCU But I Can Not Generate Even 0.5 microsecond Timer Interrupt?

Hi,

//In my project i want to use 0.5 us (500 nanosecond) timer interrupt counter. 

//The MCUs max speed is 216 MHz. To get 200 MHz clock frequency, My OSC and CLOCK Settings are 

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct;

RCC_ClkInitTypeDef RCC_ClkInitStruct;

HAL_StatusTypeDef ret = HAL_OK;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLM = 4;

RCC_OscInitStruct.PLL.PLLN = 192;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 8;

ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);

if(ret != HAL_OK)

{

while(1){;}

}

ret = HAL_PWREx_EnableOverDrive();

if(ret != HAL_OK)

{

while(1){;}

}

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |    RCC_CLOCKTYPE_PCLK1 |         RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);

if(ret != HAL_OK)

{

while(1){;}

}

}

//and 

//TIMER Settings for 5 us interrupt output 

 TIM_HandleTypeDef htim2 = {

.Instance = TIM2};

__HAL_RCC_TIM2_CLK_ENABLE();

htim9.Init.Prescaler = 99;

htim9.Init.CounterMode = TIM_COUNTERMODE_UP;

htim9.Init.Period = 9;

htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim9.Init.RepetitionCounter = 0x00;

HAL_TIM_Base_Init(&htim2);

HAL_TIM_Base_Start_IT(&htim2);

HAL_NVIC_SetPriority(TIM2_IRQn, 0x00, 0x00);

HAL_NVIC_EnableIRQ(TIM2_IRQn);

//then for 1 second LED blink using 100.000 counter variable in following function;

void TIM2_IRQHandler()

{

second++;

HAL_TIM_IRQHandler(&htim2);

}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if(second == 90.000)

{

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);

}

if(second == 100.000)

{

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);

second = 0;

}

}

Led blinks 1 time in one second. Ok. 

//***But if I decrease the division factor to get 0.5 us -500 nanosecond- changing counter variable = 1.000.000 to get 1 second LED blink***

htim9.Init.Prescaler = 9;

htim9.Init.CounterMode = TIM_COUNTERMODE_UP;

htim9.Init.Period = 9;

//It slows down that around 2 sec/blink!!! and even if i continue to decrease Prescaler = under 9 or Period = under 9 the speed of LED blinking doesnt chance!!!

//I wisited hundreds of web pages and i read toushands of pages of documents but couldnt find any useful description or solution! I just found a trick in a document DM00224583 (RCC dedicated clocks configuration register (RCC_DCKCFGRx)) about APB1 and APB2 that their division must be 1 to conduct high speed frequency, but my setings are already same with that division 1!!! Since we will never be able to use it, why it is so fast this much 216 MHz?

//Could you help me how to generate 0.5 us interrupt with 216 MHz High speed MCU STM32F7xx????

    This topic has been closed for replies.

    17 replies

    AvaTar
    Senior III
    February 18, 2019

    > STM32F7xx is a 216 MHz ARM MCU But I Can Not Generate Even 0.5 microsecond Timer Interrupt!!!

    Sorry, but the idea to have a 500ns interrupts speaks of your shallow understanding of this MCU, and embedded design.

    > //I wisited hundreds of web pages and i read toushands of pages of documents but couldnt find any useful ...

    Look for a webpage that describes the costs of an interrupt entry and exit (in clock cycles), and then calculate how much time your application spends in your questionable interrupt handler. And check the costs (time) of RMW access to a peripheral register, and a plain memory (RAM) cell.

    Do high-frequency task in hardware, i.e. with approriate the peripherals - that's what they are designed for.

    > void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

    > {

    > if(second == 100.000)

    > ...

    > if(second == 200.000)

    > ...

    Divide your interrupt frequency by 100.000.

    MSERT
    MSERTAuthor
    Associate II
    February 18, 2019

    AvaTar.. I appreciate your critisizm and explanations!

    But your answer doesnt help me unfortinately!

    ////Look for a webpage that describes...... Divide your interrupt frequency by 100.000!

    This means another thousands of pages and divide the prescalers by many various values of numbers from 0 to Infinity!..

    thanks

    AvaTar
    Senior III
    February 19, 2019

    > But your answer doesnt help me unfortinately!

    To quote Morpheus here:

    "I can only show you the door. You're the one that has to walk through it."

    Tesla DeLorean
    Guru
    February 18, 2019

    Consider why you can't get the TIM hardware to do the signalling at high rates.

    Then do a disassembly of what you have the processor executing, and see why you've got it eating hundreds of cycles looping back and forth into the HAL libraries and callbacks. Perhaps look to code something a lot tighter on the IRQ Handler side.

    Generally I'd keep the prescaler the smaller of the two terms, for short periods the prescaler of zero (DIV1) is recommended.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    MSERT
    MSERTAuthor
    Associate II
    February 18, 2019

    thank you

    I m researching to fix them..

    S.Ma
    Principal
    February 18, 2019

    https://en.wikipedia.org/wiki/ARM_Cortex-M

    For basic info about interrupts and timings.

    Live long and prosper

    MSERT
    MSERTAuthor
    Associate II
    February 18, 2019

    thanks KIC.

    text indicates 12 instruction cycle latency at every overflow of TIM interrupt of cortex7, however i think it doesnt affect my code this much at its critical point that increase the cycle duration instead decrease two times; prescaler from 99 to 9!!! Right?

    LMI2
    Senior III
    February 18, 2019

    "STM32F7xx is a 216 MHz ARM MCU" really means that there is maybe one flipflop toggling at that speed somewhere on the chip. Well, perhaps not really, but those CPUs are not really that fast.

    MSERT
    MSERTAuthor
    Associate II
    February 18, 2019

    It was so easy to generate microsecond or nanosecond in PICs even 8bit/16bit with robust working!!!

    I'll move back to the poor PICs...

    AvaTar
    Senior III
    February 19, 2019

    It is like complaining that your Formula I race car doesn't do 250mph on offroad tracks.

    If you do not want to engage with the STM32F7 and it's complex peripherals, go back to the PIC and do bit-banging.

    Piranha
    Principal III
    February 19, 2019
    1. Clock configuration is completely wrong. To get 200 MHz with that configuration, PLL would have to run at 4 MHz input and 800 MHz VCO output frequency, neither of which is possible. RM0410 5.3.2 .
    2. APB1 and APB2 configuration is also wrong. Those buses can't run at 200 MHz. Datasheet, "General operating conditions".
    3. You are handling TIM9 from TIM2 interrupt handler.
    4. Learn basic math, so that You can calculate the needed prescaler value not try "many various values".
    5. Start using hardware, which You have - timer output channels.
    6. HAL drivers are bloatware and are not an indicator of MCU capabilities. To get top performance, one must use LL drivers or better write his own.

    You clearly haven't read those "toushands of pages of documents" and even played with CubeMX clock configuration. So, before s***ing on MCU, look at Your own pants...

    Piranha
    Principal III
    February 19, 2019
    1. Clock configuration is totally wrong. To get 200 MHz SYSCLK with those settings, PLL would have to run at 4 MHz input and 800 MHz VCO output frequencies, neither of which is possible. RM0410 5.3.2 .
    2. APB buses configuration is also wrong. Those buses can't run at 200 MHz. Datasheet, "General operating conditions".
    3. You are handling TIM9 interrupt from TIM2 interrupt handler function.
    4. Start using hardware You have by it's purpose - timer output channels.
    5. Learn basic math, so that You can calculate needed prescaler value not try "many various values".
    6. HAL drivers are badly designed and bloated, and therefore are not an indicator of MCU performance. To reach top performance, one must use LL drivers or better write their own.

    You clearly haven't read those "toushands of pages of documents" and not even played with CubeMX clock configuration. Before starting to criticize the MCU, learn how it works and look at Yourself (Your solution)!

    MSERT
    MSERTAuthor
    Associate II
    February 21, 2019

    Hi,

    I reviewed my settings and code.and restructured some parts of it.

    I corrected;

    Oscillator, Clock, AHB, APBx and TIM2 Handler function that you indicated sections 1. 2. 3. ... 5. ...

    Thus: Osc 8 MHz HSE - SYS Clock 192 MHz - AHB/HCLK 192 MHz - APB1 Timer Clock 96 MHz (for my TIM2)

    However I couldnt understand;

    4.Start using hardware You have by it's purpose - timer output channels.

    You mean: *HAL_TIM_PeriodeElapsedCallback()*; or

    *HAL_TIM_OC_DelayElapsedCallback()*; functions?

    and

    6.HAL drivers are badly designed and bloated, and therefore are not an

    indicator of MCU performance. To reach top performance, *one must use LL

    drivers or better write their own. *what do you mean?

    Final form of my whole code is below:

    If APB1 bus is 96 MHz so: 96 MHz / (Prescaler * Periode) = 0.96 MHz = 1 /

    0.96 MHz ~= 1 microsecond

    the LED must blink approximately 10 times in second. But it is around 3

    times again!

    I'm trying to move from pic to ST-ARM Mcus and it is really very difficult

    for any engineer that who worked with 8/16 bit PICs for many years in

    industry! So I need really help at this point to generate at least correct

    1 or 0.5 microsecond Timer speed before I give it up!!! Then I'll work on

    ADC and PWM that which will not be able to force me this much as far as I

    understand...

    could you help me to fix my work below?

    thanks

    *

    #include

    "stm32f7xx.h" // Device header*

    *

    #include

    "stm32f7xx_hal.h"*

    */*-----SYSTEM OSCILLATOR & CLOCK CONFIGURATIONS-----*/*

    *void SystemClock_Config(void)*

    * {*

    * RCC_OscInitTypeDef RCC_OscInitStruct;*

    * RCC_ClkInitTypeDef RCC_ClkInitStruct;*

    * //RCC_PLLInitTypeDef RCC_PLLInitStruct;*

    * HAL_StatusTypeDef ret = HAL_OK; //HAL_OK = 0x00*

    * RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; //Oscillator

    is HSE (High Speed External) - 8MHz on Nucleo Board*

    * RCC_OscInitStruct.HSEState = RCC_HSE_ON; //HSE is ON*

    * RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; //PLL (Phase Locked Loop) is

    ON*

    * RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; //PLL Source is HSE

    Oscillator*

    * RCC_OscInitStruct.PLL.PLLM = 4; //Main Division Factor for PLL VCO Input

    Clock : 2 - 63*

    * RCC_OscInitStruct.PLL.PLLN = 192; //Main Multiplication Factor for PLL

    VCO Output Clock : 50 - 432*

    * RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; //Main Division Factor for

    Main System Clock : 2,4,6,8*

    * RCC_OscInitStruct.PLL.PLLQ = 8; *

    * ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);*

    * if(ret != HAL_OK)*

    * {*

    * while(1){;}*

    * }*

    * ret = HAL_PWREx_EnableOverDrive();*

    * if(ret != HAL_OK)*

    * {*

    * while(1){;}*

    * }*

    * RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK

    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);*

    * RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;*

    * RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;*

    * RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;*

    * RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;*

    * ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);*

    * if(ret != HAL_OK)*

    * {*

    * while(1){;}*

    * }*

    * }*

    *//----------GLOBAL VARIABLES----------//*

    * uint32_t second;*

    *//----------TIMER TYPEDEF----------//*

    * TIM_HandleTypeDef htim2 = {*

    *.Instance = TIM2};*

    */*----------THE MAIN FUNCTION----------*/*

    *int main()*

    *{*

    * HAL_Init();*

    * SystemClock_Config();*

    * //RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;*

    * //TIM_ClockConfigTypeDef TIM_ClockConfigStruct;*

    * TIM_Base_InitTypeDef TIM_Base_InitStruct;*

    * GPIO_InitTypeDef GPIO_InitStruct;*

    * __HAL_RCC_GPIOB_CLK_ENABLE();*

    * GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_14;*

    * GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;*

    * GPIO_InitStruct.Pull = GPIO_NOPULL;*

    * GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;*

    * HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);*

    * __HAL_RCC_GPIOC_CLK_ENABLE();*

    * GPIO_InitStruct.Pin = GPIO_PIN_13;*

    * GPIO_InitStruct.Mode = GPIO_MODE_INPUT;*

    * GPIO_InitStruct.Pull = GPIO_PULLDOWN;*

    * GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;*

    * HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);*

    * __HAL_RCC_TIM2_CLK_ENABLE();*

    * htim2.Init.Prescaler = 9;//Between 0x0000 - 0xFFFF*

    * htim2.Init.CounterMode = TIM_COUNTERMODE_UP;//UP: From 0 to Set Prescaler

    Value*

    * htim2.Init.Period = 9;//Between 0x0000 - 0xFFFF*

    * htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;*

    * htim2.Init.RepetitionCounter = 0x00;*

    * HAL_TIM_Base_Init(&htim2);*

    * HAL_TIM_Base_Start_IT(&htim2);*

    * HAL_NVIC_SetPriority(TIM2_IRQn, 0x00, 0x00);*

    * HAL_NVIC_EnableIRQ(TIM2_IRQn);*

    * while(1) {}*

    *}*

    */*--------------------USER PROGRAM--------------------*/*

    *void TIM2_IRQHandler()*

    * {*

    * HAL_TIM_IRQHandler(&htim2);*

    * second++;*

    * if(second == 99000)*

    * { *

    * HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);*

    * }*

    * if(second == 100000)*

    * {*

    * HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);*

    * second = 0;*

    * }*

    * }*

    ST Community 19 Şub 2019 Sal, 10:26 tarihinde şunu

    yazdı:

    Piranha
    Principal III
    February 22, 2019

    When posting code, use "Code Snippet" button to insert code.

    //Oscillator is HSE (High Speed External) - 8MHz on Nucleo Board
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;

    RCC_HSE_ON means that HSE oscillator is on, but on Nucleo boards by default HSE is fed by 8 MHz external clock from ST-Link. Therefore HSEState must be RCC_HSE_BYPASS.

    About my previous points:

    4.Read the RM0410 section 26. Look for phrase "output compare". Also AN4776

    is very useful. I don't know much HAL functions because I dropped usage of HAL for my projects in favor of my own drivers.

    6.I mean exactly what I said. What exactly isn't clear there?

    And as was said before - You can count microseconds or even clock ticks with a timer itself, but set up an interrupt only on reaching target time, not on every microsecond. It can be done with ARR register and in more complex cases also an output compare channel. TIM2 is a 32-bit timer. For example, at 96 MHz timer clock set prescaler to 96/2-1 and You've got Your 0.5 us timer increments.