Cortex-M 4 HardFault原因の検索方法


Cortex-M 4 HardFault原因の検索方法


文書ディレクトリ

  • Cortex-M 4 HardFault原因検索方法
  • このブログの背景を書く
  • 思想簡説
  • 私のやり方
  • Step 1:
  • Step 2:
  • Step 3:
  • Step 4:
  • Step 5:
  • Step 5:
  • 結果分析
  • このブログの背景を書く


    ここ数日、GithubでArminkという大神がCortex-MシリーズのHardFaultプロジェクトを追跡しているのを見た.

    思想を簡単に述べる.


    簡単に言えば、HardFaultが発生した後、HardFaultジャンプが中断する前にスタック情報を保存し、カーネルFaultレジスタの状態に基づいて現在どのFaultであるかを判断する.死亡前の現場を保存する.

    私のやり方


    Step 1:
  • 起動ファイルstartup_stm32f407xx.sのHardFault割込み処理部分コードを修正し、私が指定した関数にジャンプしてスタック情報をグローバル変数に保存することで、デバッグを停止した後、Keilのwatch 1にグローバル変数の値を表示することができます.
  • コード修正は以下の
  • である.
    HardFult_Handler	PROC
    ;						EXPORT		HardFault_Handler
    						IMPORT		call_back_fault     ; C , 
    						MOV		R0,	LR
    						MOV		R1,	SP
    						LDR			R2,	=call_back_fault
    						BLX			R2
    						B				.
    						ENDP
    

    Step 2:
  • 定義関数void call_back_fault(uint32_t fault_lr,uint32_t fault_sp);が完了する後に.hファイルで宣言します.
  • コードは次の
  • です.
    uint32_t stack_add[20] = {0};
    uint32_t stack_data[20] = {0};
    void call_back_fault(uint32_t fault_lr,uint32_t fault_sp)
    {
    	uint8_t i = 0;
    	uint32_t stack_pointer = fault_sp;
    	for(i = 0;i<16;i++)
    	{
    		stack_add[i] = stack_pointer;
    		stack_data[i] = *(uint32_t *)stack_pointer;
    		stack_pointer += 4;
    	}
    }
    

    Step 3:
  • Faultが現れる関数を作成します.ここではArmink大神が書いた除数が0にならない関数を直接採用しました.
  • コードは次の
  • です.
    void fault_test(void)
    {
    	volatile int * SCB_CCR = (volatile int *)0xE000ED14;
    	int x,y,z;
    	*SCB_CCR |= (1<<4);
    	x = 10;
    	y = 0;
    	z = x / y;
    }
    

    Step 4:
  • main関数で関数void fault_test(void);
  • を呼び出す
    Step 5:
  • J-Link接続開発ボードを使用して、Keilの下でデバッグモードに入り、実行プログラムをクリックし、数秒待って、停止をクリックします.
  • KeilのPeripherals --> Core Peripherals --> Fault Reportsビューダイアログボックスの次の点を開きます:
  • 1.Usage FaultsのDIVBYZEROがチェックされているのは、Faultが除数0によるものであることを示しています.2.HardFaultsの中のFORCEDがチェックされ、強制的なエラーでHardFualtと判定されたことを説明します.3.DebugFaultsのHALTEDがチェックされており、デバッグモードが停止していることを示しています.
  • KeilのView --> Watch Windows --> Watch 1を開き、2つのグローバル変数をウィンドウに追加し、2つのグローバル変数配列の値を表示します.

  • Step 5:
  • コマンドライン実行ウィンドウを開きます.
  • は、
  • というコマンドを実行します.
    addr2line -e XXX.axf -a -f   addr1   addr 2   addr3   addr4  addr5   addr6
    

    解釈コマンド
  • addr 2 lineは実行可能なコマンドであり、事前にインストールする必要があり、MinGWソフトウェアをインストールできる場合、そのインストールディレクトリの下にbinフォルダ内にこのコマンドがあり、このコマンドパスをシステム環境変数に追加すればよい.インストールが完了した後、コマンドライン実行addr2line --helpコマンドでインストールに成功したかどうかを確認することができる.
  • XXX.axfがこのコマンドを実行する場合、経路はKeil MDKエンジニアリングの生成ファイルの下にある必要があります.このフォーマットファイルはKeil MDKでコンパイルされたときに自動的に生成されます.
  • addr 1は現在のPC値であり、例えば、0 x 0800213;
  • addr 2は現在のLR−4のアドレスであり、フォーマットはaddr 1と同じである.
  • addr 3~addr 6は、Watch 1ウィンドウで観察されたグローバル変数stack_data[]における0 x 0800 xxxに関する値である.
  • の後に続くアドレス値は、複数であってもよい.

  • 結果分析

  • 以上の第5のステップのコマンドを実行した後、コマンドラインにaddr 1からaddr 6までのすべての対応するファイルの行番号と関数名が現れ、どの関数に除数0の操作があるかを見つけることができます.つまり、私たちが見つける理由の出所です.