ARMの動的割り込み管理

今日は、STM32マイクロコントローラを例として使用して、ARMプロセッサの割り込みハンドラを動的に置き換える方法を説明します。 説明した方法は、ARM Cortex M3以上のプロセッサで機能します。



いつ、どこで必要になるのでしょうか? まず、異なるハードウェアプラットフォームと互換性のあるプログラムを作成するタスクに直面している場合、割り込みハンドラを置き換えることができます。 ARMプロセッサには、アーキテクチャの実装に必要なカーネル割り込みがいくつかあります。 ただし、残りの割り込みは周辺機器用に設計されており、プロセッサの製造元は、プロセッサで使用可能な周辺機器にこれらのベクトルを自由にインストールできます。 これには、各アーキテクチャの実装に必要な割り込みハンドラを動的に置き換える必要があります。 第二に、外部イベントへの反応速度に対する要求が高い製品の場合、割り込みハンドラー内で適切なアクションを選択することが効果的でない場合があり、割り込みベクトルを動的に変更する方が有利です。



割り込みハンドラをプログラムで変更する方法を理解するために、割り込みが発生したときに何を行う必要があるかをプロセッサが正確に判断する方法を検討してください。 STM32マイクロコントローラーでは、割り込みベクターテーブルは実行可能コードの最初にあります。 実行可能ファイルの最初の32ビットワードはスタックポインターです。 通常、コントローラーRAMの最大アドレスと同じです。 次に、Reset_Handler、NMI_Handler、およびその他の割り込みハンドラーへのポインターがあります。 理論的には、割り込み処理用の新しい関数を動的に設定するには、これらのポインターのいずれかを書き換えるだけです。 ただし、プラットフォームのハードウェアの制限により、STM32のプログラムはFLASHメモリから実行され、新しい単語を書き込むために最初にページ全体を消去する必要があるため、これは許可されません。これは計画の一部ではありません。プログラムは破損できません。 したがって、割り込みテーブルをRAMに転送して、そこにあるベクトルを変更してみましょう。 しかし、疑問は残ります。テーブルが移動されたことをカーネルはどのように知るのでしょうか? 結局のところ、割り込みが発生したときにカーネルが古いテーブルに戻り、古いハンドラを呼び出す場合、テーブルをコピーするだけでは結果が得られません。 この状況を解決するために、VTOR(ベクターテーブルオフセットレジスタ)レジスタがあります。 コントローラのドキュメントにはこのレジスタの説明はありませんが、デバッガもそれについては知りません。 このレジスタに関する情報は、ARMコアのドキュメントで検索する必要があります。ヘッダーファイルcore_cm3.hで見つけることもできます。 レジスタは0xE000ED08にあり、その値は0x400の倍数でなければなりません。 これは、割り込みテーブルを必要な場所に配置できないことを意味します。 頭を悩ませるのではなく、RAMの先頭に配置し、その後、VTORレジスタを新しい値に設定します。 新しい割り込みテーブルに記入し、システムタイマー割り込みを使用してテストします。



このタスクを実装するには、gccコンパイラーであるCMSISライブラリーを使用します。 startup_stm32f103xb.asmファイルとリンカースクリプトを変更する必要があります。 リンカスクリプトでは、RAM内の割り込みテーブルの場所を明示的に指定し、割り込みテーブルの開始と終了の変数を宣言する必要があります。 startup_stm32f103xb.asmファイルで、テーブルをコピーし、新しいVTORレジスタ値を設定する必要があります。 ライブラリファイルを変更することにしたのはなぜですか。通常、これは推奨されません。 実際、メモリのセクションを割り当てる操作はできるだけ早く実行する必要があり、このファイルのコードを実行するのはこの操作です:.dataセクションからグローバル変数をコピーし、静的メモリ(.bss)をゼロで初期化します。 .isr_vectorセクションのコピーを追加するだけです。



リンカースクリプトの変更に進みます。 .isr_vectorセクションを次のように書き換えます。



/* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); //   4-  _svector = .; //    -       KEEP(*(.isr_vector)) //  .isr_vector    . = ALIGN(4); //   4-  _evector = .; //     } >RAM AT> FLASH //    flash-,       _sivector = LOADADDR(.isr_vector); //     flash-.
      
      





割り込みテーブルをRAMに配置する場所を発表しました。 ここで、リンカスクリプトで宣言された変数をアセンブラでさらに宣言する必要があります。 このコードをファイルの上部のどこかに貼り付けます。



 .word _svector .word _evector .word _sivector
      
      





次に、割り込みテーブルをコピーします。 これを行うには、命令{bcc FillZerobss}と{bl SystemInit}の間に次のコードを挿入します。



  movs r1, #0 //  b LoopCopyVectorTable //    CopyVectorTable: ldr r3, =_sivector //   r3      flash- ldr r3, [r3, r1] //      r3+r1,    r3 (r3=*(r3+r1)) str r3, [r0, r1] //   r0+r1   r3 adds r1, r1, #4 //    LoopCopyVectorTable: ldr r0, =_svector //   r0        ldr r3, =_evector //   r3        adds r2, r0, r1 //r2=r0+r1 cmp r2, r3 //  ? bcc CopyVectorTable // ,     
      
      





テーブルがコピーされます。 次に、VTORレジスタの値を設定する必要があります。 既に述べたように、このレジスタのアドレスはcore_cm3.hファイルで指定されていますが、アセンブラーからノックしないで、このファイルで直接宣言するだけです。 定義を書きます:



 .equ VTOR, 0xE000ED08
      
      





そして、この数字を割り込みテーブルの最後に置きます。 これを行うには、.isr_vectorセクションの最後に追加します。



 .word VTOR
      
      





VTORレジスタのアドレスがコントローラーのフラッシュメモリにあることを確認しました。 次に、目的の値をレジスタに書き込みます。 これを行うには、割り込みテーブルのコピーコードの後に​​次のコードを追加します。



  ldr r0, =_svector //       r0 ldr r2, =VTOR //   VTOR   r2 str r0, [r2] //  c,   r2  r0
      
      





それだけです 標準の割り込みテーブルと同じ新しい割り込みテーブルを取得しましたが、現在は動的に変更する機能があります。 これで、メイン機能に安全に切り替えることができます。



  bl __libc_init_array b main
      
      





そして、私たちの作品の仕組みを確認してください



 #define SysTickVectorLoc 0x2000003c //     void main(); void SysTick_Handler(); void SysTick_Handler2(); //  ,    void SysTick_Handler() { *(uint32_t*)SysTickVectorLoc = (uint32_t)SysTick_Handler2; } //    void SysTick_Handler2() { *(uint32_t*)SysTickVectorLoc = (uint32_t)SysTick_Handler; } void main() { //           *(uint32_t*)SysTickVectorLoc = (uint32_t)SysTick_Handler2; //   SysTick_Config(300); while(1) { __WFI();// .   . } }
      
      





ここでは、コントローラーの起動直後に、システムタイマー割り込みハンドラーを変更します。 その後、タイマーを設定し、各割り込みハンドラーでベクターを別の関数に転送します。 したがって、タイマーがアクティブになるたびに、プロセッサは交互にいずれかの機能になります。



コードはSTM32F103コントローラーで確認されました。 質問やコメントがある場合は、コメントを書いてください。



文学



ARM Cortex M3ドキュメント

ARMアセンブラーのドキュメント



All Articles