nRF 52832 GPIOTE割り込み損失の問題
1975 ワード
製品にはGPIO外部割り込み機能が必要で,チップのGPIOTE機能を用いて実現できる.しかし自分でGPIOTEを配置するのは少し面倒で、そこで怠けて、直接ルーチンの中のButton関連コードを使って、外部の中断をボタン入力と見なします.
実際にButtonモデルの下層もGPIOTEプラスタイマーで実現されているが,SDKはいくつかのパッケージを作り,遅延ジッタ除去機能を加えただけである.使用は確かに側面があるが、「割込みをなくしやすい」という弊害もあり、外部割込み信号がチップ(正確には上層アプリケーション)に100%検出されることを保証できないことを意味し、外部割込み回数に厳しい場合には受け入れられない.しかし、なぜこの問題が発生したのでしょうか.では、探究してみましょう.
まずButtonモデルの動作原理を見てみましょう.
1.キーを押したり、外部割り込み信号が入力されたりすると、チップはGPIOTEイベント(割り込み)を生成し、対応するサービス関数はgpiote_である.event_handler()
2.GPIOTE割込みサービス関数では、SDKが自動的にタイマをオンにします.このタイマのタイムアウト時間は、Buttonの初期化時にユーザが設定し、デフォルトは50 msです.タイミング時間から後にGPIO状態を再検出し、それでも有効であればキーイベントを生成し、対応するコールバック関数はbsp_event_handleは,関数のパラメータを介して,どのチャネルの割り込みが発生したのかを知ることができる.
3.50 msのタイミングが到来する前にGPIOTEが中断された場合、SDKは現在のタイマを自動的に停止し、直ちに現在のタイマを起動し、1回のタイマをリセットしたことに相当する.
上記手順3の動作は、1回実行されるごとにタイマキューにノードが追加され、無効なタイマノードはすぐにクリアされるが、GPIOTEイベントが連続的かつ密に到着すると、SDKが無効なタイマをクリーンアップするのに間に合わず、タイマキューがいっぱいになり、タイマの再起動に失敗する可能性がある.上記の手順2から分かるように,下位のGPIOTEイベントはタイマタイムアウトによって上位アプリケーションに伝達され,タイマが失効するとタイムアウトできず,上位アプリケーションに伝達できなくなる.上位アプリケーションでは、今回のキーイベントが失われました.
実は、SDK開発者は注釈の中でこの問題について説明しています.原文は以下の通りです.
だから、この問題を解決するには、GPIOTEを自分で配置し、自分で底からブレを消したほうがいい.
実際にButtonモデルの下層もGPIOTEプラスタイマーで実現されているが,SDKはいくつかのパッケージを作り,遅延ジッタ除去機能を加えただけである.使用は確かに側面があるが、「割込みをなくしやすい」という弊害もあり、外部割込み信号がチップ(正確には上層アプリケーション)に100%検出されることを保証できないことを意味し、外部割込み回数に厳しい場合には受け入れられない.しかし、なぜこの問題が発生したのでしょうか.では、探究してみましょう.
まずButtonモデルの動作原理を見てみましょう.
1.キーを押したり、外部割り込み信号が入力されたりすると、チップはGPIOTEイベント(割り込み)を生成し、対応するサービス関数はgpiote_である.event_handler()
2.GPIOTE割込みサービス関数では、SDKが自動的にタイマをオンにします.このタイマのタイムアウト時間は、Buttonの初期化時にユーザが設定し、デフォルトは50 msです.タイミング時間から後にGPIO状態を再検出し、それでも有効であればキーイベントを生成し、対応するコールバック関数はbsp_event_handleは,関数のパラメータを介して,どのチャネルの割り込みが発生したのかを知ることができる.
3.50 msのタイミングが到来する前にGPIOTEが中断された場合、SDKは現在のタイマを自動的に停止し、直ちに現在のタイマを起動し、1回のタイマをリセットしたことに相当する.
上記手順3の動作は、1回実行されるごとにタイマキューにノードが追加され、無効なタイマノードはすぐにクリアされるが、GPIOTEイベントが連続的かつ密に到着すると、SDKが無効なタイマをクリーンアップするのに間に合わず、タイマキューがいっぱいになり、タイマの再起動に失敗する可能性がある.上記の手順2から分かるように,下位のGPIOTEイベントはタイマタイムアウトによって上位アプリケーションに伝達され,タイマが失効するとタイムアウトできず,上位アプリケーションに伝達できなくなる.上位アプリケーションでは、今回のキーイベントが失われました.
実は、SDK開発者は注釈の中でこの問題について説明しています.原文は以下の通りです.
static void gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
uint32_t err_code;
uint32_t pin_mask = 1 << pin;
// Start detection timer. If timer is already running, the detection period is restarted.
// NOTE: Using the p_context parameter of app_timer_start() to transfer the pin states to the
// timeout handler (by casting event_pins_mask into the equally sized void * p_context
// parameter).
err_code = app_timer_stop(m_detection_delay_timer_id);
if (err_code != NRF_SUCCESS)
{
// The impact in app_button of the app_timer queue running full is losing a button press.
// The current implementation ensures that the system will continue working as normal.
return;
}
// ...
}
だから、この問題を解決するには、GPIOTEを自分で配置し、自分で底からブレを消したほうがいい.