0

我尝试在按下按钮时在 uboot 中实现低功耗“深度睡眠”功能。按钮按下由 linux 处理,并设置了一个魔术代码以使 u-boot 意识到保持睡眠不要重新启动"

    printf ("\nDisable interrupts to restore them later\n");
    rupts = disable_interrupts();
    printf ("\nEnable interrupts to enable magic wakeup later\n");
    enable_interrupts();
    printf ("\nSuspending. Press button to restart\n");

    while(probe_button()/*gpio probe*/){
#if 1
            //FIXME recheck if that one actually needs an unmasked interrupt or any is ok
            __asm__ __volatile__(
                            "mcr p15, 0, %0, c7, c0, 4\n" /* read cp15 */
                            "mov %0, %0"
                            : "=r" (tmp)
                            :
                            : "memory"
            );
#else
            udelay (10000);
#endif
    }
    if (rupts) {
            printf ("\nRe-Enabling interrupts\n");
            enable_interrupts();
    }

不幸的是,无论是否使用热旋转,功耗都不会改变(将功耗测量与芯片相关联)。除此之外,如果我使用等待中断 CP15 指令,它永远不会唤醒。该按钮连接到其中一个 GPIO。该平台基于 Marvell Kirkwood ARM9EJ-S。

我手动启用了一些,并为以及CONFIG_IRQ_*创建实现,我认为这是我的问题。arch_init_irq()do_irq()

根据CP15指令文档,触发中断就足够了(无论是否被屏蔽!)。

谁能告诉我我做错了什么或者除了上面的代码还需要做什么?

提前非常感谢!

4

1 回答 1

1

我不确定这是否是您的方法无法实现节能但您的内联汇编不正确的唯一原因。根据这篇文章,您需要执行:

MOV R0, #0
MCR p15, 0, r0, c7, c0, 4

但是你的内联汇编

        __asm__ __volatile__(
                        "mcr p15, 0, %0, c7, c0, 4\n" /* read cp15 */
                        "mov %0, %0"
                        : "=r" (tmp)
                        :
                        : "memory"
        );

生产

   0:   ee073f90    mcr 15, 0, r3, cr7, cr0, {4}
   4:   e1a03003    mov r3, r3
   8:   e12fff1e    bx  lr

我不确定您的意图是什么,但mov r3, r3没有任何效果。因此,您正在使用随机值进行协处理器调用。您还需要在mcr调用之前设置 r3(mcr 的 ARM 源寄存器)。顺便说一句,当您将“内存”放入 clobber 列表时,这意味着

... 将导致 GCC 不会在汇编指令中将内存值缓存在寄存器中,并且不会优化对该内存的存储或加载。

试试这条线

asm("MOV R0, #0\n MCR p15, 0, r0, c7, c0, 4" : : : "r0");

它产生

   c:   e3a00000    mov r0, #0  ; 0x0
  10:   ee070f90    mcr 15, 0, r0, cr7, cr0, {4}

一般来说,为了省电,我会推荐ARM 网站上的这篇文章。

奖励部分:
对您关于此协处理器提供的 WFI 的向后兼容性的声明的一个小回答:

ARMv7处理器(包括Cortex-A8、Cortex-A9、Cortex-R4和Cortex-M3)都执行WFI指令进入“等待中断”模式。在这些处理器上,在早期处理器上使用的协处理器写入将始终作为 NOP 执行。因此,可以通过执行 MCR 和 WFI 指令来编写跨 ARMv6K、ARMv6T2 和所有 ARMv7 配置文件的代码,尽管在 ARM11MPCore 上这将导致进入两次“等待中断”模式。要编写进入“等待中断”模式的完全可移植代码,必须在运行时读取 CPUID 寄存器以确定“等待中断”是否可用以及进入它所需的指令。

于 2012-10-17T19:46:00.427 回答