电子说
generic timer介绍
armv7-A架构中每个CPU核心都包含自己的私有定时器,所有cpu的定时器共享一个System counter, System counter负责产生计数,传递到每个核心的私有定时器,架构如下图所示:
该定时器可以产生中断,作为系统心跳使用,类似于cortex-M的systick,详细的中断号在DDI0471B_gic400_r0p1_trm.pdf中有说明,下面PPI中断号的截图说明:
gtimer寄存器介绍
armv7-A架构中generic timer寄存器如下图所示:
在ARMv7-A中定义了不同的特权级别,分别是PL0, PL1, PL2,PL0是普通用户模式,在PL1、PL2模式下分别有对应的定时器。
下面介绍PL1模式下的定时器,也就是svc、FIQ模式下的定时器,rt-thread的宏内核版本运行在svc模式下,所以我们着重研究PL1物理定时器的使用。
关键寄存器说明
CNTFRQ寄存器是定时器频率值,这个需要根据实际的硬件情况设置,在全志平台上是24M,这个必须设置, 操作寄存器的内联汇编代码:
asm volatile("MCR p15, 0 , %0, c14, c0, 0" : : "r" (Rt) : "memory" )
CNTPCT是物理计数器寄存器,这个寄存器是64位的,寄存器值会一直累加,根据CNTFRQ寄存器中的频率进行累加,所以这个值可以作为时间tick来使用,在一些需要简短的延时场景可以借助这个计数器。获取计数器值的代码:
uint64_t get_arch_counter(void)
{
uint32_t low=0, high = 0;
asm volatile("mrrc p15, 0, %0, %1, c14"
: "=r" (low), "=r" (high) |
---|
: "memory"); |
return (((uint64_t)high)<<32 |
} |
CNTP_TVAL寄存器, 这个寄存器一般在开启gtimer的中断时使用。
写入CNTP_TVAL寄存器时,硬件会自动把该值加上System Counter的值,一并写入CNTP_CVAL寄存器中,作为下一次中断的时基。内联汇编伪代码如下:
asm volatile("MCR p15, 0 , %0, c14, c2, 0" : : "r" (Rt) : "memory" )
特别说明
CNTP_CVAL = CNTP_TVAL + System Counter。
CNTP_CVAL寄存器,该寄存器是比较寄存器,当System Counter的值大于等于CNTP_CVAL的值时产生中断,如果需要改写此寄存器的值可以,通过写入CNTP_TVAL来实现,避免读改写寄存器的繁琐操作。
CNTP_CTL是PL1物理定时器的控制寄存器, 操作的内联汇编代码如下:
asm volatile("MCR p15, 0 , %0, c14, c2,
CNTP_CTL寄存器控制位说明:
其中bit0负责使能定时器,bit1是否打开中断信号。
PL1物理定时器的中断号,在全志平台是29,其他CPU平台待验证。
详细gtimer操作代码可以参考rt-thread源码目录中libcpu->cortex-a中的gtimer.c文件。
全部0条评论
快来发表一下你的评论吧 !