如何在Cortex-R5上获取或模拟64位循环计数器?
解决Cortex-R5 PMU 32位循环计数器溢出,实现64位计数的方法
方法一:软件叠加溢出计数(最可靠)
Cortex-R5的PMU支持溢出中断,我们可以利用这个特性维护一个软件层面的溢出计数器,将其与32位硬件计数器组合成64位值:
- 配置PMU:开启PMCR寄存器的
E位(使能PMU),并针对循环计数器(通常是CNT0)设置对应溢出中断使能寄存器(如CNTENS的对应位)。 - 实现溢出中断服务函数:每次触发溢出中断时,将全局32位溢出计数器(例如
uint32_t overflow_cnt)加1。 - 读取64位计数:需要获取当前计数时,进入临界区(或做原子操作),读取硬件32位计数器值(
uint32_t hw_cnt),再结合溢出计数器计算:uint64_t total_cnt = ((uint64_t)overflow_cnt << 32) | hw_cnt;
注意:读取时必须保证原子性,避免在读取hw_cnt和overflow_cnt的间隙发生溢出,导致计数错误。也可利用PMU的锁存寄存器(若支持)先锁存当前计数器值再读取。
方法二:结合系统定时器辅助校准
如果你的SoC带有64位系统定时器(如通用定时器、RTC等),可通过同步校准估算溢出次数:
- 初始化阶段:同时读取PMU计数器值
pmu_init和定时器值timer_init并记录。 - 读取阶段:读取当前定时器值
timer_now,计算差值timer_diff = timer_now - timer_init;根据CPU主频估算这段时间内PMU的溢出次数:overflow_est = (timer_diff * CPU_FREQ) >> 32(假设定时器单位为秒,CPU_FREQ为主频Hz);再读取当前PMU计数器值pmu_now,最终64位计数为:((uint64_t)overflow_est << 32) | pmu_now
这种方法无需依赖PMU中断,但精度受定时器和CPU主频误差影响,适合对精度要求不极高的场景。
方法三:多核PMU交叉验证(仅适用于多核Cortex-R5系统)
如果是双核心Cortex-R5配置,可让一个核心的PMU计数器作为另一个核心的溢出参考:
- 两个核心同时启动PMU计数,定期同步各自的计数器值。
- 当其中一个核心的计数器溢出时,通过核间通信通知另一个核心更新溢出计数。
不过这种方法实现复杂,仅在特殊多核场景下考虑。
内容的提问来源于stack exchange,提问作者David Monniaux
相关产品推荐
相关产品推荐

