Arm通用计时器简介

所有使用Arm处理器的系统中都会包含一个标准化的通用定时器(Generic Timer)框架。这个通用定时器系统提供了一个系统计数器(System Counter)和一组定时器(Timer)。其结构如下图:

可以看到,系统计数器是全局唯一的,并且全局共享,对系统中的所有Arm核心进行广播。这个计数器以一个固定的频率递增(频率范围通常从1MHz到50MHz不等)。同时,这个系统计数器还是一直存在的,哪怕系统处于待机状态,所有内核都被关闭了,它仍然可以工作。计数器的宽度有56位至64位,计数到达最大值后会回滚。

每一个Arm核都配备一组专门为自己服务的定时器。定时器到期了之后会通过私有的PPI(Private Peripheral Interrupt)向通用中断控制器发中断请求。按照不同的指令集扩展,每组都有最多7个定时器,但无论如何最基本的都会提供4个,它们分别是:

  • EL1 physical timer:给操作系统用的物理定时器;
  • EL1 virtual timer:给操作系统用的虚拟定时器;
  • Non-secure EL2 physical timer:给虚拟机的宿主系统用的定时器;
  • EL3 physical timer:给运行于EL3内的固件程序使用的定时器。

对于系统计数器来说,可以通过读取控制寄存器CNTPCT_EL0来获得当前的系统计数值(无论处于哪个异常级别),也就是通过以下汇编指令:

MRS Xn, CNTPCT_EL0

这条指令是可以乱序执行的,使用的时候要适当保护。确切的说,这是读取物理计数器的值,系统中其实还存在一个虚拟计数器的值,这个虚拟计数器主要也是给虚拟机的宿主系统用的。虚拟计数器的值和物理计数器的值有如下对应关系:

虚拟计数器 = 物理计数器 - 偏移

这个偏移的值是通过控制寄存器CNTVOFF_EL2设置的,看名字就知道只能在EL2或EL3层才有权限设置和访问,如果不设置的话,默认值是0,也就是虚拟计数器和物理计数器的值一致。如果想得到虚拟计数器的值,可以通过读取CNTVCT_EL0控制寄存器来获得。

系统计数器的频率主要通过控制寄存器CNTFRQ_EL0来控制。频率是可以随意设定的,但只能在EL3下设置,也就是说在系统固件程序里。在其它的异常级别里(EL2到EL0)都不能设置,但是可以通过读取这个CNTFRQ_EL0寄存器来获得在固件中设置好的频率。

对于Arm定时器来说,总体有两种工作方式:

  1. 到一个绝对时间之后就触发;
  2. 从现在开始再过一定时间间隔之后触发。

Arm定时器通过两类寄存器来实现以上两种工作方式。一类叫做比较寄存器(CVAL),还有一类叫做定时寄存器(TVAL)。

比较寄存器有64位,如果设置了之后,当系统计数器达到或超过了这个值之后(CVAL<系统计数器),就会触发定时器中断。通过这种方式来实现第一类定时任务,。

定时寄存器有32位,如果设置了之后,会将比较寄存器设置成当前系统计数器加上设置的定时寄存器的值(CVAL=系统计数器+TVAL),后面就一样了,当系统计数器达到或超过了这个值后,就会触发定时中断。通过这种方式来实现第二种定时任务。

可以看出来,无论那种类型的定时器都是单次出发的(One Shot),如果想要周期触发,必须在中断处理程序中重新设置。这也刚好满足Linux系统中对于高精度定时器的要求。

除了设置定时条件的寄存器,其实每组定时器都还有一个控制寄存器(CTL),其只有最低三位有意义,其它的60位全是保留的,设置成0:

最低三位分别是:

  • ENABLE:是否打开定时器,使其工作;
  • IMASK:中断掩码,如果设置成1,则即使定时器是工作的,仍然不会发出中断;
  • ISTATUS:如果定时器打开的话,且满足了触发条件,则将这一位设置成1。

所以很简单,如果想让定时器按照要求发出中断的话,必须将Enable位设置成1,且IMASK位必须设置成0。

定时中断满足触发条件后,其并不会自己消失。如果在中断处理程序中不做处理的话,那同一个触发条件会不停的触发中断。

前面说到了,每个Arm核都有4个私有定时器,每个定时器都有一个比较寄存器、一个定时寄存器、一个控制寄存器,所以一共应该有12个寄存器可以操作,将它们的命名总结如下:

定时器类型比较寄存器名定时寄存器名控制寄存器名访问异常级别
EL1 physical timerCNTP_CVAL_EL0CNTP_TVAL_EL0CNTP_CTL_EL0EL0和EL1
EL1 virtual timerCNTV_CVAL_EL0CNTV_TVAL_EL0CNTV_CTL_EL0EL0和EL1
Non-secure EL2 physical timerCNTHP_CVAL_EL2CNTHP_TVAL_EL2CNTHP_CTL_EL2NS.EL2
EL3 physical timerCNTPS_CVAL_EL1CNTPS_TVAL_EL1CNTPS_CTL_EL1EL3和S.EL1

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页