本章参考资料《ARM Cortex™-M4F 技术参考手册》 -4.5 章节 SysTick Timer(STK), 和4.48 章节 SHPRx,其中 STK 这个章节有 SysTick 的简介和寄存器的详细描述。因为SysTick 是属于 CM4 内核的外设,有关寄存器的定义和部分库函数都在 core_cm4.h 这个头文件中实现。所以学习 SysTick 的时候可以参考这两个资料,一个是文档,一个是源码。
SysTick简介
SysTick—系统定时器是属于 CM4 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 180M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。
因为 SysTick 是属于 CM4 内核的外设,所以所有基于 CM4 内核的单片机都具有这个系统定时器,使得软件在 CM4 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
寄存器
寄存器名称 | 寄存器描述 |
---|---|
CTRL | SysTick 控制及状态寄存器 |
LOAD | SysTick 重装载数值寄存器 |
VAL | SysTick 当前数值寄存器 |
CALIB | SysTick 校准数值寄存器 |
表 18-2 SysTick 控制及状态寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
16 | COUNTFLAG | R/W | 0 | 如果在上次读取本寄存器后, SysTick 已经计到了 0,则该位为 1。 |
2 | CLKSOURCE | R/W | 0 | 时钟源选择位, 0=AHB/8, 1=处理器时钟 AHB |
1 | TICKINT | R/W | 0 | 1=SysTick 倒数计数到 0 时产生 SysTick 异常请求 , 0= 数 到 0 时 无 动 作 。 也 可 以 通 过 读 取COUNTFLAG 标志位来确定计数器是否递减到0 |
0 | ENABLE | R/W | 0 | SysTick 定时器的使能位 |
表 18-3 SysTick 重装载数值寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
23:0 | RELOAD | R/W | 0 | 当倒数计数至零时,将被重装载的值 |
表 18-4 SysTick 当前数值寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
23:0 | CURRENT | R/W | 0 | 读取时返回当前倒计数的值,写它则使之清零,同时还会清除在 SysTick 控制及状态寄存器中的 COUNTFLAG 标 |
表 18-5 SysTick 校准数值寄存器
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
31 | NOREF | R | 0 | NOREF flag. Reads as zero. Indicates that aseparate reference clock is provided.The frequency of this clock is HCLK/8 |
30 | SKEW | R | 1 | SKEW flag: Indicates whether the TENMS valueis exact. Reads as one. Calibrationvalue for the 1 ms inexact timing is not knownbecause TENMS is not known. This can affectthe suitability of SysTick as a software real timeclock |
23:0 | TENMS | R | 0 | Calibration value. Indicates the calibration valuewhen the SysTick counterruns on HCLK max/8as external clock. The value is productdependent, please refer to theProduct ReferenceManual, SysTick Calibration Value section.When HCLK is programmed atthe maximumfrequency, the SysTick period is 1ms.If calibration information is not known, calculatethe calibration value required from thefrequencyof the processor clock or external clock |
SysTick定时实验
SysTick_Config()库函数主要配置了 SysTick 中的三个寄存器: LOAD、 VAL 和 CTRL,有关具体的部分看代码注释即可。其中还调用了固件库函数 NVIC_SetPriority()来配置系统定时器的中断优先级,该库函数也在 core_m4.h 中定义,原型如下:
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if ((int32_t)IRQn < 0)
{
SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] =
(uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
NVIC->IP[((uint32_t)(int32_t)IRQn)] =(uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
因为 SysTick 属于内核外设,跟普通外设的中断优先级有些区别,并没有抢占优先级和子优先级的说法。在 STM32F429 中,内核外设的中断优先级由内核 SCB 这个外设的寄存器:SHPRx(x=1.2.3)来配置。有关 SHPRx 寄存器的详细描述可参考《Cortex-M4 内核编程手册》 4.4.8 章节。下面我们简单介绍下这个寄存器。
SPRH1-SPRH3 是一个 32 位的寄存器,但是只能通过字节访问,每 8 个字段控制着一个内核外设的中断优先级的配置。在 STM32F429 中,只有位 7:3 这高四位有效,低四位没有用到,所以内核外设的中断优先级可编程为: 0~15,只有 16 个可编程优先级,数值越小,优先级越高。如果软件优先级配置相同,那就根据他们在中断向量表里面的位置编号来决定优先级大小,编号越小,优先级越高。
如果要修改内核外设的优先级,只需要修改下面三个寄存器对应的某个字段即可。
在系统定时器中,配置优先级为(1UL << __NVIC_PRIO_BITS) - 1UL),其中宏__NVIC_PRIO_BITS 为 4,那计算结果就等于 15,可以看出系统定时器此时设置的优先级在内核外设中是最低的。
// 设置系统定时器中断优先级 NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
参考引用:
- 野火---《零死角玩转STM32-F429挑战者》
- 《STM32F4xx中文参考手册》
- 《Cortex-M4内核编程手册》