打印
[应用方案]

Cortex-M3之SysTick

[复制链接]
1526|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lovecat2015|  楼主 | 2016-10-9 19:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。 SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。它使操作系统和其它系统软件在CM3器件间的移植变得简单多了,因为在所有CM3产品间对其处理都是相同的。


先制动STCLK为HCLK的多少,例如STCLK=HCLK/8,HCLK为72M,则STCLK为9M,也就是一次计数的时间为1/9us。
示范程序如下:
沙发
lovecat2015|  楼主 | 2016-10-9 19:35 | 只看该作者
void delay_ms(u16 nms)
{      
u32temp;   
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL=0x00;          //清空计数器
SysTick->CTRL=0x01;         //开始倒数
do
{
  temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达  
SysTick->CTRL=0x00;      //关闭计数器
SysTick->VAL=0X00;      //清空计数器      
}

//延时nus
//nus为要延时的us数.               
void delay_us(u32 nus)
{  
u32temp;     
SysTick->LOAD=nus*fac_us;//时间加载   
SysTick->VAL=0x00;       //清空计数器
SysTick->CTRL=0x01;     //开始倒数  
do
{
  temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达  
SysTick->CTRL=0x00;      //关闭计数器
SysTick->VAL=0X00;      //清空计数器
}


使用特权

评论回复
板凳
lovecat2015|  楼主 | 2016-10-9 19:36 | 只看该作者
MDK中这几个寄存器被定义在了一个结构体中,如图:

#defineSCS_BASE             ((u32)0xE000E000)
#defineSysTick_BASE         (SCS_BASE + 0x0010)

#ifdef _SysTick
  #defineSysTick            ((SysTick_TypeDef *) SysTick_BASE)
#endif
//把SysTick_BASE强制转换成SysTick_TypeDef结构体指针的地址



使用特权

评论回复
地板
598330983| | 2016-10-9 21:33 | 只看该作者
STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同

使用特权

评论回复
5
天灵灵地灵灵| | 2016-10-9 22:32 | 只看该作者
SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。

使用特权

评论回复
6
wahahaheihei| | 2016-10-10 16:35 | 只看该作者
Systick就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。

使用特权

评论回复
7
Jessicakjdsl| | 2016-10-17 20:06 | 只看该作者
学习ucos ii的时候可以深刻的学习systick

使用特权

评论回复
8
wahahaheihei| | 2016-10-18 16:07 | 只看该作者
STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同

使用特权

评论回复
9
稳稳の幸福| | 2016-10-19 14:16 | 只看该作者
Systick简介 Systick也叫系统滴答定时器,滴答定时器就是一个非常基本的倒计时定时器。

使用特权

评论回复
10
zhuomuniao110| | 2016-10-19 14:38 | 只看该作者
该定时器的时钟源可以是内部时钟

使用特权

评论回复
11
gaoyang9992006| | 2016-10-20 10:51 | 只看该作者
讲的很清楚,把这个滴答时钟的用法都说明白了。

使用特权

评论回复
12
zhuomuniao110| | 2016-10-21 21:27 | 只看该作者
Systick也叫系统滴答定时器,滴答定时器就是一个非常基本的倒计时定时器。它存在的意义是为系统提供一个时基,能够给操作系统提供一个硬件上的中断。使用Systick能够精准延时,对于时间要求严格的场所,意义十分重大

使用特权

评论回复
13
643757107| | 2016-10-22 11:28 | 只看该作者
请问时间的嘀嗒数是根据什么来设定的
有必要明确一些Linux内核时钟驱动中的基本概念。
(1)时钟周期(clock cycle)的频率:8253/8254 PIT的本质就是对由晶体振荡器产生的时钟周期进行计数,晶体振荡器在1秒时间内产生的时钟脉冲个数就是时钟周期的频率。Linux用宏 CLOCK_TICK_RATE来表示8254 PIT的输入时钟脉冲的频率(在PC机中这个值通常是1193180HZ),该宏定义在include/asm-i386/timex.h头文件中:
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
(2)时钟滴答(clock tick):我们知道,当PIT通道0的计数器减到0值时,它就在IRQ0上产生一次时钟中断,也即一次时钟滴答。PIT通道0的计数器的初始值决定了要过多少时钟周期才产生一次时钟中断,因此也就决定了一次时钟滴答的时间间隔长度。
(3)时钟滴答的频率(HZ):也即1秒时间内PIT所产生的时钟滴答次数。类似地,这个值也是由PIT通道0的计数器初值决定的(反过来说,确定了时钟滴答的频率值后也就可以确定8254 PIT通道0的计数器初值)。Linux内核用宏HZ来表示时钟滴答的频率,而且在不同的平台上HZ有不同的定义值。对于ALPHA和IA62平台HZ的值是1024,对于SPARC、MIPS、ARM和i386等平台HZ的值都是100。该宏在i386平台上的定义如下(include/asm- i386/param.h):
#ifndef HZ
#define HZ 100
#endif
根据HZ的值,我们也可以知道一次时钟滴答的具体时间间隔应该是(1000ms/HZ)=10ms。
(4)时钟滴答的时间间隔:Linux用全局变量tick来表示时钟滴答的时间间隔长度,该变量定义在kernel/timer.c文件中,如下:
long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */
tick变量的单位是微妙(μs),由于在不同平台上宏HZ的值会有所不同,因此方程式tick=1000000÷HZ的结果可能会是个小数,因此将其进行四舍五入成一个整数,所以Linux将tick定义成(1000000+HZ/2)/HZ,其中被除数表达式中的HZ/2的作用就是用来将 tick值向上圆整成一个整型数。
另外,Linux还用宏TICK_SIZE来作为tick变量的引用别名(alias),其定义如下(arch/i386/kernel/time.c):
#define TICK_SIZE tick
(5)宏LATCH:Linux用宏LATCH来定义要写到PIT通道0的计数器中的值,它表示PIT将没隔多少个时钟周期产生一次时钟中断。显然LATCH应该由下列公式计算:
LATCH=(1秒之内的时钟周期个数)÷(1秒之内的时钟中断次数)=(CLOCK_TICK_RATE)÷(HZ)
类似地,上述公式的结果可能会是个小数,应该对其进行四舍五入。所以,Linux将LATCH定义为(include/linux/timex.h):
/* LATCH is used in the interval timer and ftape setup. */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
类似地,被除数表达式中的HZ/2也是用来将LATCH向上圆整成一个整数。

使用特权

评论回复
14
yyglucky| | 2017-7-22 15:08 | 只看该作者

使用特权

评论回复
15
643757107| | 2017-7-23 11:45 | 只看该作者
这个是定时器的章节内容?

使用特权

评论回复
16
yyglucky| | 2017-8-7 16:43 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

80

主题

816

帖子

0

粉丝