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開発者は注釈の中でこの問題について説明しています.原文は以下の通りです.
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を自分で配置し、自分で底からブレを消したほうがいい.