/* * 割込み・例外あれこれ * by uratan! 2012.12.30 * revised: 2015.07.25 */ PRIGROUP - 優先順位の設定を GROUP と SUB の二つに分ける。 例外処理中に さらに割り込むことができるのは GROUP が より強い場合だけ。 SUB は同一グループの場合の処理の順番を決めるのに使用される。 GROUP/SUB に各々何ビット振り分けるか、は AIRCR レジスタで 設定できる。 LPC1830 では priority は 3bit分のみ実装されている。 リセットでのデフォルト設定では 3bit すべて GROUP として扱われる。 NVIC->IP[] - 割り込みの優先順位を設定するレジスタ群。 LPC1830 では設定値は 3bit 幅 (8bitレジスタ中の 0xE0 の位置)。 NVIC_Get/SetPriority() では 0〜7 を渡す。 SCB->SHP[] - 例外処理の優先順位を設定するレジスタ群。 LPC1830 では設定値は 3bit 幅 (8bitレジスタ中の 0xE0 の位置)。 例外の中で優先順位を設定できるのは以下の 6つ。 /* 4: MemManageFault */ /* 5: BusFault */ /* 6: UsageFault */ /* 11: SVCall */ /* 14: PendSV */ /* 15: SysTick */ NVIC_Get/SetPriority() では 0〜7 を渡す。 PRIMASK - priority を設定できる例外・割込み、のハンドラの起動をマスク。 (すべての割込みと一部の例外) (CPSIx I もしくは MRs/mSR で触れ、と書いてある) ( CPSIx I - __disable/enable_irq() ) ( MRs/mSR - __Get/Set_PRIMASK() ) FAULTMASK - NMI 以外のすべての例外・割込み、のハンドラの起動をマスク。 本ビットは、(NMI 以外の)ハンドラから抜けるときには プロセッサによって自動的にクリアされる、らしい。 (CPSIx F もしくは MRs/mSR で触れ、と書いてある) ( CPSIx F - __disable/enable_fault_irq() ) ( MRs/mSR - __Get/Set_FAULTMASK() ) PRIMASK との違いは 実質的に HardFault をマスクするかどうか、 だけである。 FAULTMASK 中に HardFault を起こすとダブルフォルトで停止するみたい。 (内部的な実行レベルを HardFault ハンドラ実行中と扱うためか) BASEPRI - 現在のコンテキストの割込み優先レベルを設定するレジスタ。 優先順位がこれを上回る割込み・例外のみがハンドラ起動される。 0 の場合は最弱として扱われる。(優先順位 8 と等価) 最強設定 1 でも、優先順位 0 および マイナス は割り込める、ようだ。 ハンドラの記述 - gcc において、__attribute((interrupt))属性 は必要ない。 これは関数呼び出し規約に則ったレジスタ退避ほかを ハードがやってしまうから。 RITIMER - RITIMER はリセット直後からカウント開始している NVIC->ISPR[] に要求が現れることがありました。 (NVIC->ISER[] で disable されているので割り込みには至らない) (*) 割込み禁止は __disable_irq() を使いましょう。 通常メモリ書き込みによる割込み禁止は、パイプラインによる 遅れがあるものと思いましょう。 - * - * - [2015.07.25] Cortex-M0 を扱うようになったのでいろいろ復習中 PRIMASK ... 「割り込みマスク機能ビット」でなくて、 「現在の割込み優先レベル(pri)を 最強のゼロに(mask)と扱うから (レベル比較上)どの割り込みも割り込めないぜ」 というモデルのように思いなおし中…。 FAULTMASK ... 同じく、…レベルを -1 と扱う…、と思い直し中。 BASEPRI ... M0 ではこのレジスタはない。 これは本レジスタで現在レベルを 保持 しているのでなくて、 現在レベルの最低値をホショウするロジックみたいと思い直し中。 if(intr_level > higher(exec_level, BASEPRI)) then ... ま、M3 と M0 と、どこまで設計思想が同じなのかも不明ですが…。 とかく ARM 関係の資料はポインターが多くて…。