QEMU 中 CPU 的定时器供应

Timer supply to CPU in QEMU

我正在尝试用 CPU cortex m4 模拟 STM32 机器的时钟控制。它在 STM32 reference manual 中提供,提供给内核的时钟由 HCLK 提供。

The RCC feeds the external clock of the Cortex System Timer (SysTick) with the AHB clock (HCLK) divided by 8. The SysTick can work either with this clock or with the Cortex clock (HCLK), configurable in the SysTick control and status register.

现在 Cortex m4 已经被 QEMU 模拟,我正在使用相同的 STM32 模拟。我的困惑是我是否应该提供我为 STM32 开发的 "HCLK" 的时钟频率以将时钟脉冲发送到 cortex m4 或 cortex -m4 本身设法拥有自己的 HCLK 时钟频率为 168MHz 的时钟?或者时钟频率不同?

如果我必须将这个频率传递给皮质 m4,我该怎么做?

Systick 通过多路复用器提供,您可以选择 AHB 总线时钟或除以 8 系统定时器时钟

QEMU 的模拟通常不会尝试模拟以兆赫兹速率发送脉冲的实际时钟线(这将非常低效)。相反,当来宾对计时器设备进行编程时,计时器设备的模型会设置一个内部 QEMU 计时器以在适当的持续时间后触发(然后处理程序会引发中断线或执行模拟硬件行为所需的任何操作)。持续时间是根据来宾写入设备寄存器的值以及时钟频率的值计算得出的。

QEMU 没有任何基础设施来处理诸如可编程时钟分频器或在 SoC 周围路由时钟信号的“时钟树”(可以添加一个,但还没有人知道)。相反,定时器设备通常用 hard-coded 频率编写,或者可以编写为具有 QOM 属性,允许由板或创建它们的 SoC 模型代码设置频率。

特别是对于 Cortex-M 模型中的 SysTick 设备,当前的实现将对它使用的 QEMU 计时器进行编程,其持续时间对应于以下频率:

  • 1MHz,如果客户已将 CLKSOURCE 位设置为 1(处理器时钟)
  • 如果来宾已将 CLKSOURCE 设置为 0(外部参考时钟),则板型号通过 'system_clock_scale' 全局变量配置的东西(例如 25MHz 用于 mps2 板)

(system_clock_scale 全局应设置为 NANOSECONDS_PER_SECOND / clk_frq_in_hz。)

1MHz 只是一个愚蠢的硬编码值,还没有人费心去改进它,因为我们还没有 运行 到关心的访客代码中。 system_clock_scale 全局变量很笨重但有效。

None 这会影响模拟 QEMU 的速度 CPU(即它在给定时间段内执行的指令数)。默认情况下,QEMU CPUs 将 运行 “尽可能快”。您可以使用 -icount 选项指定您希望 CPU 到 运行 以相对于实时的特定速率,这会隐式设置 'cpu frequency',但这只会排序粗略地设置一个平均值 - 一些指令将 运行 比其他指令快得多,以一种不太可预测的方式。一般来说,QEMU 的理念是“运行 来宾代码尽可能快”,并且我们不会尝试任何接近 cycle-accurate 或其他时间紧迫的仿真。

截至 2020 年的更新:QEMU 现在有一些 API 和用于建模时钟树的基础设施,这在 docs/devel/clocks.rst 源代码树中有记录。这基本上是上述概念的形式化版本,使一个设备更容易告诉另一个设备“我的时钟频率现在是 20MHz”,而无需像“system_clock_scale”全局变量或 ad-hoc QOM 这样的黑客攻击属性。

一个旧线程和一个经常被问到的问题,所以这应该能帮助你们中的一些人尝试模拟皮质系统。

如果在引导时使用 .dtb,则可以在您的 .dts 中向 'timers' 块添加一行 clock-frequency = <value>; 并重新编译它。这确实会提高皮质处理器的速度。显然,value 是一个很大的数字。