デバッグ 256

デバッグ

mbed は JTAG などのデバッグに使えるインターフェースが引き出されていない。

そのため、シリアルへ printf() で文字を表示してデバッグすることになる。

プログラム書込み用のUSB接続で、シリアル(COMポート、ttys)が使える。
参照 USBシリアル入出力 (by Tedd OKANO)

ここでは、どうしても暴走して動かなくなるプログラムのデバッグ方法を書き記す。

Information

最近はmbedチップが CMSIS DAP というインターフェースに対応するようになり、対応しているデバッガからデバッグできるようになった。

当然ながらブラウザとリンクするわけないので、クラウドコンパイラからは使えない。

printf()デバッグ

プログラムの行間に printf を入れて、プログラムの流れを見る。

printf

    :
  printf("A\r\n");
  x = function(value);
  printf("B\r\n");
  if (x == 0) {
    printf("C\r\n");
      :
  } else {
    printf("D\r\n");
      :
  }
  printf("E\r\n");
    :

便利な使い方

デバッグが終了した時に printf を削除するのはめんどくさい。 そんな時は #define を活用する。

こんなヘッダファイルを用意しておき

dbg.h

#ifdef DEBUG
#define DBG(...) printf("" __VA_ARGS__)
#else
#define DBG(...)
#endif

プログラムに include する。

デバッグ表示のON/OFFは #define DEBUG / #undef DEBUG で切り替える。

main.cpp

#define DEBUG
#include "dbg.h"
#include "mbed.h"

int main () {
    :
  DBG("A\r\n");
  x = function(value);
  DBG("B\r\n");
  if (x == 0) {
    DBG("C\r\n");
      :
  } else {
    DBG("D\r\n");
      :
  }
  DBG("E\r\n");
    :    

勝手にLEDがチカチカする

それはこんなふうですか?

/media/uploads/samux/m3_gif.gif

内部でエラーが起きたことを表している。
例えば、I2SやSPIなどの機能のないピンを使って、初期化しようとしたときなどに起こる。

PCシリアルに何かメッセージが出力されているかもしれない。(Serialが未初期化の時は9600bps)

error("文字列") を呼ぶか、main() を return -1 で抜けて、わざとこの状態にすることもできる。

参考:Debugging

メモリーあふれ

巨大な変数を定義したために、メモリー(RAM)あふれを起こしている場合、プログラムが動き出す前にFalut割込みが発生してしまう。

静的変数の場合は Hard Fault にて検出する。

HardFault

extern "C"
void HardFault_Handler() {
    printf("Hard Fault!\r\n");
    while(1);
}

動的変数やクラスの場合は set_new_handler にて検出する。

set_new_handler

#include "mbed.h"
#include <new>

void no_memory () {
    printf("panic: can't allocate to memory!\r\n");
    while(1);
}

int main() {
    set_new_handler(no_memory); // new handler function

    :

その他のFault

初期状態では、Bus Fault、Memory Manage Fault、Usage Fault の全てがHard Fault割込みを発生させる。

個別に割込みベクタを定義し、フラグをセットすることにより、それぞれ個別の割込みルーチンで処理できる。

Fault

extern "C" {

void HardFault_Handler() {
    printf("Hard Fault!\r\n");
    while(1);
}

// メモリ管理
void MemManage_Handler() {
    printf("MemManage Fault!\n");
    while(1);
}

// プリフェチ、メモリアクセス異常
void BusFault_Handler() {
    printf("BusFault Fault!\r\n");
    while(1);
}

// 未定義命令 or 異常状態
void UsageFault_Handler() {
    printf("Usage Fault!\r\n");
    while(1);
}

} // extern "C"

int main() {
    SCB->SHCSR |= (1<<18)|(1<<17)|(1<<16); // fault handler enable

    :

戻る


Report

1 comment on デバッグ 256:

22 Aug 2013

すみません (>_<; ページ冒頭でリンク頂いている「シリアル入出力」のページヘのリンクですが,旧HTMLからWikiへのフォーマット変換をしたら元のURLでは保存できなくなてしまいました. 新しいリンクはコチラですので,もしまだこの私のページに意味があればリンクの変更をお願いします. http://mbed.org/users/okano/notebook/personal_memo--usb-serial_IO/ お手数をおかけします.

Please log in to post comments.