STM32の停止

短期集中コース

基本的な考え方:
リンクレジスタLR:アドレスは、実際には、最近の機能と呼んで、次の自動保存時間のサブルーチンの戻りアドレスを動員します。

クラッシュコース:


ここでは、最も注意が必要なスタックに最初のステップです:
8個のレジスタがされる順序


LRの値は、固定の内部異常発生されます

最後にスタック・ポインタを更新し、我々は最後の内部に使用、あなたは問題の時に最後のシーンを知ることができる内容に基づいて積み重ねます。

ポジショニングのクラッシュ

:簡単に言えば、アイデアはこれで
クラッシュLRレジスタを見つけ、その後、この時点で見つけるために、値LRレジスタによっては、PSPスタック、またはMSPスタックにプッシュされます。次に、スタックの内容に応じて(最後の値は、8つのレジスタのスタックにプッシュ)。臨界値内のリターンアドレススタックに押し込まれており、これが最後の時間で、それはクラッシュの位置を突き止めることができる、スタック上の最後の機能を押しました。

ダイレクトを使用して測位Keil社のデバッグ環境

実際の分析の例では:
まず、シングルチップのクラッシュを有効にコードを書く、デバッグアップを実行します。

プログラムの実行死へのNULLポインタの意図的な使用


デバッグビューを開いて、選択レジスタ、

判決は、PSPスタックを使用して、LRの値に基づいて、その後、メモリ・ウィンドウを開いて、メモリデータ0x20002FF0、最後のスタックの、すなわちコンテンツのアドレスを表示します。右を選択し、長い表示


住所、ビューを見つける0x08034a17第六、逆アセンブルウィンドウこのウィンドウでは、あなたが対応するアセンブリファイルの場所を見つけることができ、アドレスを入力して、アドレスにショーの解体を右クリックして、逆アセンブルウィンドウに逆アセンブルファイルを参照してください、そしてCに移動することができます対応する位置にある言語。

あなたがクラッシュする前の場所に移動することができるよう
な方法は、関数の呼び出し関係を調べることで、あります。2.プログラムが死んでいる場合、直接参照
クリックビューコールスタックウィンドウは、あなたがクラッシュする前に、プログラムの直接の機能を見ることができます呼び出し関係

また、これはすぐに実際には、原理は同じですが、見つけ、スタックデータを見ることにより、第一の方法は、単に手動でこのプロセスに再度行くことです。

完璧なソリューション

クラッシュの問題の実際のプロジェクトでは、その多くは再現が困難であるため、長期の過程での製品は、実際には非常に実用的ではありませんより多くの方法で、その結果、デバッグすることは困難です。したがって、我々はより便利なソリューションを必要としています。
アイデア:たびにシステムがクラッシュした、ブラックボックスであるとマイクロコントローラに相当します。私たちは、内部のフラッシュがあり、重要なレジスタを記録し、情報をスタックします。もしそうであれば問題があります。限り、我々は読み出しフラッシュ情報から保存されます再度デバッグに見えるよう。クラッシュ問題を再現するのは難しい、我々はまた、ロック位置への道を持っています。

.Sファイルを変更し
、元のコンテンツHardFault_Handlerより新しいコンテンツに置き換えられます、hard_fault_handler_cは、この機能クラッシュにジャンプする関数です。
PROC HardFault_Handler    
                 IMPORTはhard_fault_handler_c
                 TST LR、#4 
                 ITE EQ    
                 MRSEQ R0、MSP
                 MRSNE R0、PSP
                 Bのhard_fault_handler_cの               
                 ENDP

情報が格納されているクラッシュなどの領域を選択します。

#define ADDR_FLASH_SECTOR_2((U32)は0x08008000) // 、セクタ2の開始アドレス16バイト
システムクラッシュを記録する際の#define SYS_CRASH_INFO_ADDR ADDR_FLASH_SECTOR_2 //重要情報  
。1つの
2
情報を格納するための定義されたクラッシュ構造

typedefの構造体{
     unsigned int型crash_time。
     unsigned int型is_crash。
     / *情報* /登録
     unsigned long型stacked_r0を。
     unsigned long型stacked_r1。 
     unsigned long型stacked_r2。
     unsigned long型stacked_r3。   
     unsigned long型stacked_r12。 
     unsigned long型stacked_lr。 
     unsigned long型stacked_pc。 
     unsigned long型stacked_psr。 
     unsigned long型SHCSR。 
     unsigned long型MFSR。 
     unsigned long型の銀行財務格付け。  
     unsigned long型UFSR。 
     unsigned long型HFSR。 
     unsigned long型DFSR。 
     unsigned long型MMAR。 
     unsigned long型BFAR。
} System_Crash_Info。

空hard_fault_handler_c(unsigned int型* hardfault_args)
{    
   静的System_Crash_Infoのcrash_info。
   memset(&crash_info、0、はsizeof(System_Crash_Info))。
  
   crash_info.is_crash = 1。
   crash_info.crash_time =(unsigned int型)HAL_GetTick();
  
   crash_info.stacked_r0 =((unsigned long型)hardfault_args [0])。 
   crash_info.stacked_r1 =((unsigned long型)hardfault_args [1])。 
   crash_info.stacked_r2 =((unsigned long型)hardfault_args [2])。 
   crash_info.stacked_r3 =((unsigned long型)hardfault_args [3])。 
   crash_info.stacked_r12 =((unsigned long型)hardfault_args [4])。   
   crash_info.stacked_lr =((unsigned long型)hardfault_args [5])。  
   crash_info.stacked_pc =((unsigned long型)hardfault_args [6])。 
   crash_info.stacked_psr =((unsigned long型)hardfault_args [7])。

  crash_info.MFSR =(*((揮発性符号なしのchar *)(0xE000ED28))); // メモリ管理フォールトステータスレジスタ  
   crash_info.BFSR =(*((揮発性符号なしのchar *)(0xE000ED29を))); // バス障害状態登録  
   crash_info.UFSRを=(*((揮発性、符号なし short int型*)(0xE000ED2A))); // フォルト・ステータス・レジスタを使用   
   crash_info.HFSRを=(*((揮発性、符号なしロング*)(0xE000ED2C))); // ハード障害ステータスレジスタ    
   crash_info.DFSR =(*((揮発性、符号なしロング*)(0xE000ED30))); // デバッグフォールトステータスレジスタの 
   crash_info.MMARは=(*((符号なし揮発長い*)(0xE000ED34))); // ストレージ管理をアドレスレジスタ 
   crash_info.BFAR =(*((揮発性、符号なしロング*)(0xE000ED38))); // バスフォールトアドレスレジスタの 
  
   U8 RET = STMFLASH_EraseSector(STMFLASH_GetFlashSector(SYS_CRASH_INFO_ADDR ))を、
   U8 RET2 = STMFLASH_Write(SYS_CRASH_INFO_ADDR、(U32 *)(&crash_info)、(3 +はsizeof(System_Crash_Info))/ 4)。

  一方、(1); 
}

通常コードプラス

   = {0} System_Crash_Info crash_info;
   crash_info = *(System_Crash_Info *)(SYS_CRASH_INFO_ADDR);
   IF(= crash_info.is_crash 1!){
       STMFLASH_EraseSector(STMFLASH_GetFlashSector(SYS_CRASH_INFO_ADDR));
   }他{
       CT_PRINTF( "これまでのコードがクラッシュを持っている\ N-") ;
       分析における情報は、プリントアウトすることができるcrash_info //ここで見たときにケースの前に死ぬ、またはある
   }

実用的な例:

このようなコードは、デバッグを再び、あなたがクラッシュする前に状況を見ることができます。Lrが直接コードが最終的に死んでいる場所がわから、逆アセンブルコードを見てみましょう、レジスタの値を参照してください。
----------------
免責事項:この記事は元の記事CSDNブロガー「txsonfire」であり、BY-SAの著作権契約、複製、元のソースのリンクと、この文を添付してくださいCC 4.0に従ってください。 。
オリジナルリンクします。https://blog.csdn.net/qq_27087571/article/details/84580532

おすすめ

転載: www.cnblogs.com/xiumusheng/p/11576762.html