NT-Logger の使い方メモ
TOPPERS/SSP で簡単にトレースログをとる方法ないかな,ということで NT-Logger というものがあるらしいので,使い方をざっと調べてみた.
CuBeatSystems - ファームウェア - Natural Tiny Logger (NT-Logger)
前提:ファイルの配置
configure スクリプトの実行
$ perl ../ssp/configure -T cq_frk_fm3_gcc -a ../ntlogger/src/target/ -U "ntl.o ntlser.o"
これで,Makefile に以下の追加が行われ,ビルド,リンク対象になる
APPL_COBJS = $(APPLNAME).o ntl.o ntlser.o APPLDIR = ../ntlogger/src/target
ここまで準備できたら,通常と同じ手順でビルドできる.
NT-Logger側のカスタマイズ
使えるようにするには src/target/ntlser.c をカスタマイズする
- int ntlser_init(void)
- NT-Loggerを使えるようにするための初期設定処理.
- 成功したら0を,失敗したら-1を返す.
- ここでログ出力の初期設定に必要な処理を書く.
- int ntlser_write(const unsigned char *buf, const int siz)
- 実際のデータ送信処理を書く.
- ntl_event_{start,end} から呼び出される.
- 既定では siz は 1 で呼び出される.
データ送信方法
- シリアルドライバを利用するのが一番自然だが,タスクコンテキスト限定となっているため,トレースの観点からは使いにくい.
- syslog は非タスクコンテキストからも利用できるが,NT-Logger の送信方法としては余計な処理が多すぎる.
- syslog は処理中の改行出力部分を省かないとホスト側で取り込んだときにうまく処理できない
syslog 使おうと思ったときにカーネルで対処が必要な部分
- syslog.c :
/* * 低レベル出力 */ if (((~syslog_lowmask_not) & LOG_MASK(prio)) != 0U) { syslog_print(p_syslog, target_fput_log); (*target_fput_log)('\n'); }
- logtask.c :
syslog_print(&syslog, logtask_putc); logtask_putc('\n');
NT-Logger を利用する側の処理
- ntl.h を include する
#include <ntl.h>
- ログ出力したい箇所にマクロを追加する
- NTL_EVENT_START(TRACK,EVENT)
- NTL_EVENT_END(TRACK,EVENT)
- 同じトラックの同じイベントの場合,入口と出口で番号をそろえること
- パケットの内部構造
- 8バイト中の最下位ビットが1のときSTART,0のときEND
- 上位4ビットがTRACK, 残り3ビットがEVENT
- マクロのパラメータ TRACK, EVENT は const int 型で,その範囲で使う
- ntlser_write の実装方法によっては呼び出し可能なコンテキストに制約が出る.
ログを取得する.
ログのキャプチャ
PCとマイコンをシリアルラインで接続し,PC側で次のコマンドを実行する.
FIFOのバッファが32なので,カウント数を増やしたい場合は設定を変える.
$ ntlcap.exe -p /dev/ttyS10 -b 115200 -o sample1.txt -c 30
ログデータからHTMLを生成
$ ntlgen.exe -i sample1.txt -o sample1.html -d sample1.ntd
ntlgen/timeline/timeline-2.1.2.zip を展開しておく
timelineディレクトリのひとつ上のディレクトリに sample1.html を置いて開く
例
NT-Loggerのカスタマイズ(ntlser.c)
#include <kernel.h> #include "ntlser.h" #include "t_syslog.h" #include "syssvc/serial.h" #include "syssvc/syslog.h" #include "target_test.h" #define NTL_ENABLED (1) int ntlser_init(void) { #if NTL_ENABLED serial_ctl_por(TASK_PORTID , IOCTL_NULL); syslog_msk_log(0, LOG_MASK(LOG_DEBUG)); return 0; #else return 0; #endif } int ntlser_write(const unsigned char *buf, const int siz) { #if NTL_ENABLED syslog(LOG_DEBUG, "%c", buf[0]); return siz; #else return siz; #endif }
sample1.cfg
// バナーとログタスクを使わない //INCLUDE("syssvc/banner.cfg"); //INCLUDE("syssvc/logtask.cfg");
sample1.c
// NT-Logger の定義 #include <ntl.h> // ログタスクを使わない /* シリアルポートのオープン */ SVC(serial_opn_por(TASK_PORTID)); SVC(serial_ctl_por(TASK_PORTID , IOCTL_CRLF)); /* ログタスクの初期化 */ // logtask_initialize(LOGTASK_PORTID); (void)ntl_init(); ||< ** 注意 NT-Logger でトレースするときは,別のシリアル出力と混ざらないようにする必要がある.