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();
    }

残念ながら、ホットスピニングが使用されているかどうかに関係なく、消費電力はまったく変化しません (消費電力の測定値がチップに関連付けられています)。さらに、Wait-For-Interrupt CP15 命令を使用すると、起動しません。ボタンは、GPIO の 1 つに接続されています。プラットフォームは 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わかりませんが、何の効果もありません。したがって、ランダムな値でコプロセッサ呼び出しを行っています。また、呼び出す前に r3 (mcr の ARM ソース レジスタ) を設定する必要がありmcrます。ところで、「メモリ」をクロバーリストに入れると、それはつまり

... 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 の Web サイトにあるこの記事をお勧めします。

ボーナス セクション:
このコプロセッサが提供する WFI の後方互換性に関するあなたの主張に対する小さな答え:

ARMv7 プロセッサ (Cortex-A8、Cortex-A9、Cortex-R4、および Cortex-M3 を含む) はすべて、「割り込み待ち」モードに入る WFI 命令を実装しています。これらのプロセッサでは、以前のプロセッサで使用されたコプロセッサ書き込みは常に NOP として実行されます。したがって、MCR 命令と WFI 命令の両方を実行することで、ARMv6K、ARMv6T2、および ARMv7 のすべてのプロファイルで機能するコードを作成できますが、ARM11MPCore では、これにより「割り込み待機」モードが 2 回入力されます。「割り込み待機」モードに入る完全に移植可能なコードを記述するには、実行時に CPUID レジスタを読み取って、「割り込み待機」が使用可能かどうか、およびそのモードに入るために必要な命令を判別する必要があります。

于 2012-10-17T19:46:00.427 に答える