Skip to main content
Sam Walsh
Associate
August 15, 2017
Question

LL_mDelay taking an extra millisecond?

  • August 15, 2017
  • 1 reply
  • 6406 views
Posted on August 15, 2017 at 15:12

Hi, I am using a Nucleo F401RE running at 84 MHz (8 MHz XTAL PLL'd up to 84 MHz) and then using Timer 2 as a simple counter to count how long it takes to run the delays.

Timer 2 is set to run at 84 MHz with no prescaler and I am using LL_mDelay for the delays. I have a function which converts the counts to milliseconds. You can see in the timer2 function I am simply reading the count, delaying and resetting the count. However every one of my LL_mDelays are a millisecond over what they should be.

Eg LL_mDelay(1) takes 2 milliseconds, LL_mDelay(0) takes 1 millisecond.

Any ideas why this is? I have attached the watch window output and the project as a zip.

#include 'main.h'
void SystemClock_Config(void);
void Configure_Timer2(void);
float Counts_To_Ms(uint32_t);
volatile uint32_t Counts[10];
volatile float Counts_ms[10];
int main(void)
{
/* Configure the system clock to 84 MHz */
SystemClock_Config();
/* Configure Timer 2 as a software start stop timer */
Configure_Timer2();

/* Infinite loop */
while (1)
{
}
}
float Counts_To_Ms(uint32_t count){
return ((1.0/84000000) * count) * 1000;
}
void Configure_Timer2(void){
// Timer 2 peripheral Configuration
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); // Enable clock to Timer 2 peripheral
/* Enable counter */
LL_TIM_EnableCounter(TIM2);
//First Count
LL_mDelay(0);
Counts[0] = LL_TIM_GetCounter(TIM2);
Counts_ms[0] = Counts_To_Ms(Counts[0]);
LL_TIM_SetCounter(TIM2, 0);
//Second Count
LL_mDelay(1);
Counts[1] = LL_TIM_GetCounter(TIM2);
Counts_ms[1] = Counts_To_Ms(Counts[1]);
LL_TIM_SetCounter(TIM2, 0);
//Third Count
LL_mDelay(2);
Counts[2] = LL_TIM_GetCounter(TIM2);
Counts_ms[2] = Counts_To_Ms(Counts[2]);
LL_TIM_SetCounter(TIM2, 0);
//Fourth Count
LL_mDelay(3);
Counts[3] = LL_TIM_GetCounter(TIM2); 
Counts_ms[3] = Counts_To_Ms(Counts[3]);
LL_TIM_SetCounter(TIM2, 0);
//Fifth Count
LL_mDelay(4);
Counts[4] = LL_TIM_GetCounter(TIM2);
Counts_ms[4] = Counts_To_Ms(Counts[4]);
LL_TIM_SetCounter(TIM2, 0);
//Sixth Count
LL_mDelay(5);
Counts[5] = LL_TIM_GetCounter(TIM2);
Counts_ms[5] = Counts_To_Ms(Counts[5]);
LL_TIM_SetCounter(TIM2, 0);
//Seventh Count
LL_mDelay(6);
Counts[6] = LL_TIM_GetCounter(TIM2);
Counts_ms[6] = Counts_To_Ms(Counts[6]);
LL_TIM_SetCounter(TIM2, 0);
__nop();
}
/**
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 84000000
* HCLK(Hz) = 84000000
* AHB Prescaler = 1
* APB1 Prescaler = 1
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 8000000
* PLL_M = 8
* PLL_N = 336
* PLL_P = 4
* VDD(V) = 3.3
* Main regulator output voltage = Scale2 mode
* Flash Latency(WS) = 2
*/
void SystemClock_Config(void)
{
/* Enable HSE oscillator */
LL_RCC_HSE_EnableBypass();
LL_RCC_HSE_Enable();
while(LL_RCC_HSE_IsReady() != 1){};
/* Set FLASH latency */
LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
/* Main PLL configuration and activation */
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_8, 336, LL_RCC_PLLP_DIV_4);
LL_RCC_PLL_Enable();
while(LL_RCC_PLL_IsReady() != 1){};
/* Sysclk activation on the main PLL */
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL){};
/* Set APB1 & APB2 prescaler */
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
/* Set systick to 1us */
SysTick_Config(84000000 / 1000);
/* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */
SystemCoreClock = 84000000;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

#nucleo #ll #low-layer #stm32f4
This topic has been closed for replies.

1 reply

After Forever
Senior III
August 15, 2017
Posted on August 15, 2017 at 15:36

Please use a 'Syntax highlighter' section for pasting code.

Looking at LL_mDelay function's code it seems there is a bug there:

#define LL_MAX_DELAY 0xFFFFFFFFU�?�?
void LL_mDelay(uint32_t Delay)
{
 __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
 /* Add this code to indicate that local variable is not used */
 ((void)tmp);
 // !!! BUG?: This condition will pretty much always be true, so we will get one more millisecond than we desire
 /* Add a period to guaranty minimum wait */
 if(Delay < LL_MAX_DELAY)
 {
 Delay++;
 }
 while (Delay)
 {
 if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
 {
 Delay--;
 }
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

See my comment starting with '// !!! BUG'.

Sam Walsh
Sam WalshAuthor
Associate
August 15, 2017
Posted on August 15, 2017 at 16:25

You are totally correct, I commented the lines and the delays are all correct. I hope ST can fix this, seems a large oversight seems as it is the only official delay function provided.

void LL_mDelay(uint32_t Delay)
{
 __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
 /* Add this code to indicate that local variable is not used */
 ((void)tmp);
 /* Add a period to guaranty minimum wait */
 //if(Delay <= LL_MAX_DELAY)
 //{
 // Delay++;
 //}
 while (Delay)
 {
 if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
 {
 Delay--;
 }
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

After Forever
Senior III
August 15, 2017
Posted on August 15, 2017 at 17:17

You are totally correct

Giving it another thought, maybe not so. I think this function is not intended to be very precise. If you need precise delays use a hardware timer with interrupts.

The thing is, when entering into this function the time may already be, for example, on 900-th microsecond of a millisecond, so the next millisecond will tick just after 0.1 milliseconds.

That condition that you commented out moves the possible skew to from 'taking up to millisecond less time' to 'taking up to milliseconds more time'. Maybe the developers decided that it's less desirable the delay take a little less time than a little more time.