SWD (Serial Wire Debug) やっててさらにトレース(printfみたいなこと)も行いたいことは多い。別途 USART を繋げて printf() デバッグしても良いが、正直めんどうくさい。
ITM とは?
Instrument Trace Macrocell の略で Cortex-M の Arm CoreSight (MCU 側のデバッグ機能) に含まれるトレース機能。トレース機能は雑にいうと printf() みたいなもので、実際 printf() を中継するのに使うこともできる。
SWO (Serial Wire Output) というトレース用のピンを使う。
semihosting との違い
セミホスティングとはが詳しいが、セミホスティングはホスト側でシステムコールの一部をホストするという仕組みで、bkpt (ブレークポイント) などで発生する例外を ARM プロセッサのデバッガインターフェイスが拾ってホスト側に中継する。
仕組み的にビルド・トレース環境とかを作るのがめんどい。
ITM の Pros. Cons.
- ↑ 特殊なビルドが不要
- ↓ 余計な配線が1つ必要 (SWO)
semihosting の Pros. Cons.
中華 ST-Link V2 の改造
よく売ってる安い ST-Link V2 には SWO 用のピンが出ていない。機能自体はあるので配線してやる。5V と 3.3V はピンが2本ずつ重複しているので、片方を潰せば特にデメリットなく拡張できる。
↑ こういう感じでケース(カバー?)は外せる。USB コネクタ側にスライドする
↑ 31ピンが SWO 用のピン。一応親切?なのか若干配線が伸びてるので、カッターでレジストを剥してはんだづけするのが楽
↑ 今回は 5V のピンを1つ配線をカットして使うことにした。22Ωを介して外に出す。UEW 線でやってる。ちゃんとテスターで導通チェックしましょう
配線
MCU 側は SYS_JTDO_SWO の機能があるピンを設定する。STM32F401 の場合は PB3。Alternate function を設定しなければデフォルトで SWO のはず?モノによるかも
コード側
ここでは printf() を中継する前提で _write() を適当な位置に定義する
int _write(int file, char *ptr, int len) {
for(int i = 0; i < len; i++) {
ITM_SendChar(*ptr++);
}
return len;
}
あとは printf() を使うところで以下のように stdio.h を include すれば良い
#include <stdio.h>
VSCode + Cortex-Debug の設定
Cortex-Debug は ITM のデコードをサポートしていて以下のような設定をできる。
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "OpenOCD-Debug",
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"executable": "build/stm32f401-usbserial-host.elf",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"postLaunchCommands": [
"monitor reset init",
"monitor itm port 0 on"
],
"cwd": "${workspaceRoot}",
"svdFile": "STM32F4x1.svd",
"device": "stm32f4x",
"preLaunchTask": "build",
"swoConfig": {
"cpuFrequency": 64000000,
"source": "probe",
"swoFrequency": 1000000,
"enabled": true,
"decoders": [
{
"port": 0,
"label": "ITM",
"type": "console"
}
]
}
}
]
}
これで、VSCode の「出力」タブのドロップダウン「SWO: ITM [port: 0, type: console]」に ITM 経由のログが出るようになる。type: console の場合 "\n" 区切りであることを前提にタイムスタンプを追加してくれる。
postLaunchCommands
の monitor reset init
はないほうがいいかも。cpuFrequency
は HCLK にあわせるのが良い。
- トップ
-
tech
-
Cortex-M の SWD/ITM を使った UART を使わない printf() デバッグ