短文标题:SysTick:内核自带“心跳”,HAL_Delay和RTOS都靠它

你有没有想过一个问题:HAL_Delay(1000)为什么能延时1秒?FreeRTOS的vTaskDelay(100)又是怎么知道100ms到了?答案:SysTick。 一个集成在Cortex-M内核里的24位递减定时器,在所有Cortex-M芯片上都有,地址固定。

SysTick的三个寄存器(CMSIS定义)

配置方法:

SysTick_Config(SystemCoreClock / 1000);  // 每1ms中断一次

为HAL_Delay提供“心跳”

HAL_Delay的底层是uwTick变量,由SysTick中断每1ms加1。

__weak void HAL_Delay(uint32_t Delay)

{

    uint32_t tickstart = HAL_GetTick();

    uint32_t wait = Delay;

    if (wait < HAL_MAX_DELAY) wait++;  // 补偿一个tick

    while ((HAL_GetTick() - tickstart) < wait);

}

SysTick停,HAL_Delay就停。 调试时在SysTick中断设断点会导致时间停滞。RTOS的心跳,FreeRTOS的configTICK_RATE_HZ(通常100或1000Hz)对应SysTick的中断频率。SysTick中断里调用xTaskIncrementTick(),检查任务延时、时间片轮转等。没有SysTick,RTOS就没有时间基准,任务无法切换。

时钟频率改变后必须重配SysTick,上电默认用HSI(8MHz)配置SysTick。执行SystemClock_Config切换到PLL(72MHz)后,SystemCoreClock更新为72000000,但SysTick的LOAD值仍是8000。72MHz下8000个时钟周期≈111μs,不是1ms。HAL_RCC_ClockConfig会自动调用HAL_InitTick重配SysTick,手动改时钟时别忘调用。

SysTick中断优先级,SysTick中断优先级通常设为最低(15),确保高优先级中断(串口接收、外部急停)能随时打断SysTick,不增加中断延迟。FreeRTOS的最低优先级可设为configLIBRARY_LOWEST_INTERRUPT_PRIORITY,SysTick设为此值。

微秒延时的替代方案,SysTick的1ms分辨率不适合微秒延时。方案:

  1. 硬件定时器(TIM2):微秒级PWM或单脉冲模式
  2. DWT外设(Cortex-M内核自带):DWT->CYCCNT 72MHz下1 tick≈13.9ns

void delay_us(uint32_t us) {

    uint32_t start = DWT->CYCCNT;

    uint32_t cycles = us * (SystemCoreClock / 1000000);

    while ((DWT->CYCCNT - start) < cycles);

}

这个故事的启示,SysTick不是“又一个定时器”,它是系统软件的时间基石。HAL_Delay、RTOS、软件定时器都依赖它的心跳。没有SysTick,STM32的软件生态会塌掉一半。

写在最后,SysTick不起眼,但它是整个嵌入式软件的“脉搏”。HAL_Delay靠它,RTOS靠它,软件定时器靠它。一个1ms的心跳,撑起整个系统的时间线。


(本文灵感源于于振南《新概念ARM32单片机》教程第6.1节、第6.2节、第6.3节。)

觉得有用?点赞、转发,让更多人看懂SysTick的“心跳”智慧。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐