cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L011 + systick + WFI problem

LBogd.2
Associate II

Hello,

my STM32L011's core is running at 32 MHz. I use systick for 1 ms interrupt. However, if i try to use the WFI inside my while loop in my delay function, the timebase changes from 1 ms to 6.28 ms. Any help is appreciated!

#include "user_systick.h"
 
volatile uint32_t coefficient_ms;
volatile uint32_t sys_ticks;
 
void SysTick_Handler(void){
  sys_ticks++;	
}
 
void user_systick_init(void){	
	coefficient_ms = 32000000 / 1000;
	SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk;
}
 
void user_systick_start(void){  
	NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
}
 
void user_systick_stop(void){  
	SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk); 
}
 
void user_systick_wait_ms(uint32_t delay_value){
	SysTick->LOAD  = (uint32_t)(coefficient_ms - 1UL);  
	SysTick->VAL = 1;  	
	sys_ticks	= 0;
	SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;                         
 
	while(sys_ticks < delay_value){		
		//__WFI(); //If I uncomment this, I get a 6.28 ms timebase which is wrong.		
	}
}

5 REPLIES 5
Jeff Tenney
Senior

Try

    __DSB();
    __WFI();
    __ISB();

Also it seems odd that the wait function starts the systick but doesn't call user_systick_start(), which doesn't start the systick. It also seems odd that the wait function doesn't stop the systick at the end.

LBogd.2
Associate II

OK, I found my problem - elsewhere in my code I was using:

	RCC->APB1ENR |= RCC_APB1ENR_PWREN;	
	PWR->CR |= PWR_CR_ULP;

so before calling my user_systick_wait_ms( ) I put:

	RCC->APB1ENR |= RCC_APB1ENR_PWREN;	
	PWR->CR &= ~PWR_CR_ULP;
        RCC->APB1ENR &= ~RCC_APB1ENR_PWREN;	

This solved that issue.

Regards,

L. B.

I need the systick functionality only in certain parts of my code. The start function enables this functionality and the stop function disables it. The delay function does the actual blocking delay. If I had put the start functionality inside the delay, it would have been called every time when I called the delay. Time is power. I need low power firmware.

As it stands, the code allows SysTick interrupts every millisecond when they aren't being used. I think you could save some power by disabling the SysTick when you're not using it.

Oh, I've made a mistake, actually my code is like that:

    #include "user_systick.h"
     
    volatile uint32_t coefficient_ms;
    volatile uint32_t sys_ticks;
     
    void SysTick_Handler(void){
      sys_ticks++;	
    }
     
    void user_systick_init(void){	
    	coefficient_ms = 32000000 / 1000;
    	SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk;
        NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    }
     
    void user_systick_start(void){  
    	 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
    }
     
    void user_systick_stop(void){  
    	SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk); 
    }
     
    void user_systick_wait_ms(uint32_t delay_value){
    	SysTick->LOAD  = (uint32_t)(coefficient_ms - 1UL);  
    	SysTick->VAL = 1;  	
    	sys_ticks = 0;
                              
    	while(sys_ticks < delay_value){	}
    }

And I'm using it like that:

user_systick_start();

user_systick_wait_ms(50);

....

user_systick_stop();