Skip to main content
Visitor II
August 29, 2019
Solved

STM32L462 delay in a microsecond(us)

  • August 29, 2019
  • 9 replies
  • 29362 views

HAL Library provide the HAL_Delay() for millisecond delay. I want to use micro second delay in STM32L4 so how I do it? Is it available in HAL library?

    This topic has been closed for replies.
    Best answer by AP_040

    I am done.

    Added this dwt files in my project and working fine.

    #ifndef DWT_STM32_DELAY_H
    #define DWT_STM32_DELAY_H
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
     
    #include "stm32f1xx_hal.h"
    uint32_t DWT_Delay_Init(void);
     
     
     
    /**
     * @brief This function provides a delay (in microseconds)
     * @param microseconds: delay in microseconds
     */
    __STATIC_INLINE void DWT_Delay_us(volatile uint32_t microseconds)
    {
     uint32_t clk_cycle_start = DWT->CYCCNT;
     
     /* Go to number of cycles for system */
     microseconds *= (HAL_RCC_GetHCLKFreq() / 1000000);
     
     /* Delay till end */
     while ((DWT->CYCCNT - clk_cycle_start) < microseconds);
    }
     
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif

    9 replies

    Graduate II
    August 29, 2019

    Use a free running TIM at 1 MHz or faster, and delta the TIM->CNT​ in a loop until you get the elapsed micro-seconds

    AP_040Author
    Visitor II
    August 29, 2019

    Hello @Community member​  I found below example and implement in my MCU but it is not properly delay the system.

    //******************************************************************************

    volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register

    volatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register

    volatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register

    //******************************************************************************

    void EnableTiming(void)

    {

    *SCB_DEMCR = *SCB_DEMCR | 0x01000000;

    *DWT_CYCCNT = 0; // reset the counter

    *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter

    }

    //******************************************************************************

    void HAL_Delay_us(uint32_t tick)

    {

    unsigned int start, current;

    start = *DWT_CYCCNT;

    do

    {

    current = *DWT_CYCCNT;

    } while((current - start) < tick);

    }

    Is it register address is different for my MCU?

    Can I do it this way without free running timer?

    Graduate II
    August 29, 2019

    Yes, this will work on non CM0(+) parts. CM7 parts need an unlock sequence

    It will have the granularity of the CPU clock.

    1ms = SystemCoreClock / 1000

    1us = SystemCoreClock / 1000000

    AP_040Author
    Visitor II
    August 29, 2019

    @Community member​ 

    So, I need to change "1us = SystemCoreClock / 1000000" this in HAL_InitTick(). Is it?

    HAL_SYSTICK_Config(SystemCoreClock / (1000000U/ uwTickFreq))

    instead of

    HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq))

    This way?

    Graduate II
    August 29, 2019

    No, this is simply a computation of CPU ticks passed into HAL_Delay_us() to achieve a milli-second, or micro-second of elapsed time. It doesn't use/change SysTick.

    AP_040AuthorAnswer
    Visitor II
    August 29, 2019

    I am done.

    Added this dwt files in my project and working fine.

    #ifndef DWT_STM32_DELAY_H
    #define DWT_STM32_DELAY_H
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
     
    #include "stm32f1xx_hal.h"
    uint32_t DWT_Delay_Init(void);
     
     
     
    /**
     * @brief This function provides a delay (in microseconds)
     * @param microseconds: delay in microseconds
     */
    __STATIC_INLINE void DWT_Delay_us(volatile uint32_t microseconds)
    {
     uint32_t clk_cycle_start = DWT->CYCCNT;
     
     /* Go to number of cycles for system */
     microseconds *= (HAL_RCC_GetHCLKFreq() / 1000000);
     
     /* Delay till end */
     while ((DWT->CYCCNT - clk_cycle_start) < microseconds);
    }
     
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif

    Visitor II
    August 29, 2019

    You can simply do a nop loop if you know the core frequency. Otherwise, the lptimer is a good way to generate delays and callbacks.

    AP_040Author
    Visitor II
    August 30, 2019

    @S.Ma​  Yes, we can do it using LPtimer and callbacks but still I have note worked with timer yet. So, can you please help me how I generate microseconds delay using timer itself?

    Visitor II
    August 30, 2019

    This forum is inadequate to share source code (did answer and shared this kind of source code already), I'm not going to do the extra mile to compensate for the forum missing services. One there is an STM32 community Git repo for code example, snippets, projets with web links to use on this forum, it may make things much more efficient sharing know-how.

    Graduate II
    August 31, 2019

    > You can simply do a nop loop

    No, You can't.

    https://developer.arm.com/docs/dui0553/a/the-cortex-m4-instruction-set/miscellaneous-instructions/nop

    NOP does nothing. NOP is not necessarily a time-consuming NOP. The processor might remove it from the pipeline before it reaches the execution stage.

    Use NOP for padding, for example to place the following instruction on a 64-bit boundary.

    Graduate II
    August 31, 2019

    Also it doesn't account for time in interrupts

    Graduate II
    May 9, 2024

    I tried the DWT method in my code. It basically works.

    However, I have 2 issues:

    1. The delay time is not so accurate; and does not go linear with input value.
    2. I wonder if it's OK to call DWT_Delay_Init(void) multiple times.