armv7 generic timer使用笔记

电子说

1.3w人已加入

描述

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文件。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分