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.
1 Answer 1
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.
-
\$\begingroup\$ is there any better logic for achieving same result?. If yes a hint will be helpful. \$\endgroup\$Vaibhav– Vaibhav2019年03月26日 07:26:49 +00:00Commented 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\$brhans– brhans2019年03月26日 11:18:56 +00:00Commented 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\$Vaibhav– Vaibhav2019年03月26日 16:23:36 +00:00Commented Mar 26, 2019 at 16:23
NOP
. Not in a loop, but literally just NOP NOP NOP... \$\endgroup\$