MSP430開発入門講座(3) LPM(Low-Power Mode)への入り方
電気を大切にね (←でんこちゃん知ってます?)
今回は新たなソースはありません。前回の ソースの最後の部分:
for(;;) _BIS_SR(SCG1 | SCG0 | CPUOFF | OSCOFF); // goes into LPM4
だけを解説します。
何もしない無限ループ、つまりfor(;;);は、
ふつうは電気のムダ遣いになります。
CPUは停止することなく、巡航速度で狭い空間をジャンプしまくるからです。
そこで、CPUを停止させるコードを書きます。それが、上記の_BIS_SRの部分です。
SR
CPU(CPUコアの部分は MSP430X というらしいです。) の Status Register (SR) の中身を見てみましょう。 User’s Guide によれば 次のようになっています。
MSP430X の Status Register
| 15-9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|
| Reserved | V | SCG1 | SCG0 | OSC OFF | CPU OFF | GIE | N | Z | C |
この中でSCG1, SCG0, OSCOFF,
CPUOFFの4ビットがLPMに関する部分です。この 4 つのビットを
前回やった、
WRITE_SR(),
_BIS_SR(),
_BIC_SR()
などで操作してやれば CPU は眠りにつくことができます。
LPM
Low-Power Mode の詳細は User’s Guide の 2.3 Operating Modes に書いてありますが、 MSP430X は電力モードについて Active と LPM0〜4 の 6 つの状態を切り替え られます。LPM4 が一番消費電力が小さくて、Active の 1/3000 程度になるようです。 実測したら本当にだいたいそうなっていました。 レジスタ設定とLPMをまとめると次のようになります。
LPMまとめ
| (SR) SCG1 | (SR) SCG0 | (SR) OSCOFF | (SR) CPUOFF | MODE | CPU | MCLK | SMCLK | ACLK | DCO | DC generator |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | Active | on | on | on | on | on | on |
| 0 | 0 | 0 | 1 | LPM0 | – | – | on | on | on | on |
| 0 | 1 | 0 | 1 | LPM1 | – | – | → | on | SMCLK未使用ならoff | SMCLK未使用ならoff |
| 1 | 0 | 0 | 1 | LPM2 | – | – | – | on | – | on |
| 1 | 1 | 0 | 1 | LPM3 | – | – | – | on | – | – |
| 1 | 1 | 1 | 1 | LPM4 | – | – | – | – | – | – |
イマイチLPM2と3の違いがわからない(DC generatorというのはDCOのソースで、 それ以外に使っていないみたいなので、DCO を disable して DC generator を 駆動する意味がわからない)のですが、こんなふうに設定できます。
CPUを止めちゃって大丈夫なの? と思うかもしれませんが、MSP430 の場合、割り込みが 発生すると常にActiveモードに戻るので問題ありません。 また、LPMではRAMや出力ピンの状態も保持されるので、点いていたLEDが 消えたりもしません。 割り込みを待つだけのときは どんどんCPUを止めましょう。 ただし、ペリフェラル(例えばTimer A)を使って割り込みをかける場合、そのペリフェラルを 止めたら元も子もないので、MCLK, SMCLK, ACLK を上手に使い分けてください。 クロックシステムについての詳細は クロックについてのページ にまとめてあります。
前回の例の場合、割り込み源はタクトスイッチによる外部信号なので、全部止めちゃっても 大丈夫です。したがって、
for(;;) _BIS_SR(SCG1 | SCG0 | CPUOFF | OSCOFF); // goes into LPM4
のようにLPM4に移行しました。無限ループ突入後の動作は次のようになります。
- LPM4へ移行(CPU停止, スイッチ待ち)
- スイッチが押されて割り込み発生
- SRの状態がスタックに退避され、割り込み処理関数にジャンプ
- Active モードへ移行
- 割り込み処理終了後、PC は元に戻るがSRも元に戻る(つまりLPM状態も 元に戻る)のでふたたびスリープ
というわけで、実は無限ループにする必要はないようなのですが、何というか しまりがない感じがするので念のため無限ループで終わっています。 (実はこの辺の挙動勘違いしていました。Active に以降するのは ISR に飛んだ 後みたいです。)
ところで(割り込み後は LPM 解除したいなど)、こんなふうに SR を元に 戻したくない場合は ISR 内で _BIC_SR_IRQ(CPUOFF) などとしてやると、 スタック内にある一時退避された SR を変更可能です。