参考文档:
《Cortex -A7 MPCore Technical Reference Manual》
中Chapter 9:Generic Timer
。
《ARM ® Architecture Reference Manual ARMv7-A and ARMv7-R edition》
中Chapter B8:The Generic Timer
。
一、Chapter B8 The Generic Timer 翻译
这一章节描述ARM
通用定时器的实现,ARM
通用定时器实现对于ARMv7-A
和ARMv7-R
架构处理器是一个可扩展选项。它包括定义了ARM
通用寄存器的系统控制接口。
包含以下章节:
关于通用定时器(B8-1960
页)通用定时器寄存器摘要(B8-1969
页)
Appendix D5 System Level Implementation of the Generic Timer
描述通用定时器系统实现等级。
注:Chapter B4 System Control Registers in a VMSA implementation
和Chapter B6 System Control Registers in a PMSA implementation
都描述通用定时器CP15
寄存器。大多数寄存器被包含在VMSA
和PMSA
实现中,对于这些寄存器,VMSA
和PMSA
实现中的位分配是相同的。但是,本章中的大多数寄存器引用都链接到Chapter B4
中的寄存器描述。
1、关于通用定时器
图B8-1
中展示使用通用定时器作为系统定时器的一个片上系统的示例。在这个图片中:
本手册定义了多处理器块中各个处理器的体系结构。
《ARM Generic Interrupt Controller Architecture Specification》
为GIC
定义了一个可能的架构。
通用计时器功能分布在多个组件中。
本章:
给出通用定时器的一般描述。
定义通用计时器的系统控制寄存器接口。图B8-1
中所示的每个处理器都包含此接口的实现。
通用定时器:
提供一个系统计数器,实时测量时间的流逝。在支持虚拟化的系统中,支持测量虚拟时间流逝的虚拟计数器。也就是说,虚拟计数器可以测量特定虚拟机上的时间流逝。提供定时器,它可以在一段时间过去后断言计时器输出信号。计时器: 可以向上或向下计数。在支持虚拟化的组件中,可以实时或虚拟运行。
注:定时器输出信号可以用作电平敏感中断信号。
1、系统计数器
通用定时器提供了一个具有以下规范的系统计数器:
Width
:至少56
位宽。计数器的任何64
位读取返回的值都是零扩展为64
位。
Frequency
:固定频率的增量,通常在1-50MHz
范围内。可以支持一种或多种可选的工作模式,在这种模式下,它以较低的频率递增较大的数量,通常用于节省功耗。
Roll-over
:周转时间不少于40
年。
Accuracy
:ARM
没有指定所需的精度,但建议计数器在24
小时周期内增益或损失不超过10
秒。低频模式的使用不能影响实现的精度。
Start-up
:从零开始运行。
系统计数器必须提供系统时间的统一视图。更准确地说,以下事件序列必须无法显示系统时间的倒退:
设备A
从系统计数器读取时间。设备A
与系统中的另一个设备B
通信。设备B
识别出与设备A
的通信后,从系统计数器中读取时间。
系统计数器必须在始终接通的电源域中实现。
为了支持低功耗工作模式,计数器可以在较低频率下以更大的数量递增。例如,一个10MHz
的系统计数器可以增加:
在10MHz
增加1
。在20kHz
增加500
,当系统降低时钟频率时,降低功耗。
在这种情况下,计数器必须支持高频率、高精度和低频率、低精度之间的转换,而不影响计数器所需的精度。
软件可以访问CNTFRQ
寄存器以读取系统计数器的时钟频率,并且具有足够权限的软件可以修改该寄存器的值。详细信息见Initializing and reading the system counter frequency
。
从系统计数器的计数被分配到系统组件的机制是由具体实现定义的,但是每个具有系统控制寄存器接口到系统计数器的处理器必须包含一个计数器输入,该输入可以捕获计数器的每个增量。
注:因此,系统计数器可以独立于处理器进行计时,计数值可以使用Gray
代码序列进行分配。Gray-count scheme for timer distribution scheme on page D5-2427
给出更多信息。
初始化和读取系统计数器频率
通常,系统以固定频率驱动系统计数器,在系统引导过程中,CNTFRQ
寄存器必须编程为这个值。在一个支持ARM
安全扩展的实现中,只有在安全PL1
模式下执行的软件才能写入CNTFRQ
。如果系统允许对系统计数器频率进行任何配置,则必须确保CNTFRQ
始终编程为正确的系统计数器频率。
注:CNTFRQ
寄存器在复位时是未知的,因此计数器频率必须写入CNTFRQ
作为系统引导过程的一部分。
软件可以读取CNTFRQ
寄存器,以确定当前系统计数器频率,处于以下状态和模式:
不安全的PL2
模式。安全和非安全PL1
模式。当CNTKCTL.PL0PCTEN
设置为1
时,“安全"和"不安全”PL0
模式。
系统计数器的内存映射控件
某些系统计数器控件只能通过与系统计数器的内存映射接口进行访问。这些控件包括:
启用和禁用计数器。设置计数器值。更改操作模式,以更改更新频率和增量值。启用调试时暂停,然后调试器可以使用该调试器挂起计数。
对于更多描述见Appendix D5 System Level Implementation of the Generic Timer
。
2、物理计数器
处理器提供一个物理计数器,该计数器包含系统计数器的计数值。CNTPCT
寄存器保存当前的物理计数器值。
访问物理计数器
具有足够权限的软件可以使用64
位系统控制寄存器读取CNTPCT
。
在不包括虚拟化扩展的实现中,无论安全状态如何,始终可以从PL1
模式访问CNTPCT
。
在包含虚拟化扩展的实现中,CNTPCT
:
始终可以从安全PL1
模式和非安全Hyp
模式访问。仅当CNTHCTL.PL1PCTEN
设置为1
时,才能从非安全PL1
模式访问。当CNTHCTL.PL1PCTEN
设置为0
时,任何从非安全PL1
模式访问CNTPCT
的尝试都会产生一个Hyp Trap
异常。详细信息见Hyp Trap exception on page B1-1209
。
此外,当CNTHCTL.PL1PCTEN
设置为1
时,如果在当前安全状态下可以从PL1
模式访问CNTPCT
,那么在该安全状态下也可以从PL0
模式访问CNTPCT
。
当CNTKCTL.PL0PCTEN
设置为0
时,任何从PL0
模式访问CNTPCT
的尝试都会产生一个Undefined Instruction
异常。
在包含虚拟化扩展的实现中:
CNTKCTL
控件的优先级高于CNTHCTL
控件。当下面两个都适用时,这意味着尝试从非安全PL0
模式访问CNTPCT
会产生一个Undefined Instruction
异常:CNTHCTL.PL1PCTEN
设置为0
,表示禁止非安全PL1
模式访问。CNTHCTL.PL0PCTEN
设置为0
,表示禁止PL0
模式访问。 启用PL0
访问后,CNTHCTL
将应用于不安全的PL0
访问。当同时满足以下两种情况时,这意味着尝试从非安全PL0
模式访问CNTPCT
将生成Hyp Trap
异常:CNTHCTL.PL1PCTEN
设置为0
,禁用非安全PL1
模式访问。CNTHCTL.PL0PCTEN
设置为1
,以允许从PL0
模式访问。
CNTPCT
的读取可以推测性地发生,并且相对于在同一处理器上执行的其他指令而言是无序的。例如,如果从内存中读取用于从另一个代理获取信号,该信号指示必须读取CNTPCT
,必须使用ISB
来确保在从存储器读取信号后读取CNTPCT
,如以下代码序列所示:
3、虚拟计数器
通用计时器的实现始终包括一个虚拟计数器,该计数器指示虚拟时间:
在不包括虚拟化扩展的处理器实现中,虚拟时间与物理时间相同,并且虚拟计数器包含与物理计数器相同的值。在包含虚拟化扩展的处理器实现中,虚拟计数器包含物理计数器的值减去64
位虚拟偏移量。在不安全的PL1
或PL0
模式下执行时,虚拟偏移量值与当前虚拟机相关。
在包含虚拟化扩展的处理器实现中,CNTVOFF
寄存器包含虚拟偏移。CNTVOFF
只能从Hyp
模式访问,当SCR.NS
设置为1
时,只能从监视器模式访问。
注:通用计时器的所有实现都包括虚拟计数器。但是,只有支持虚拟化的系统才能明确区分物理时间和虚拟时间,并且:
在支持虚拟化的系统中,CNTVOFF
作为RW
寄存器实现。在不支持虚拟化的系统中: 如果系统包含安全扩展,则从安全监视器模式访问CNTVOFF
是不可预测的。虚拟计数器的行为就像CNTVOFF
为零一样。
更多信息看Status of the CNTVOFF register on page B8-1970
。
CNTVCT
寄存器保存当前虚拟计数器值。
访问虚拟计数器
具有足够权限的软件可以使用64
位系统控制寄存器读取CNTVCT
。
CNTVCT
始终可从安全PL1
模式以及非安全PL1
和PL2
模式访问。
此外,当CNTKCTL.PL0VCTEN
设置为1
时,可以从PL0
模式访问CNTVCT
。
当CNTKCTL.PL0VCTEN
设置为0
时,任何从PL0
模式访问CNTVCT
的尝试都会生成Undefined Instruction
异常。
CNTVCT
的读取可以推测性地发生,并且相对于在同一处理器上执行的其他指令而言是无序的。例如,如果从内存中读取用于从另一个代理获取指示必须读取CNTVCT
的信号,必须使用ISB
来确保在从内存读取信号后读取CNTVCT
,如以下代码序列所示:
4、事件流
包含通用计时器的实现可以使用系统计数器生成一个或多个事件流,以生成定期唤醒事件,作为Wait For Event and Send Event on page B1-1200
中描述的机制的一部分。
注:可以使用事件流:
对等待事件轮询循环施加超时。防止任何导致不会生成预期事件的编程错误。
事件流通过以下方式配置:
从计数器的底部16
位中选择哪个位将生成事件。这决定了流中事件的频率。选择是在所选计数器位的每个0
到1
转换或每个1
到0
转换时生成事件。
CNTKCTL.{EVNTEN, EVNTDIR, EVNTI}
字段定义从虚拟计数器生成的事件流。
在包含虚拟化扩展的实现中,CNTHCTL.{EVNTEN, EVNTDIR, EVNTI}
字段定义从物理计数器生成的事件流。
事件流的操作如下:
伪代码变量PreviousCNTVCT
和PreviousCNTPCT
声明为:
// Variables used for generation of the timer event stream. bits(64) PreviousCNTVCT; bits(64) PreviousCNTPCT;
伪代码函数TestEventCNTV()
和TestEventCNTP()
在处理器时钟的每个周期上调用。TestEventCNTx()
伪代码模板定义了函数TestEventCNTV()
和TestEventCNTP()
:
5、定时器
通用计时器的实现提供的计时器数取决于实现是否包括安全扩展和虚拟化扩展,如下所示:
未实现安全扩展插件
该实现提供了物理计时器和虚拟计时器。
已实现安全扩展,未实施虚拟化扩展
该实现提供:
不安全的物理计时器。安全的物理计时器。虚拟计时器。
实现的虚拟化扩展
该实现提供:
不安全的PL1
物理计时器。安全PL1
物理计时器。不安全的PL2
物理计时器。虚拟计时器。
每个已实现计时器的输出:
向系统提供输出信号。如果处理器连接到通用中断控制器 (GIC
),则向该 GIC 发出专用外设中断 (PPI
) 信号。在多处理器实现中,每个处理器必须为每个计时器使用相同的中断号。
每个计时器实现为三个寄存器:
64
位CompareValue
寄存器,提供64
位无符号upcounter
。一个32
位的TimerValue
寄存器,它提供了一个32
位的签名下行计数器。32
位控制寄存器。
在包含安全扩展的处理器实现中,PL1
物理计时器的寄存器被存放,以提供计时器的安全和非安全实现。表B8-1
显示了定时器寄存器。
Table B8-2 on page B8-1969
包括对这些寄存器的描述的引用。
以下各节介绍计时器的操作:
访问计时器寄存器定时器的CompareValue
视图的操作定时器的TimerValue
视图的操作操作时输出定时器信号
访问计时器寄存器
对于每个计时器,所有计时器寄存器都具有相同的访问权限,如下所示:
PL1 physical timer
从PL1
模式访问,除非实现包括虚拟化扩展,否则执行在PL2
上的非安全软件控制从非安全PL1
模式访问。
当允许从PL1
模式访问时,CNTKCTL.PL0PTEN
确定寄存器是否可以从PL0
模式访问。如果因为CNTKCTL.PL0PTEN
被设置为0
而不允许访问,尝试从PL0
模式访问会产生一个Undefined Instruction
异常。
如果实现包括安全扩展插件:
除了从Monitor
模式访问外,访问都是针对当前安全状态的寄存器。对于Monitor
模式的访问,SCR.NS
的值决定访问的是安全寄存器还是非安全寄存器。
如果实现包括虚拟化扩展:
非安全寄存器可从Hyp
模式访问。
CNTHCTL.PL1PCEN
确定非安全寄存器是否可以从非安全PL1
模式访问。如果此位设置为1
,则启用从非安全PL1
模式的访问,CNTKCTL.PL0PTEN
将确定寄存器是否可以从非安全PL0
模式访问。
如果因为CNTHCTL.PL1PCEN
设置为0
而不允许访问,则从非安全PL1或PL0模式访问时,会产生Hyp Trap
异常。但是,如果CNTKCTL.PL0PTEN
设置为0
,这个控件优先,并且试图从PL0
访问会产生一个Undefined Instruction
异常。
Virtual timer
可从安全和非安全PL1
模式以及Hyp
模式访问。
CNTKCTL.PL0VTEN
确定寄存器是否可以从PL0
模式访问。如果因为CNTKCTL.PL0VTEN
被设置为0
而不允许访问,尝试从PL0
模式访问会产生一个Undefined Instruction
异常。
PL2 physical timer
当SCR.NS
设置为1
时,可从非安全催眠模式以及从安全监视器模式访问。
定时器的CompareValue
视图的操作
计时器的CompareValue
视图作为64
位upcounter
运行。当相应的计数器达到编程到CompareValue
寄存器中的值时,满足定时器条件。当计时器条件满足时,只有当计时器启用,且该信号在相应的计时器控制寄存器CNTP_CTL
、CNTHP_CTL
或CNTV_CTL
中没有被屏蔽时,才会断言定时器输出信号。
注:
定时器输出信号可用作电平敏感中断信号。在CompareValue
视图操作的伪代码描述中,EventTriggered
指示是否满足计时器条件。它不指示是否断言定时器输出信号。
计时器的此视图的操作是:
EventTriggered = (((Counter[63:0] – Offset[63:0])[63:0] - CompareValue[63:0]) >= 0)
EventTriggered
:如果满足此计时器的条件,则为TRUE
,否则为FALSE
。
Counter
:物理计数器值,可以从CNTPCT
寄存器读取。(注:可以从CNTVCT
寄存器中读取的虚拟计数器值就是这个值)。
Offset
:对于物理计时器,以及不包含虚拟化扩展的实现中的虚拟计时器,偏移量为零。对于包含虚拟化扩展的实现中的虚拟计时器,Offset
是保存在CNTVOFF
寄存器中的虚拟偏移量。
CompareValue
:相应的CompareValue
寄存器、CNTP_CVAL
、CNTHP_CVAL
或CNTV_CVAL
的值。
在此计时器视图中,计数器、偏移量和比较值都是64
位无符号值。
这意味着可能永远不会满足CompareValue
等于或接近0xFFFFFFFFFFFFFFFF
的计时器的计时器条件。但是,没有实际要求使用接近计数器包装值的值。
定时器的TimerValue
视图的操作
定时器的TimerValue
视图作为带符号的32
位downcounter
操作。一个TimerValue
寄存器是用一个计数值编程的。这个值随着相应计数器的每一次增量而递减,当该值为零时,计时器条件就满足了。当计时器条件满足时,只有当计时器启用,且该信号在相应的计时器控制寄存器CNTP_CTL
、CNTHP_CTL
或CNTV_CTL
中没有被屏蔽时,才会断言定时器输出信号。
注:
定时器输出信号可用作电平敏感中断信号。在CompareValue
视图操作的伪代码说明中,EventTriggered
指示是否满足计时器条件。它不指示定时器输出信号是否被置位。
定时器的这个视图依赖于以下访问TimerValue
寄存器的行为:
Reads
:TimerValue = (CompareValue – (Counter - Offset))[31:0]
Writes
:CompareValue = ((Counter - Offset)[63:0] + SignExtend(TimerValue))[63:0]
其中参数具有Operation of the CompareValue views of the timers on page B8-1966
中使用的定义,此外:
TimerValue
:TimerValue
寄存器的值,CNTP_TVAL
、CNTHP_TVAL
或CNTV_TVAL
。
这个定时器视图的操作是有效的:EventTriggered = (TimerValue ≤ 0)
在计时器的这个视图中,所有值都是有符号的,采用标准的2
的补码形式。
在满足计时器条件之后,读取TimerValue
寄存器将指示自满足该条件以来的时间。
注:将TimerValue
编程为一个大小大于(Counter-Offset
)的负数可能会导致算术溢出,从而导致CompareValue
成为一个非常大的正值。这可能意味着在极长的一段时间内不满足计时器条件。
定时器输出信号的操作
只要满足以下所有条件,定时器输出信号就会置位:
至少满足其中一个计时器条件,详细信息看Operation of the CompareValue views of the timers on page B8-1966
和Operation of the TimerValue views of the timers on page B8-1967
。在定时器控制寄存器CNTP_CTL
、CNTHP_CTL
或CNTV_CTL
中: 启用定时器。定时器输出信号没有被屏蔽。
这意味着,要取消定时器输出信号的断言,软件必须执行以下操作之一:
对计时器寄存器重新编程,以便不满足任何计时器条件。屏蔽定时器输出信号,在定时器控制寄存器中。在计时器控制寄存器中禁用计时器。
2、通用定时器寄存器摘要
表B8-2
显示了包含通用计时器扩展的实现中的CP15
寄存器。实现的寄存器集取决于实现是否也包括虚拟化扩展。
1、CNTVOFF 状态寄存器
通用计时器扩展的所有实现都包括虚拟计数器。因此,从概念上讲,所有实现都包括CNTVOFF
寄存器,该寄存器定义物理计数和虚拟计数之间的虚拟偏移。在不支持虚拟化的实现中,这个偏移量为零。CNTVOFF
被定义为PL2
模式寄存器,详细信息见Banked PL2-mode CP15 read/write registers on page B3-1454
。这意味着:
在包含虚拟化扩展的实现中,CNTVOFF
是一个RW
寄存器,当SCR.NS
设置为1
时,可以从非安全Hyp
模式和从安全监视器模式访问。CNTVOFF
编码的MCRR
或MRRC
未定义: 当SCR.NS
设置为0
时,以Monitor
模式执行。如果不是在Monitor
模式或Hyp
模式下执行。 在包含安全扩展但不包括虚拟化扩展的实现中,CNTVOFF
编码的MCRR
或MRRC
是: 如果在监视模式下执行,则不可预知,而不考虑SCR.NS
的值。如果在非Monitor
模式下执行,则未定义。 在不包括安全扩展插件(包括任何PMSA
实现)的实现中,尽管寄存器在概念上存在,但无法访问它。寄存器的MCRR
和MRRC
指令编码未定义。
在所有CNTVOFF
寄存器没有定义为RW寄存器的情况下,虚拟计数器使用固定的虚拟偏移值0
。
二、Chapter 9:Generic Timer 翻译
本章介绍Cortex-A7 MPCore
处理器的通用计时器。它包含以下部分:
关于通用计时器通用计时器功能说明定时器编程模型
1、关于通用定时器
通用定时器可以根据递增的计数器值调度事件和触发中断。它提供了:
生成定时器事件作为中断输出。生成事件流。支持虚拟化扩展。
Cortex-A7 MPCore
定时器符合ARM
架构参考手册。
本章仅介绍特定于Cortex-A7 MPCore
实现的功能。
2、通用计时器功能说明
Cortex-A7 MPCore
处理器为集群中的每个处理器提供了一组四个计时器。
物理计时器,用于安全和非安全PL1
模式。物理计时器的寄存器被存入以提供安全和非安全副本。虚拟计时器,用于非安全PL1
模式。物理定时器使用在Hyp
模式。
计数器值通过同步二进制编码的64
位总线分发到处理器,CNTVALUEB[63:0]
。
A-6
中表A-4
显示了外部中断输出引脚的信号。
3、定时器编程模型
在每个处理器中,一组定时器寄存器被分配到CP15
协处理器空间。定时器寄存器的宽度为32
位或64
位宽。
表9-1
显示了系统定时器寄存器。
三、通用定时器总结
参考博客:Linux时间子系统之(十七):ARM generic timer驱动代码分析 ()
1、通用定时器框架
上图为ARMv7-A
和ARMv7-R
架构使用通用定时器作为系统定时器的一个示例。
generic timer
相关硬件包括System counter
、Counter interface
、Timer_x
、System events
组成。
System counter
:用来记录时间的流逝,多个处理器共享。主要功能是统计输入时钟已经过了多少个clock
。
Counter interface
:System counter
和Timer_x
信息交互接口。
Timer_x
:用来触发timer
事件。
System counter
的counter value
需要分发到各个timer
中,也就是说,从各个timer
的角度看,system counter value
应该是一致的。Timer
其实就是定时器,它可以定义一段指定的时间,当时间到了,就会触发一个外部的输出信号(可以输出到GIC
,作为一个interrupt
源)。
2、System Counter 要求
1、System counter
的计数器有多少bit
?
至少56
个bit
,和具体的实现相关。
2、输出频率范围?
典型值是1M~50MHz
。
3、操作模式?
正常的时候,每个clock
都会加一,但是,在power saving mode
的时候,我们希望功耗可以更低一些,这时候会考虑将system clock
的输入频率降低下来,例如降低4
倍。为了保证system counter
的计时是准确的,可以设定每个clock
增加4
,而不是加1
,这样system counter
的计时仍然保持准确。
4、溢出时间?
至少40
年。
5、精度要求?
未规定,推荐是每24
小时在正负10
秒的误差。
6、reset
值?
0
7、是否支持debug
?
可以设定enable halt-on-debug
。这个和JTAG
调试相关。如果你使用JTAG
调试,在单步运行的时候当然系统counter
停下来,否则timer
的中断就会来了,导致你无法正常的进行程序代码跟踪。
3、定时器使用
各个cpu
的timer
是根据system counter
的值来触发timer event
的,因此,系统中一定有一个机制让System counter
的值广播到各个CPU
的timer
上,同时运行在各个processor
上的软件可以通过接口获取System counter
的值。
处理器可以通过CNTPCT
寄存器来获取system counter
的当前值,我们称之physical counter
(物理计数器) 。有physical
就有virtual
,processor
可以通过CNTVCT
寄存器访问virtual counter
(虚拟计数器),不过,对于不支持security extension
(安全扩展) 和virtualization extension
(虚拟扩展) 的系统,virtual counter
和physical counter
是一样的值。
系统中每个processor
都会附着多个timer
,具体如下:
1、对于不支持security extension
的SOC
(不支持security extension
也就意味着 不支持virtualization extension
),timer
实际上有两个,一个是physical timer
,另外一个是virtual timer
。虽然有两个,不过从行为上看,virtual timer
和physical timer
行为一致。
2、对于支持security extension
但不支持virtualization extension
的SOC
,每个cpu
有三个timer
:Non-secure physical timer
,Secure physical timer
和virtual timer
。
3、对于支持virtualization extension
的SOC
,每个cpu
有四个timer
:Non-secure PL1 physical timer
,Secure PL1 physical timer
,Non-secure PL2 physical timer
和virtual timer
。
每个timer
都会有三个寄存器(我们用physical timer
为例描述):
1、64-bit CompareValue register
该寄存器配合system counter
可以实现一个64 bit unsigned upcounter
。如果physical counter - CompareValue >= 0
的话,触发中断。也就是说,CompareValue register
其实就是一个64
比特的upcounter
,设定为一个比当前system counter
要大的值,随着system counter
的不断累加,当system counter value
触及CompareValue register
设定的值的时候,便会向GIC
触发中断。
2、32-bit TimerValue register
该寄存器配合system counter
可以实现一个32 bit signed downcounter
(有的时候,使用downcounter
会让软件逻辑更容易,看ARM generic timer
的设计人员考虑的多么周到)。开始的时候,我们可以设定TimerValue
寄存器的值为1000
(假设我们想down count 1000
,然后触发中断),向该寄存器写入1000
实际上也就是设定了CompareValue register
的值是system counter
值加上1000
。随着system counter
的值不断累加,TimerValue register
的值在递减,当值<=0
的时候,便会向GIC
触发中断。
3、32-bit
控制寄存器
该寄存器主要对timer
进行控制,具体包括:enable
或是disable
该timer
,mask
或者unmask
该timer
的output signal(timer interrupt)
。
四、软件编程接口
ARM generic timer
的硬件包括两个部分:一个是每个cpu
的timer
硬件,另外一个就是system level
的counter
硬件。对于每个cpu
的timer
硬件,使用system control register(CP15)
来访问是最合适的,而且速度也快。要访问system level
的counter
硬件,当然使用memory mapped IO
的形式(请注意架构图中的APB
总线,很多system level
的外设都是通过APB
访问的)。
五、Linux 内核 generic timer 相关源码分析
未完成