はじめに
STMicroelectronicsは、低リーク技術および最適化された設計により、優れた低消費電流を実現し、バッテリ駆動およびエネルギーハーベスティング(環境発電)のアプリケーションに最適な超低消費電力MCUファミリを提供しています。これらのデバイスの低消費電力性能を最大限に活用するためには、どのような低消費電力モードがあり、どのように設定することができ、どのようなタスクに最適なのかを知ることが必要です。低消費電力モードはシリーズ全体で共通であるため、どのSTM32L0デバイスをとりあげてもよかったのですが、この記事では、STM32L053C8 MCUの低消費電力モードの概要を説明します。また、超低消費電力ファミリのSTM32L1シリーズとSTM32L4シリーズも含みます。これらのデバイスは、より高度なコア、追加メモリ、およびより多くのペリフェラルを備えた高性能な製品で、L0シリーズと同じ低消費電力モード(L4の場合は追加機能あり)を備えているので、この記事が参考になると思います。図1は、STのパンフレットから引用したもので、L0、L1およびL4各シリーズの特徴と利点を簡潔にまとめています。
STのMCUで何らかの作業をする場合、すぐに入手すべきドキュメントが2つあります。1つ目はリファレンスマニュアルで、STM32L053C8の場合はSTM32L0x3 reference manualになります。本書は、STM32L0x3製品ラインの詳細情報、すなわちメモリとペリフェラルセットの使用方法について記載しています。ピン配置、電気的特性およびパッケージ情報など、製品ラインの特定のデバイスに関するより詳細な情報については、データシート(ここではSTM32L053xx datasheetを参照する必要があります。低消費電力モードに関しては、リファレンスマニュアルにその開始と終了の方法が明示され、データシートには使用可能なペリフェラル、可能なウェイクアップソースおよび消費電流の見積もりが具体的に明記されています。
背景
STM32L0はCortex-M0+コアで構築されているため、その低消費電力機能はこのコアのパワーマネジメント機能に依存することになります。これらの機能は、システム制御ブロックにあるシステム制御レジスタ(SCR)を使って設定することができます。残念ながら、コアレジスタについては、リファレンスマニュアルにもデータシートにも記載がありません。STは、Cortex-M0+に関する簡潔なドキュメントをお求めのお客様向けに、代わりにSTM32L0 Series Cortex-M0+ Programming Manualを提供しています。Cortex-M0、M0+およびM1コアに関する完全なドキュメントは、ARMv6-M Architecture Reference Manualに記載されています。どちらのドキュメントにもPower Managementのセクションがあり、このトピックに最適な資料です。
図2に示すように、SCRは以下の3つのビットで構成されています。SEVONPEND、SLEEPONEXITおよびSLEEPDEEPの3ビットです。SEVONPEND(Send EVent ON PENDing)ビットは、保留状態に入った割り込みがウェイクアップイベントをトリガすることを可能にします。これらの割り込みがNVICで有効になっていない場合、ウェイクアップイベントは依然として発生しますが、ISRには入りませんのでご注意ください。保留中の割り込み、割り込みの有効化、またはNVIC全般に関する詳細については、前述のCortex-M0+マニュアルのいずれかのNested Vectored Interrupt Controllerのセクションを参照してください。SLEEPONEXITビットは、例外リターン後、プログラムの実行を再開する前にプロセッサを低電力モードにするオプションを提供します。これは、サービス割り込みに対してのみ起動する必要があるアプリケーションに最適です。最後に、SLEEPDEEPビットは、通常のスリープ状態とは異なり、ディープスリープ状態への移行を可能にします。Cortex-M0+コアを利用するチップのメーカーは、これらの状態におけるデバイスの正確な動作を定めています。STの場合、スリープモードと低消費電力スリープモードはスリープ状態を基本に、ストップモードとスタンバイモードはディープスリープ状態を基本にします。
Cortex-M0+で低消費電力モードに入るには、3つの方法があります。1つ目は、WFI(Wait For Interrupt)命令を使用する方法です。その名の通り、この命令の結果、デバイスが低消費電力モードになった場合、割り込み(NVICでイネーブル)によりデバイスをウェイクアップさせることが可能です。低消費電力モードに移行する2つ目の方法は、WFE(Wait For Event)命令を実行することです。これはWFI命令と非常によく似ていますが、より柔軟性があります。 拡張割り込みおよびイベントコントローラ(EXTI)で設定されたイベントだけでなく、NVICで無効になっている割り込み(対応するペリフェラル制御レジスタで有効になっている限り)でもデバイスをウェイクアップさせることができるのです。 低消費電力モードに入る3つ目の方法は既に述べたとおりです。SCRのSLEEPONEXITビットを設定することで、例外リターンにより、WFI命令を実行したかのように低消費電力モードに移行することができます。なお、いずれの場合も、低消費電力モードになるのは、割り込みやイベントが保留されていない場合のみです。WFIとWFEはプログラムの実行を停止させることが保証されていないため、しばしば「ヒント命令」と呼ばれることがあります。
最後のコアレジスタとして、PRIMASKレジスタを紹介します。このレジスタは、設定可能なビットであるPM(Prioritizable Interrupt Mask)を1つだけ含み、「1」に設定すると設定可能な優先度を持つすべての割り込みをディセーブルにします。これはアトミックな操作の実行に使用できるだけでなく、最初にシステムを動作状態に戻す必要がある場合に、ISRの実行を遅らせるために使用することができます。この例については、停止モードの詳細のセクションで説明します。
Cアプリケーションを開発する際に、プログラマがWFIとWFE命令に簡単にアクセスできるように、CMSIS-CORE規格は __WFI()
と __WFE()
関数を提供しています。以下のセクションのすべてのサンプル関数は、__WFI()
を使用して WFI命令を実行し、低消費電力モードに入ります。また、CMSISはPRIMASKレジスタへの直接アクセスを提供するのではなく、PMビットのセットとクリアのために、それぞれ __disable_irq()
と__enable_irq()
関数を実装しています。PMビットの状態を確認するために、__get_PRIMASK()
関数はその現在の状態を返します。ほとんどのIDEは、プロジェクトにCMSISドライバを非常に簡単に追加できます。例えば、Keilでは、ARM::CMSISがPack Installerでインストールされていることを確認し、新しいプロジェクトを作成する際にRun-Time Environment Manager (実行環境マネージャ)で(CMSISコンポーネントの下にある)「CORE」をチェックするだけでよいのです。
低消費電力モード
STM32L0デバイスは、5つの低消費電力モードを実装しています。低消費電力実行モード(Low-power run mode)、スリープモード(Sleep mode)、低消費電力スリープモード(Low-power sleep mode)、ストップモード(Stop mode)およびスタンバイモード(Standby mode)です。これらのモードの違いは、消費電力、パフォーマンス、ウェイクアップ時間、およびウェイクアップソースの観点から説明することができます。これらのパラメータごとに、モードをベスト(1)からワースト(5)まで並べると、トレードオフの関係が明らかになります。一般に、消費電力が下がると、性能は低下し、ウェイクアップ時間は長くなり、ウェイクアップ ソースの数は少なくなります。表1は、低消費電力モードのランキングをまとめたものです。表の見方の一例として、低消費電力実行モードを考えてみましょう。このモードは、性能が最も高く、ウェイクアップ ソースの数が最も多くて、ウェイクアップ時間は2番目に速く、消費電流は4番目に低いモードです。
表1:各種動作パラメータに基づくSTM32L0低消費電力モードの序列ランキング
性能 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
消費電力 | 4 | 5 | 3 | 2 | 1 |
ウェイクアップ時間 | 2 | 1 | 4 | 3 | 5 |
ウェイクアップ ソース | 1 | 2 | 3 | 4 | 5 |
このセクションでは、これらのランキングがどのように導き出されたかを明らかにしていきますが、一般的な意味での真実でしかないことを、早い段階で認識しておくことが重要です。たとえば、ストップモードが低電力スリープモードよりも消費電流が大きいことは、その構成や、どの周辺機器を有効/無効にするかによって、十分にあり得ることです。しかし、一般的にはそうではありません。ストップモードは、より多くの電力を節約するために、低電力スリープモードよりもはるかに多くのデバイスの機能を制限しているからです。
この記事では、各モードで消費される電流の明確な値を示していませんが、STM32L053 DiscoveryボードのIDD電流測定機能を使うのページでは、各低消費電力モードの測定例をいくつか示しています。
低消費電力実行モード
低いシステムクロックを採用して低消費電力モードとして販売するのは、むしろごまかしです。なぜなら、低いシステムクロックが低消費電力モードの主な理由だからです。マイクロコントローラのクロック速度をキロヘルツ台まで下げると、消費電流が劇的に減少し、平均的なスリープモードに匹敵するほどになります。しかし、性能の低下と静的な消費電流(クロック周波数に依存しない)が、長期的にはより多くのエネルギーを消費する可能性があるため、通常、そのようなことは行われません。どのスリープモードを使用するか、またはデバイスがウェイクアップする頻度などアアプリケーションによっては、少ない電流で長い時間消費するよりも、多い電流で短い時間消費する方が効率的な場合があります。STがこれを低消費電力モードと分類できるのは、内蔵電圧レギュレータを低消費電力状態にする機能を提供しているからです。これにより、デバイスが消費する静的電流が減少し、性能と総消費電流のトレードオフへの影響を最小限に抑えることができます。
レギュレータを低電力モードに切り替えるには、2つの条件を満たす必要があります。まず、レギュレータ電圧(VCORE)が範囲2でなければなりません。幸運なことに、PWR_CR レジスタのドキュメントによると、これはレギュレータのデフォルト構成です。したがって、デバイスの動的電圧スケーリング機能を利用しない限り、この前提条件を心配する必要はありません。2つ目の条件は、システム周波数がfMSIの範囲1を超えないことです。RCC_ICSCRレジスタのMSIRANGEビットの記述によると、これは約131.072kHzの周波数に相当します。この速度と電力レベルでは、USB、ADCおよびTSC(Touch Sensing Controller)ペリフェラルは使用不可です。周波数に依存する周辺機器(USART、タイマなど)はすでに初期化されていても、正しく動作し続けるために、システム周波数が変更された後、再初期化される必要があります。
低消費電力実行モードでは、他の低消費電力モードと異なり、CPUが停止することはありません。つまり、先に説明したWFI/WFE命令で入るのではなく、PWR_CRレジスタのLPSDSR(Low-Power Sleep-Deep/Sleep/low-power Run)ビットとLPRUN(Low-Power RUN)ビットを設定することで入ることができるのです。LPRUNを設定する前にLPSDSRを設定し、LPSDSRをクリアする前にLPRUNをクリアし、他の低電力モードに入る前にLPRUNをクリアする必要があることに注意してください。低消費電力実行モードでもプログラムの実行は継続されるため、デバイスは有限の割り込みやイベント に制限されることなく、ソフトウェアによって「ウェイクアップ」されます。LPRUNビットをクリアし、システム周波数をフルスピードに戻すだけで、システムは実行モードに戻ります。リスト1は、リファレンスマニュアルに記載されている手順を使用して、低消費電力実行モードに移行する全手順を示しています。リスト2は、デバイスがもはや低消費電力実行モードを必要としない場合に、実行モードに再エントリする方法を示しています。
リスト1:低消費電力実行モードへの移行例
void enter_LPRun( void )
{
/* 1. Each digital IP clock must be enabled or disabled by using the
RCC_APBxENR and RCC_AHBENR registers */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* 2. The frequency of the system clock must be decreased to not exceed the
frequency of f_MSI range1. */
Config_SysClk_MSI_131();
// Reinitialize peripherals dependent on clock speed
USART1_Init();
SysTick_Init( 0.001 );
I2C1_Init();
/* 3. The regulator is forced in low-power mode by software
(LPRUN and LPSDSR bits set ) */
PWR->CR &= ~PWR_CR_LPRUN; // Be sure LPRUN is cleared!
PWR->CR |= PWR_CR_LPSDSR; // must be set before LPRUN
PWR->CR |= PWR_CR_LPRUN; // enter low power run mode
}
リスト2:実行モードに入る例
void enter_Run( void )
{
/* Enable Clocks */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Force the regulator into main mode */
// Reset LPRUN bit
PWR->CR &= ~( PWR_CR_LPRUN );
// LPSDSR can be reset only when LPRUN bit = 0;
PWR->CR &= ~( PWR_CR_LPSDSR );
/* Set HSI16 oscillator as system clock */
Config_SysClk_HSI16();
// Reinitialize peripherals dependent on clock speed
USART1_Init();
SysTick_Init( 0.001 );
I2C1_Init();
}
スリープモード
スリープモードは、低消費電力モードの中で最も分かりやすく、ウェイクアップ時間を最短にできる反面、消費電力が最も高くなります。データシートによると、すべてのペリフェラルを無効にし、システム周波数を16MHzにした場合、約1mAの電流が消費されるということです。これは、マイクロアンペアやナノアンペアのオーダーで値を達成できる他の低消費電力モードよりもはるかに高い値です。しかし、ウェイクアップ時間は、最も競争力のある低消費電力モードと比較して、ほぼ10倍の速さになります。表2は、各低消費電力モードからウェイクアップし、動作モードに移行するまでの時間を示したものです。ウェイクアップ時間の値は、データシートの表4から引用しています。
表2:各低消費電力動作モードのウェイクアップ時間
Low-power run | 3 µs |
---|---|
Sleep | 0.36 µs |
Low-power sleep | 32 µs |
Stop | 3.5 µs |
Standby | 50 µs |
スリープモードでは、コアだけが停止し、すべてのペリフェラルは動作し続けます。このため、システム周波数を下げる必要がなく、デバイスのすべてのペリフェラルが使用可能なため、スリープモードに入るのは実質的に簡単です。また、実行モードで利用可能なあらゆる割り込みやイベントがデバイスをウェイクアップし、非常に短い遅延時間でサービスを受けることができるため、スリープモードを終了することも非常に簡単です。このように、スリープモードは、CPUがスピンロック状態でイベント発生を待っているようなほぼすべての状況で使用することができます。ビジーウェイトループに入るのではなく、ユーザーは単にWFIまたはWFE(ウェイクアップ方法による)を実行して動作を中断し、コアが再び必要になるまで電力を節約することができます。これは、SCRがデフォルトでスリープモードに設定されている、つまりSLEEPDEEPビットがクリアされているために機能します。CPUが割り込みの処理にのみ必要なアプリケーションでは、SLEEPONEXITビットを設定し、常に割り込みが処理された後にスリープモードに入る方が、プログラムの実行を再開するよりも理にかなっています。
リスト3は、スリープモードに入るために使用できる関数の例です。この関数は、複数の低消費電力モードを使用するプログラムから取られているため、最初のステートメントでは、予期しない動作を避けるためにSLEEPDEEPビットがクリアされていることを確認しています。また、ウェイクアップの遅延を避けるため、デバイスがスリープモードの間、不揮発性メモリをアイドル状態に保つよう、フラッシュアクセス制御レジスタが設定されています。フラッシュメモリインターフェースのクロック停止については、低消費電力スリープモードのセクションで詳しく説明します。
リスト3:スリープモードへの移行例
void enter_Sleep( void )
{
/* Configure low-power mode */
SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk ); // low-power mode = sleep mode
SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // reenter low-power mode after ISR
/* Ensure Flash memory stays on */
FLASH->ACR &= ~FLASH_ACR_SLEEP_PD;
__WFI(); // enter low-power mode
}
低消費電力スリープモード
低消費電力スリープモードは、基本的に低消費電力実行モードとスリープモードを組み合わせたものです。Cortex-M0+コアが停止するだけでなく、レギュレータが低消費電力モードになるため、低消費電力実行モードと同じ条件を満たす必要があります。VCOREが範囲2(デフォルト設定)であること、システムクロック周波数がfMSIの範囲1(131.072kHz)以下に低下していることが必要であることを思い出してください。このため、USB、ADCおよびTSCペリフェラルはこのモードでは使用できません。また、低消費電力スリープモードで動作し続ける周波数依存のペリフェラルは、正しく動作し続けるように再初期化する必要があります。
低消費電力実行モードとは異なり、LPRUNビットはレギュレータを低消費電力モードにするために使用されるものではありません。システム周波数が低下したら、LPSDSRビットを設定し、スリープモードに入るのと同じ手順を行う必要があります。すなわち、SLEEPDEEPビットがクリアされていることを確認し、WFI命令、WFE命令を実行するか、SLEEPONEXITビットを設定し、例外リターンを待ちます。LPSDSRビットは、デバイスが低消費電力モードに入ると、レギュレータを自動的に低消費電力状態にします。ウェイクアップイベントの後、デバイスが低消費電力モードを終了すると、レギュレータがフルパワーで動作する実行モードになります。
リファレンスマニュアルでは、低消費電力スリープモードのセクションで、フラッシュメモリをオフにするオプションに言及しています。FLASH_ACRレジスタのSLEEP_PD(SLEEP Power-Down)ビットを設定すると、デバイスがスリープモードまたは低消費電力スリープモードになったときに不揮発性メモリがパワーダウン状態になります。これにより、ウェイクアップの遅延が増加しますが、消費電力は約12μA減少し(データシートの表34)、アプリケーションによっては、大きな効果を発揮する可能性があります。リファレンスマニュアルのスリープモードセクションでこのオプションについて言及されていないのは、おそらくこのウェイクアップ時間の増加のためです(スリープモードで動作するにもかかわらず)。スリープモードを使用するアプリケーションが、スリープモードが提供する非常に速いウェイクアップ時間を必要としない場合、おそらく代わりに低消費電力スリープモードを使用するべきです。リスト4は、リファレンスマニュアルに記載されている手順に従って、低消費電力スリープモードに入るために使用される関数の例です。
リスト4:低消費電力スリープモードへの移行例
void enter_LPSleep( void )
{
/* 1. The Flash memory can be switched off by using the control bits
(SLEEP_PD in the FLASH_ACR register). This reduces power consumption
but increases the wake-up time. */
FLASH->ACR |= FLASH_ACR_SLEEP_PD;
/* 2. Each digital IP clock must be enabled or disabled by using the
RCC_APBxENR and RCC_AHBENR registers */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* 3. The frequency of the system clock must be decreased to not exceed the
frequency of f_MSI range1. */
// Set MSI 131.072 kHz as system clock
Config_SysClk_MSI_131();
// Reinitialize peripherals dependent on clock speed
USART1_Init();
SysTick_Init( 0.001 );
I2C1_Init();
/* 4. The regulator is forced in low-power mode by software
(LPSDSR bits set ) */
PWR->CR |= PWR_CR_LPSDSR; // voltage regulator in low-power mode during sleep
/* 5. Follow the steps described in Section 6.3.5: Entering low-power mode */
SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk ); // low-power mode = sleep mode
SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // reenter low-power mode after ISR
__WFI(); // enter low-power mode
}
ストップモード
STM32L0シリーズで利用可能な低消費電力モードの中で最も複雑なモードと言えるストップモードは、SRAMとレジスタの内容を保持したまま、ナノアンペアオーダーの消費電流を達成する可能性を持っています。しかし、ウェイクアップ時間がより重要である場合、低消費電力動作モードと同等の遅延を達成するために、多くの省電力オプションが無視される可能性があります。さらに、利用可能なウェイクアップソースの数が限られていること、エラッタシートでストップモードについて何度も言及されていること、およびデバッグが複雑であることなどが問題を複雑にしています。とはいえ、ウェイクアップ時にシステムを再初期化する必要がなく、最小限の電力で動作させたい場合は、ストップモードが最適な選択肢になるでしょう。
ストップモードでは、コアは停止し、LSE、LSIおよびHSIのみが限定的に動作可能な発振器となります。低速クロックにより、RTCとIWDGは動作を継続し、デバイスをウェイクアップすることができます。HSIはストップモードで動作可能なペリフェラルに制限された機能を提供することができます。例えば、USARTとI2Cはストップモードでも、必要なときにHSIをウェイクアップすることでデータを受信することができます。HSIはそれを要求したペリフェラルにのみ給電し、不要になると自動的に無効になります。ストップモードで機能する全てのペリフェラルと、どのウェイクアップソースが利用可能かの完全なリストについては、データシートの表4を参照してください。なお、ストップモードに入ると、コアクロックが停止するため、デバッグ接続を維持することができなくなります。ただし、リファレンスマニュアルによると、DBGMCU_CRレジスタのDBG_STOPビットを設定することで、ストップモードでのデバッグが可能になります。
ストップモードとスタンバイモードはどちらもCortex-M0+コアによって提供されるディープスリープ状態の実装であるため、ストップモードに入るにはSLEEPDEEPビットを設定する必要があります。PWR_CRレジスタのPDDS(Power Down DeepSleep)ビットをクリアすることで、スタンバイモードではなくストップモードが選択されます。また、PWR_CSRレジスタのWUF(Wake-Up Flag)ビットをクリアしておく必要があります。残念ながら、このビットはソフトウェアで変更できないため、PWR_CR レジスタのCWUF (Clear Wake-UP Flag)ビットに1を書き込むことでクリアする必要があります。これにより、2システムクロックサイクル後にWUFがクリアされます。これらの条件が満たされれば、ユーザーはWFI命令、WFE命令を実行するか、SLEEPONEXITビットを設定し、例外リターンを待つだけでよいのです。デフォルトでは、デバイスがストップモードからウェイクアップするとき、システムクロックとしてMSI発振器が選択されることに注意してください。ストップモードに入る前にRCC_CFGRレジスタのSTOPWUCK(STOP Wake-Up ClocK)ビットを設定すると、代わりにHSI16発振器がシステムクロックとして選択されるようになります。リスト5は、この最小限の構成でストップモードに入る関数例です。また、デバイスをウェイクアップさせる外部割り込みを有効にする方法も示しています。
リスト5:ストップモードに移行する簡単な例
void enter_Stop( void )
{
/* Enable Clocks */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
/* Configure PA0 as External Interrupt */
GPIOA->MODER &= ~( GPIO_MODER_MODE0 ); // PA0 is in Input mode
EXTI->IMR |= EXTI_IMR_IM0; // interrupt request from line 0 not masked
EXTI->RTSR |= EXTI_RTSR_TR0; // rising trigger enabled for input line 0
// Enable interrupt in the NVIC
NVIC_EnableIRQ( EXTI0_1_IRQn );
NVIC_SetPriority( EXTI0_1_IRQn, BTN_INT_PRIO );
/* Prepare to enter stop mode */
PWR->CR |= PWR_CR_CWUF; // clear the WUF flag after 2 clock cycles
PWR->CR &= ~( PWR_CR_PDDS ); // Enter stop mode when the CPU enters deepsleep
RCC->CFGR |= RCC_CFGR_STOPWUCK; // HSI16 oscillator is wake-up from stop clock
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode
__WFI(); // enter low-power mode
}
より多くの電力を節約したいが、ウェイクアップ時間をあまり気にしない場合は、ストップモードに入る前に追加で設定できることがあります。最も簡単なものは、PWR_CRレジスタのLPSDSRビットを設定することにより、レギュレータを低電力モードにすることです。同じレジスタで、ULP(超低電力モード)ビットを設定し、VREFINT(内部電圧基準)がどのアナログペリフェラルによっても使用されていない場合、それを無効にすることもできます。さらに、ウェイクアップ直後にVREFINTが必要ない場合は、FWU(Fast Wake-Up)ビットを設定すれば、ULPを設定した場合に発生するウェイクアップ遅延が追加されることはありません。
上記の変更により、消費電流は大幅に減少しますが、それでもマイクロアンペアのオーダーで消費する可能性があります。ナノアンペア台にするには、すべてのGPIOピンをアナログモードにする必要があります。リファレンスマニュアルの9.3.12項によると、I/Oピンをアナログに設定すると、シュミットトリガ入力が非アクティブになり、各ピンの消費電流はゼロになります。ただし、この場合、各ピンをアナログモードに切り替える前に、各ポートのGPIOx_MODERレジスタを保存しておく必要があります。この方法では、デバイスがウェイクアップすると同時に、すべてのピンを以前のモードに戻すことができます。また、予期せぬエラーを避けるために、保存と復元の両方のプロセスで割り込みを無効にする必要があります。
リスト6の関数は、リスト5の基本関数をベースに構築されています。レギュレータを低消費電力モードにし、VREFINTをオフにするだけでなく、ストップモードに入る前にI/Oコンテキストを保存しています。WFI実行時に割り込みが無効になっていたため、つまりPMビットが設定されていたため、外部割り込みによってデバイスはウェイクアップしますが、そのISRには入りません。プログラムの実行はWFI命令から継続され、コンテキストが直ちに復元されます。割り込みが再び有効になると、割り込みはまだ保留状態なので、外部割り込みのISRに入ります。
リスト6:ストップモードに移行する高度な例
void enter_Stop( void )
{
/* Enable Clocks */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
/* Configure PA0 as External Interrupt */
GPIOA->MODER &= ~( GPIO_MODER_MODE0 ); // PA0 is in Input mode
EXTI->IMR |= EXTI_IMR_IM0; // interrupt request from line 0 not masked
EXTI->RTSR |= EXTI_RTSR_TR0; // rising trigger enabled for input line 0
// Enable interrupt in the NVIC
NVIC_EnableIRQ( EXTI0_1_IRQn );
NVIC_SetPriority( EXTI0_1_IRQn, BTN_INT_PRIO );
/* Prepare to enter stop mode */
PWR->CR |= PWR_CR_CWUF; // clear the WUF flag after 2 clock cycles
PWR->CR &= ~( PWR_CR_PDDS ); // Enter stop mode when the CPU enters deepsleep
// V_REFINT startup time ignored | V_REFINT off in LP mode | regulator in LP mode
PWR->CR |= PWR_CR_FWU | PWR_CR_ULP | PWR_CR_LPSDSR;
RCC->CFGR |= RCC_CFGR_STOPWUCK; // HSI16 oscillator is wake-up from stop clock
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode
__disable_irq();
Idd_SaveContext();
I2C1->CR1 &= ~I2C_CR1_PE; // Address issue 2.5.1 in Errata
__WFI(); // enter low-power mode
I2C1->CR1 |= I2C_CR1_PE;
Idd_RestoreContext();
__enable_irq(); // <-- go to isr
}
リスト5とリスト6は、いずれもPA0ピンからの外部割り込みを使用してデバイスをウェイクアップします。これは、外部割込みはEXTIによって制御され、システムリセット以外ではEXTIだけがデバイスをストップモードから抜け出させることができるためです。つまり、EXTIは、割り込みやイベントを発生させることができる30本の内部および外部ラインを管理しています。リファレンスマニュアルの表52は、各ラインのラインソースと、それらが設定可能なラインであるか、ダイレクトラインであるかを明記しています。上記の例では、EXTIライン0はデフォルトでPA0にマップされているため、ライン自体を設定する必要はありません。必要なことは、このラインを割り込みソースとしてイネーブルにし、割り込みのトリガを選択し、NVICで対応する割り込みをイネーブルにすればよいだけです。WFE 命令を使用してストップモードに入った場合、ラインはイベントモードでイネーブルになります。
表3は、STM32L053x6/8 Errata sheetに記載されているストップモードの制限事項をまとめたものです。どのようなチップリビジョンであっても、予期せぬエラーを回避するために、プログラマーが対処すべき問題があることは明らかです。リスト6の関数は、I2Cペリフェラルがストップモードからデバイスをウェイクアップするように設定されていないために起こる問題の回避策を提案して実装しています。Errataの2.5.1項では、ストップモードに入る前にI2Cペリフェラルをディセーブルし、ウェイクアップ後にすぐにそれを再イネーブルするとエラーが回避されると説明されています。幸運にも、この回避策は、I/Oコンテキストの保存および復元と同時に行うことができます。
表3:STM32L053x6/8のエラッタに記載されているストップモードの制限事項
Section 2.1.2 | HSI16がクロックシステムで、 ウェイクアップクロックとして 選択されている場合、リセット イベントによるストップモ ード の解除はできません |
回避策あり | 対応済 | 対応済み | 対応済み |
---|---|---|---|---|---|
Section 2.1.10 | フラッシュが省電力モードの 状態で、ストップまたはスリ ープから復帰する際のフラッシュ メモリのウェイクアップ問題 |
回避策あり | 回避策あり | 対応済み | 対応済み |
Section 2.1.11 |
レギュレータを低消費電力 モードにした状態でストップ モードから復帰した際の予期 せぬシステムリセット |
回避策あり | 回避策あり | 対応済み | 対応済み |
Section 2.1.12 | I2CとUSARTがデバイスをスト ップモードからウェイクアップ できない |
回避策なし | 回避策なし | 回避策なし | 対応済み |
Section 2.5.1 |
I2Cペリフェラルでストップ モードからのウェイクアップを 無効にしている場合、ストップ モードでの動作が異常になる |
回避策あり | 回避策あり | 回避策あり | 回避策あり |
スタンバイモード
ストップモードと異なり、スタンバイモードへの移行は、ユーザーの選択肢が少ないため非常にシンプルです。発振器はLSIとLSEのみ、ペリフェラルはRTCとIWDGのみ、電圧レギュレータは完全に無効、そしてI/Oピンはすべてハイインピーダンス(つまりコンテキストを保存しても意味がない)に設定されます。スタンバイモードに入るには、SLEEPDEEPビットを設定し、PDDSビットを設定し、CWUFビットに「1」を書き込んでWFUビットがクリアされていることを確認するだけでよいのです。その後、WFI命令、WFE命令を実行するか、例外リターンの前にSLEEPONEXITを設定すると、デバイスはこの低消費電力モードになります。また、スタンバイモードを終了するためのオプションも限られています。ウェイクアップピン(PA0またはPC13)の立ち上がりエッジ、RTCウェイクアップイベントの1つ、またはIWDGリセットのみがデバイスをウェイクアップさせます。スタンバイモードに入る前に、選択した方法を設定し、対応するウェイクアップフラグをクリアする必要があります。STM32L053C8チップにはウェイクアップピンが2つしかありませんが、リファレンスマニュアルやデータシートでは、ピン数の多いパッケージでのみ使用できる第3のウェイクアップピンに言及していることが多いので、注意してください。
スタンバイモードの最大の問題点は、SRAMやレジスタ(RTCレジスタ、RTCバックアップレジスタおよびスタンバイ回路を除く)の内容を保持しないことです。スタンバイモードから復帰した後は、リセットが発生した場合と同様にプログラムの実行が再開されます。システムがスタンバイモードからウェイクアップされたかどうかを判断するには、main()関数に入るとすぐにPWR_CSRレジスタのSBF(StandBy Flag)ビットでチェックすることができます。このビットがセットされている場合、デバイスはスタンバイモードだったということであり、SBFをクリアにするためにCSBF(Clear StandBy Flag)をセットすることで、ユーザーは初回実行時にシステムを初期化するべきか、システムを以前の状態に戻すべきか判断できます。
表2において、スタンバイモードが最も長いウェイクアップ時間であることに注目してください。この推定値には、システムを再初期化し、プログラムの実行を再開するのに必要な時間は含まれていません。この遅延時間が増えると、ウェイクアップイベントに即座に対応できなくなるだけでなく、スタンバイモードの省電力機能が大きく制限されることになります。平均消費電流をストップモード以下にするためには、デバイスを非常に長い時間スタンバイモードにする必要があります。どの程度の時間かは、ウェイクアップ/再初期化処理でどの程度の電流が消費されるかに依存します。リスト7はスタンバイモードに入るために使用される関数の例で、ウェイクアップピンのいずれかがデバイスをウェイクアップします。
リスト7:スタンバイモードへの移行例
void enter_Standby( void )
{
/* Enable Clocks */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Prepare for Standby */
// if WKUP pins are already high, the WUF bit will be set
PWR->CSR |= PWR_CSR_EWUP1 | PWR_CSR_EWUP2;
PWR->CR |= PWR_CR_CWUF; // clear the WUF flag after 2 clock cycles
PWR->CR |= PWR_CR_ULP; // V_{REFINT} is off in low-power mode
PWR->CR |= PWR_CR_PDDS; // Enter Standby mode when the CPU enters deepsleep
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode
SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // reenter low-power mode after ISR
__WFI(); // enter low-power mode
}
まとめ
STM32Lファミリのマイクロコントローラは、ガス/水道メータ、ウェアラブル、あるいはIoTセンサなどの超低消費電力アプリケーション向けに、ユーザーが性能と消費電力のバランスを慎重に判断できるように多くの低消費電力モードを備えています。特に、STM32L0シリーズは、最もエネルギー効率の高いARMプロセッサ(Cortex-M0+)を採用し、ほとんどのエントリレベルのアプリケーションに適した5つの低消費電力モードを提供しています。これらを低消費電力ペリフェラルと組み合わせて使用することで、バッテリ寿命を大幅に延長し、達成すべき環境発電の要件を1つ満たすことができます。
低消費電力実行モードは、スリープモードよりも消費電流を抑えながら、最高のパフォーマンスを発揮します。CPUが動作し続けるため、デバイスをウェイクアップするかどうかはソフトウェアが決定するという点で、最も柔軟性があります。残念ながら、レギュレータを低消費電力モードにすると、多くのリアルタイムアプリケーションにとって大きすぎるウェイクアップ遅延が発生します。スリープモードが最も優れているのはこの点で、コアが無効化されている間も、すべてのペリフェラルがフルスピードで動作しているため、ウェイクアップ時間は0.36μ秒を誇ります。しかし、このモードは最も電力を消費する低消費電力モードであり、ペリフェラルの性能とハードウェアウェイクアップソースのフルセットがあっても、これを補うことはほとんどできません。低消費電力スリープモードは、低消費電力動作モードと同じ手法で、ウェイクアップソースの数を制限することなく、消費電流をストップモードと同レベルまで低減させます。しかし、EXITでウェイクアップさせれば十分な場合は、ストップモードがSRAMやレジスタの内容を保持したままで、最も低消費電流になります。また、ウェイクアップ時間も低消費電力実行モードに匹敵します。最後に、MCUが非常に長い時間必要とされないアプリケーションには、スタンバイモードが適しているかもしれません。ウェイクアップソースが非常に少なく、ウェイクアップ時間が最も長くなりますが、消費電力は最も少なくなります。
機能的なアプリケーションで使用される上記の関数の例を確認するには、次のページにアクセスしてください:STM32L053 DiscoveryボードのIDD電流測定機能を使う
このアプリケーションでは、ユーザーが希望する低消費電力モードを入力し、その状態で消費される電流を確認することができます。Config_SysClk_HSI16()、Idd_SaveContext()など、上記の例で使用されている関数を含む、完全なコードが利用可能です。また、これらの機能を使って各モードに入った場合の平均消費電流が同ページの表1にまとめられています。