2408758_zh-CN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

2408758_zh-CN

2408758_zh-CN

修改im8QM的A72核的CNTFRQ_el0的值

您好!

如何修改im8QM的A72核的CNTFRQ_el0的值,目前是8000000, 想改为16M,

谢谢!


Re: 修改im8QM的A72核的CNTFRQ_el0的值

i.MX8QM 上不建议、也基本不能把 A72 的 CNTFRQ_EL0 对应的真实计数频率从 8 MHz 改成 16 MHz 。原因是: CNTFRQ_EL0 只是让软件“发现”System Counter 频率的寄存器;即使软件能写这个寄存器值,也不会改变硬件 System Counter 的实际频率。

对 i.MX8QM,参考手册里说明 SCU ROM 会启用 System Counter,并给它输入 24 MHz 时钟;System Counter 内部再分频生成 8 MHz 时钟。 相关 clock root 也属于 System Controller Firmware 管理的时钟域,文档显示 SCU_MSLICE0_CLK_ROOT / SCU_MSLICE1_CLK_ROOT 可作为 SYS COUNTER 的 root clock,且 root clock generation 由 SC FW 控制。

所以如果你现在读到:

CNTFRQ_EL0 = 8000000

想改成:

CNTFRQ_EL0 = 16000000

需要区分两件事:

  • 只改 CNTFRQ_EL0 的寄存器值
    这可能让部分软件“以为”timer 是 16 MHz ,但硬件 counter 仍按 8 MHz 跑,会导致时间、调度、延时、profiling 等全部按 2 倍比例出错。
  • 真正把 System Counter 改成 16 MHz
    从我检索到的 i.MX8QM 资料看,System Counter 是 SCU ROM 初始化为 24 MHz / 3 = 8 MHz ,没有公开的寄存器或流程可以把它改成 16 MHz 。 类似 i.MX8 系列讨论中也明确说过,system counter frequency 是硬件固定的, it can't be changed 。

如果你的目标是让 Linux/RTOS 使用正确频率,建议保持 CNTFRQ_EL0 = 8000000 ,并检查 device tree / firmware / bootloader 是否错误覆盖 timer frequency。不要仅为了满足 16 MHz 需求而伪改 CNTFRQ_EL0 ,除非你明确要做一个非真实频率的实验。

结论:i.MX8QM 的 A72 CNTFRQ_EL0 不应从 8 MHz 改为 16 MHz ;真实 System Counter 由 SCU/SCFW 初始化并实际为 8 MHz ,单独改寄存器值不会改变硬件频率,反而会破坏系统时间基准。


Re: 修改im8QM的A72核的CNTFRQ_el0的值

你好:

谢谢回复!

能否提供SCU或SCFW里如何使System Counter变为16MHz的方法或Demo代码,

谢谢!

Re: 修改im8QM的A72核的CNTFRQ_el0的值

在 SCFW 中,您可以自定义特定于开发板的固件,通常位于 SCFW 移植套件的 board.c 文件中。但是,检索到的SCFW指南描述的是板级/时钟/资源定制的一般方法,而不是系统计数器频率更改钩子。在其他 NXP 平台讨论中,同一类系统计数器频率被描述为硬件固定,写入频率 ID / CNTFRQ_EL0 样式的值不会改变实际的计数器时钟。

因此,我不会提供向 SCFW 写入 16 MHz 的演示代码,因为除非实际的系统计数器硬件时钟/分频器也发生改变,否则这只会产生一个软件可见的虚假频率。

一个安全的诊断/演示方法是验证实际计数器速率:

复制

/*

* 在 A72 上从特权固件或早期裸机代码运行。

* 这只读取架构计数器和 CNTFRQ_EL0。

* 它不会尝试更改系统计数器。

*/


#include


static inline uint64_t read_cntpct_el0(void)

{

uint64_t v;

    __asm__ volatile("mrs %0, cntpct_el0" : "=r"(v));

返回 v;

}


static inline uint32_t read_cntfrq_el0(void)

{

uint64_t v;

    __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(v));

返回 (uint32_t)v;

}


void check_arch_timer_frequency(void)

{

uint32_t reported_hz = read_cntfrq_el0();


    /*

* 将 cntpct delta 与一个独立的、已知良好的延迟源进行比较

例如 SCU 定时器、板载示波器 GPIO 切换定时或其他

* 校准计时器。在 i.MX8QM 上,预计计数约为 8,000,000 次/秒。

*/

uint64_t t0 = read_cntpct_el0();


    /* 替换为板载校准的 1 秒延迟,而不是基于 CNTFRQ_EL0。*/

external_calibrated_delay_1s();


uint64_t t1 = read_cntpct_el0();

uint64_t measured_counts_per_sec = t1 - t0;


board_print(3,

“CNTFRQ_EL0 报告 %u Hz,CNTPCT 测量 %llu 计数/秒\n”

        reported_hz,

        measured_counts_per_sec);

}

如果目标是使 Linux 或其他操作系统使用正确的时基,请保持 CNTFRQ_EL0 与实际计数器频率对齐——即根据 RM 文本,i.MX8QM 上的 8 MHz。如果硬件速率没有实际改变,仅将频率设置为 16 MHz 会导致定时器延迟和计时比例不正确。

要点:对于 i.MX8QM,将系统计数器视为由 SCU ROM 初始化的 8 MHz 硬件时基;不支持通过 SCFW 自定义将其变为 16 MHz。


Tags (1)
No ratings
Version history
Last update:
3 weeks ago
Updated by: