有人可以解释exynos ARM中的电源控制寄存器吗?

在Linux内核中,更准确地说是3.9- rc6上的/arch/arm/mach-exynos/cpuidle.c ,这些行读取

static unsigned int g_pwr_ctrl, g_diag_reg; static void save_cpu_arch_register(void) { /*read power control register*/ asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc"); /*read diagnostic register*/ asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc"); return; } 

在研究了这个问题后,这似乎是gcc内联汇编。 考虑到它是一个关键组件, asm正在阅读它

  1. 更快,因此更有效率
  2. 不适用于C.

我检查了ARM手册中的MCR因为我正在学习汇编,但我可以告诉MCR是一个协处理器,因为它有三个字母长度。 内联asm似乎访问功率控制寄存器并将结果(从寄存器)保存到第一行中的无符号整数(我希望在某个时刻调用)。

关于电源控制寄存器,臂手册列出,

  • 实现Cortex-A9处理器的时钟延迟
  • 动态时钟门控。

我无法理解为什么需要它,这可以在一个函数中动态访问。

最后,ARM手册列出了32位宽寄存器的设计。 基本时钟似乎是在那里设置的,我们是否在从空闲上下文进程启动时读取它?

我也发现了类似的问题 – 这也可能对你有帮助。

您的问题确实缺乏重点,请考虑更新它。 我将假设您正在尝试了解Linux内核中的exynos挂起/恢复机制。

为什么内联汇编程序

…这似乎是gcc内联汇编。 考虑到它是一个关键组件,asm正在阅读它
a)更快,因此更有效率;
b)C中没有

我们选择选项b ,没有办法在C中表达mcr / mrc

内联clobber列表

其次,…… : : "cc");

这是一个gcc clobber列表。 它表示条件代码将被指令改变。 这可能只是为了确保gcc决定不丢弃该指令。 您可以在gcc手册中阅读更多内容。

这是做什么的

我无法理解为什么需要它,这可以在一个函数中动态访问。

您需要查看的部分是exynos4_enter_core0_aftr() 。 这使用save_cpu_arch_register()restore_cpu_arch_register() 。 因此,有一组双重函数,我们注意到这些值存储在全局变量中 。 另外需要注意的是cpu_suspend(0, idle_finisher); 。 这个函数告诉Linux cpu被挂起然后调用cpu_do_idle(); 这通常是ARM WFI ( 等待中断 )指令。 这使CPU在该指令处冻结 ,直到启用中断触发。 暂停CPU时钟全速运行的问题是这会浪费一些电流/功率。 通常,SDRAM和平台时钟可以在此模式下自动进入低功耗状态。

您需要查阅CPU / SOC上的数据表以获取更多信息。 但是,回到这个问题。 这种低功耗模式很可能会破坏/更改这些协处理器寄存器,因此需要save_cpu_arch_register()restore_cpu_arch_register()来确保它们保持与调用之前一样。 该代码可能使用exynos4_enter_core0_aftr()本地代码。 它们确实需要保存和恢复,否则CPU可能会以奇怪的电源/电压/时钟恢复。 也可能是cpu_do_idle()被你的机器覆盖了,它正在改变这些寄存器。

简而言之,此函数用于保存当CPU进入挂起等待中断模式时将被销毁的某些状态。