[ST NUCLEO-U575ZI-Q Review] Systick time base usage and testing using HAL/LL library
[Copy link]
Preface
Systick is a standard core peripheral of CORTEX-M series microcontrollers.
Generally used for time base, timestamp, or RTOS tick timing interrupt.
Based on the GPIO in the previous article, we can test whether the systick timing is correct. We can flip the IO in the systick interrupt and use an oscilloscope/logic analyzer to measure the waveform period of the IO to test whether the timing is accurate.
process
Systick can refer to the kernel architecture document of CORTEX-M3. I will not go into details here. Just look at the code directly.
The HAL library also uses systick as a timer, and operations such as delay depend on systick.
initialization
The code is located in HAL_Init in stm32u5xx_hal.c.
HAL_StatusTypeDef HAL_Init(void)
{
/* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0U)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Update the SystemCoreClock global variable */
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR2 & RCC_CFGR2_HPRE) >> RCC_CFGR2_HPRE_Pos];
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
Call HAL_InitTick for initialization
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
if ((uint32_t)uwTickFreq == 0UL)
{
return HAL_ERROR;
}
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
The timing period is defined by HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
The default is
typedef enum
{
HAL_TICK_FREQ_10HZ = 100U,
HAL_TICK_FREQ_100HZ = 10U,
HAL_TICK_FREQ_1KHZ = 1U,
HAL_TICK_FREQ_DEFAULT = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;
Interrupt handling
SysTick_Handler calls HAL_IncTick to update the counter.
void SysTick_Handler(void)
{
static volatile uint32_t num = 0;
if(num++ >= 1000)
{
LL_GPIO_TogglePin(GPIOB, 1u<<7);
num=0;
}
HAL_IncTick();
}
Measuring time
Total code
include "stm32u575xx.h"
include "stm32u5xx_ll_gpio.h"
include "stm32u5xx_ll_bus.h"
void SysTick_Handler(void)
{
static volatile uint32_t num = 0;
if(num++ >= 1000)
{
LL_GPIO_TogglePin(GPIOB, 1u<<7);
num=0;
}
HAL_IncTick();
}
void delay(uint32_t t)
{
volatile uint32_t timeout = t;
while(t--);
}
int main(void)
{
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_GPIO_InitTypeDef GPIO_InitStruct;
//LL_GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_Init();
while(1)
{
///delay(1000000ul);
///LL_GPIO_TogglePin(GPIOB, 1u<<7);
}
}
Using a logic analyzer to measure, the IO flip time is 1.982917488/2=0.991458744S.
Since interrupt response and execution of processing code take a certain amount of time, there are some errors.
Summarize
This article introduces the use of systick and tests its accuracy. Later, we will often use time base, delay, etc. Thanks to the official library, it can be done efficiently with just a few lines of code.
|