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.
Best Answer
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 yourmain()
, it looks to me as though it's pretty spot-on.