漫谈LiteOS之开发板-SysTick(基于GD32450i-EVAL)
6 SysTick
1 什么是SysTick
SysTick是ARM Cortex-M3/Cortex-M4内核芯片提供的一个24位(最大值2^24 - 1)的系统节拍定时器。因此并非某开发板独有,而是所有基于上述两类处理器的所有开发板都具有的。
2 特性以及作用
2.1 特性
(1)SysTick是24位定时器,因此最大值为0xFF FFFF,注意不要超过此值。
(2)SysTick采用倒计时方式,当其设定初值并使能后,每经过一个系统时钟周期,计数值自动减1。
(3)具有自动重载和溢出中断功能,当SysTick开启后,就会自动从初始值开始递减计数,当递减到0时,则重新加载。
(4)SysTick被绑定在NVIC中,用于产生SysTick异常,可设置中断优先级。配置时只需要使能SysTick中断和处理器中断进入中断服务函数后,硬件会自动清除中断状态和计数标志位,无需手动清除。
(5)SysTick是ARM Cortex-M3/M4自带属性,并非外设,无需在RCC寄存器组打开它的时钟。
2.2 作用
(1)首先SysTick可以用于测量时间,如当做一个闹铃等。但处理器在调试期间若被叫停,则SysTick也暂停。
(2)为系统提供一个必要的时钟节拍,为实时操作系统(RTOS)的任务调度提供一个有节奏的“心跳”。
(3)我们知道很多开发板本身也存在定时器,但是各有不同。而SysTick的存在方便了程序在不同开发板上的移植。
3 寄存器
系统定时器一共有4个寄存器具体如下:
l SYST_CTRL: 系统定时器控制和状态寄存器
l SYST_LOAD:系统定时器重载值寄存器
l SYST_VAL:系统定时器当前值寄存器
l SYST_CALIB : 系统定时器校准值寄存器
其中系统定时器校准值寄存器是在出厂之前就已经配置好的,实际操作时,无需对其进行操作,接下来对上述三个寄存器分别加以介绍:
(1)SYST_CTRL寄存器:该寄存器主要用到4位,具体表1所示。
表1 SYST_CTRL寄存器信息
Name | Bit | Type | Default | Description |
ENABLE | 0 | R/W | 0 | 使能位,1开启定时器 |
TICKINT | 1 | R/W | 0 | 中断位,1允许产生中断 |
CLKSOURCE | 2 | R/W | 0 | 时钟源,1内核时钟,0外部时钟 |
COUNTFLAG | 16 | R | 0 | 上次读取该寄存器后,SysTick数到0则该位为1。若读该位,自动清零 |
(2)SYST_LOAD寄存器,用24位即0-23,最大值为2^24-1存储的是定时器倒计时的初始值,定时器开启后,从该值倒计时到0,自动从该值重新开始倒计时。具体如表2所示。
表2 SYST_LOAD寄存器信息
Name | Bit | Type | Default | Description |
RELOAD | 23:0 | R/W | 0 | 倒数到0,则自动重载 |
(3)SYST_VAL寄存器,该寄存器主要用于存储系统定时器当前值,因此也是24位即0-23,具体如表3所示。
表3 SYST_VAL寄存器信息
Name | Bit | Type | Default | Description |
CURRENT | 23:0 | R/W | 0 | 读时返回当前倒计时的值,写则清零,同时清除SYST_CTRL寄存器的CONTFLAG标志 |
4 程序
从SysTick配置的程序也可以看出只需要对前面所讲的三个寄存器操作即可,具体如下所示。其中参数ticks即为重载值,即两次中断期间的SysTick时钟周期数。
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1);
//重载值要小于0xFF FFFF(24位计数器)
SysTick->LOAD = ticks - 1;
//对重载寄存器操作设置重载值ticks-1,装载时消耗一个SysTick时钟周期
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 、
//设置中断优先级
SysTick->VAL = 0; //初始化当前值寄存器的值
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
//对控制寄存器的2,1,0位分别置1,完成时钟源设置,打开中断,使能定时器
return (0);
}
上述函数配合成下面代码就实现了毫秒级延时具体如下。
void systick_config(void)
{
if (SysTick_Config(SystemCoreClock / 1000U)){
while (1){
}
}
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
void delay_1ms(uint32_t count)
{
delay = count;
while(0U != delay){
}
}
- 点赞
- 收藏
- 关注作者
评论(0)