STM32のEXTIはGPIOを外部割り込みラインに使える便利な機能ですが、HALの説明が雑で、どうすればイネーブル・ディセーブルできるのかがピンときません。
EXTIを使えばGPIO経由で最大16本のEXTI割り込み線を定義できます。内部ではもっと利用できるのですが、GPIO各ポートが16pinまでなので、EXTIで使える外部線は16というのは合理的です。
さて、EXTIの設定はCubeIDEで出来ますので、ささっと設定して対応するNVICの割り込みラインをイネーブルにすれば、すぐにアプリケーションを割り込み可能に出来ます。ところが、Enable Interrupt, Disable InterruptといったAPIがありません。割り込みを禁止できないアプリケーションというのは、どうも気分がよくありません。
「だったらNVICのラインでイネーブル・ディセーブルすればいい」
という声が返ってきそうですが、それはだめです。STM32の設計ではEXTIの各ラインとNVICの割り込み入力が一対一対応していません。そのため、独立に割り込みラインを制御したければ、NVICを触るのは悪手です。
結局、割り込みのイネーブルとディセーブルは次のAPIを使います。
- HAL_EXTI_SetConfigLine();
- HAL_EXTI_ClearConfigLine();
なんでやねん。
以下、プログラムの中でEXTIをディセーブル、イネーブルする手順を説明します。
まず、EXTIのハンドルと設定用変数を定義します。CubeIDEはEXTIのハンドルを生成しませんので、自分で作らなければなりません。ハンドルはEXTIのライン一本一本に専用のハンドルを定義します。
EXTI_HandleTypeDef hexti_b1 = { 0 }; EXTI_ConfigTypeDef hexti_b1_config;
次に、ハンドルをを初期化します。初期化はlineメンバー変数にEXTIのラインを設定するだけです。ここで注意すべきは、lineメンバー変数に勝手な変数を代入しては行けないことです。必ずEXTI_LINE_##定数を代入してください。
hexti_b1.Line = EXTI_LINE_13;
次に、EXTIの設定をペリフェラルから取り出します。最初の引数には先程のハンドルでEXTIラインを指定しします。成功するとAPIは2番めの引数に設定を格納します。
HAL_EXTI_GetConfigLine( &hexti_b1, &hexti_b1_config );
EXTIのディセーブルにはClear API を使います。
HAL_EXTI_ClearConfigLine( &hexti_b1);
この呼び出しでEXTIの当該ラインの割り込み設定が全てクリアされますので、割り込みディセーブルとすることが出来ます。イネーブルしたい場合には先ほど取り出したEXTI設定を使ってハードウェアを再設定します。
HAL_EXTI_SetConfigLine( &hexti_b1, &hexti_b1_config);
たかが割り込み線のイネーブル・ディセーブルに設定全体をいじりまわすとは大げさですが、他に適当なAPIがありません。もしもっと良い方法をご存知の方はお教えください。
3年前以上前のブログにレスするのもアレですが
HAL_NVIC_EnableIRQ
と
HAL_NVIC_DisableIRQ
ではダメなんですか?
引数にはEXTIx_IRQnを指定します
3年前にはこの関数はなかった?
HAL_NVIC_EnableIRQ()はNVICの割り込みライン単位でイネーブル・ディセーブルを行います。
STM32はGPIOの複数割り込みラインを同じNVICのラインで共用してしまうため、それらが一斉にイネーブル・ディセーブルされてしまう問題があります。
ということで、私はこの関数は使っていません。