1
\$\begingroup\$

I am currently trying to achieve delay of 1 uS using timer in stm32 for my application purpose.

SYSCLk is set to 16MHZ LSI and define same for timer clock.
Timer used is a 16 bit timer.
The logic I am using is this.

void delay_us (unsigned int cnt_val)
{ 
unsigned long x =0;
unsigned int cnt=0, psc_cnt = 0;
RCC->APB1ENR |= (RCC_APB1ENR_TIM6EN );
x = (unsigned int)((cnt_val * 1000) / 62);
if(x < 65536)
 {
 cnt = x;
 psc_cnt = 0;
 }
else
 {
 cnt = 0xFFFF;
 psc_cnt = x / 65536;
 }
TIM6->SR = 0x00;
TIM6->ARR = cnt;
TIM6->PSC = psc_cnt;
TIM6->CR1 |= (TIM_CR1_CEN | TIM_CR1_OPM);
while(!(TIM6->SR & TIM_SR_UIF));
RCC->APB1ENR &= ~(RCC_APB1ENR_TIM6EN); 
}

Issue is when i tried to achieve the delay of 1 us i am getting 2.5 us. I checked it by toggling the gpio.

while(1)
{
GPIOA->ODR ^= GPIO_PIN_5;
delay_us(1);
}

can't understand the reason and looking for the solution.

brhans
15.1k3 gold badges37 silver badges51 bronze badges
asked Mar 25, 2019 at 17:19
\$\endgroup\$
5
  • \$\begingroup\$ How about longer times? I guess 1us is comparable with your processor clock and very affected by the overhead of the instruction executed around. \$\endgroup\$ Commented Mar 25, 2019 at 17:24
  • \$\begingroup\$ Achieving accurate delays on the order of a microsecond will be difficult using microcontroller software. Why don't you tell us what you plan to do with this delay function? \$\endgroup\$ Commented Mar 25, 2019 at 17:48
  • \$\begingroup\$ @EugeneSh. in case of longer times as the error is in microseconds, output is acceptable I tried with 1 sec delay and it works good. \$\endgroup\$ Commented Mar 26, 2019 at 7:24
  • \$\begingroup\$ @ElliotAlderson curiosity as how far can i go. \$\endgroup\$ Commented Mar 26, 2019 at 7:25
  • 1
    \$\begingroup\$ If you need this kind of microsecond accuracy you are using the wrong tool. You'd need some beast like a fast-clocked DSP. It can be achieved with a MCU however, by simply executing a bunch of NOP. Not in a loop, but literally just NOP NOP NOP... \$\endgroup\$ Commented Mar 27, 2019 at 16:09

1 Answer 1

5
\$\begingroup\$

Look at your delay_us() function.
How many assembler instructions do you think that will compile to?
Don't forget the stack push/pop and return at the end.
Now, at 16MHz, how long do you think that function will take to execute, assuming the while() at the end just falls straight through.

I threw your function into my GCC-based ARM compiler and, without much optimization enabled, it produced 33 instructions.
Considering that your measured 2.5uSec corresponds to about 40 instructions at 16MHz, and adding a few extra instructions for the while(1) loop , the GPIO toggle and the call to the function in your main(), it looks to me as though it's pretty spot-on.

answered Mar 25, 2019 at 17:42
\$\endgroup\$
3
  • \$\begingroup\$ is there any better logic for achieving same result?. If yes a hint will be helpful. \$\endgroup\$ Commented Mar 26, 2019 at 7:26
  • \$\begingroup\$ It depends largely on what your desired use-case is. For toggling a GPIO, as in your example, you should be directly driving the pin using a hardware module in your micro and not try to control it in the firmware. So - what are you actually trying to do? \$\endgroup\$ Commented Mar 26, 2019 at 11:18
  • \$\begingroup\$ i am trying to create a delay in microseconds, toggling gpio is just for testing that delay created working expected or not. I was confirming that reason of issue is same as i am thinking and get any better solution if any \$\endgroup\$ Commented Mar 26, 2019 at 16:23

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.