Skip to main content
Visitor II
March 21, 2024
Question

Is there a way to make microsecond delay in freertos

  • March 21, 2024
  • 2 replies
  • 3465 views

I need 40 us delay. I made my own function using timers, which works on NUCLEO, just using it in main. Now that I put my program my circuit, I moved that SPI part on freertos, but now I have problem, because that delay doesnt work anymore. I would use osDelay, but that is only ms and I need us. Why my delay using timers doesnt work and is there any other way to make it. Thank you for help. 

Mijta_0-1711049470365.png

Mijta_1-1711049524663.png

 

 

 

    This topic has been closed for replies.

    2 replies

    Graduate II
    March 21, 2024

    Well resetting at every entry isn't exactly thread safe.

    Read the value at entry, and compare the delta, I'd cut-n-paste-n-edit but hard to do with bitmaps.

    Visitor II
    October 28, 2024

    Have exactly same issue when need precise timing in us for SPI communications in RTOS (STM32H743 + HAL). 

    have this timDelay_us function in timer 1 but still cant get it working.

     

     

    void timDelay_us(uint16_t us){
     uint16_t entryPoint = __HAL_TIM_GET_COUNTER(&htim1);
     //__HAL_TIM_SET_COUNTER(&htim1,0); // set the counter value a 0
     while ((uint16_t)__HAL_TIM_GET_COUNTER(&htim1) < (us + entryPoint)); 
    }

     

     

    Graduate II
    October 28, 2024

    You have the math backward, compute the delta (now - start), and then compare with the elapsed time delay you're looking for

     

    void timDelay_us(uint16_t us){
     uint16_t entryPoint = __HAL_TIM_GET_COUNTER(&htim1);
     while (((uint16_t)__HAL_TIM_GET_COUNTER(&htim1) - entryPoint) < us); 
    }

     

    The unsigned math should then manage the wrapping transparently.

    Here TIM would be maximal (0 .. 0xFFFF), clocking at 1 MHz

    Interrupts and context changes will make the time the delay takes a little more complicated, but should be at least as long as requested +/- 1us depending on when you enter. For finer granularity, clock faster.

    But you can't use an interrupt at 1 MHz, you'll just saturate the processor.

     

    Explorer
    October 29, 2024

     

    /* timer for nona second, need a hardware 32-bit timer */
    #define MY_NS_TIM TIM5
    #define MY_NS_TIM_HANDLER htim5
    
    	// nsTmr_t should use 32-bit timer
    	typedef uint32_t ns_t;
    	typedef struct nsTmr_t
    	{
    		ns_t tickstart;
    		ns_t wait;
    	} nsTmr_t;

     

    extern TIM_HandleTypeDef MY_NS_TIM_HANDLER;
    #define NS_SCALE (1000 / TIM_MHZ) // 1MHZ = 1us = 1000ns
    void InitNsTmr()
    {
    	HAL_TIM_Base_Start(&MY_NS_TIM_HANDLER);
    }
    
    void SetNsTmr(nsTmr_t *tmr, ns_t delay)
    {
    	tmr->tickstart = (ns_t)MY_NS_TIM->CNT;
    	tmr->wait = (delay != 0 && delay < NS_SCALE) ? 1 : (ns_t)(delay / NS_SCALE);
    }
    
    void ClrNsTmr(nsTmr_t *tmr)
    {
    	tmr->tickstart = (ns_t)MY_NS_TIM->CNT;
    	tmr->wait = 0;
    }
    
    int IsNsTmrExpired(nsTmr_t *tmr)
    {
    	return (tmr->wait != 0) && ((ns_t)((ns_t)MY_NS_TIM->CNT - tmr->tickstart) >= tmr->wait);
    }
    
    int IsNsTmrSet(nsTmr_t *tmr)
    {
    	return tmr->wait;
    }
    
    void Delay_ns(ns_t delay)
    {
    	nsTmr_t tmr;
    	SetNsTmr(&tmr, delay);
    	while ((ns_t)((ns_t)MY_NS_TIM->CNT - tmr.tickstart) < tmr.wait)
    		;
    }
    
    ns_t GetNsTmrCnt(nsTmr_t *tmr)
    {
    	return MY_NS_TIM->CNT - tmr->tickstart;
    }