LPCXpressoでITM printf

前回(LPCXpressoでセミホスティング - 滴了庵日録)はセミホスティングによるprintfデバッグについて説明した。しかしセミホスティングは速度がものすごく遅く、またデバッガを接続していないときにはprintf関数でスタックしてしまうという問題があった。そこで今回はセミホスティングより高速なITM printfについて説明する。

ITM printfとは?

ITM printfは、SWDのトレース機能を利用してprintf関数の出力をSWO端子からデバッガに送る。セミホスティングよりも桁違いに高速であり、またデバッガを接続していないときにもスタックが発生しない。

いっぽうで、セミホスティングはSWCLKとSWDIOの接続のみで利用できるが、ITM printfはSWOの接続が必要となる。また、ITM printfはCortex-M3以上で利用できるが、Cortex-M0/M0+は対応していない。

LPC XpressoでITM printfの設定

(1) 標準入出力をUARTへリダイレクトしない

ボードライブラリのプロジェクトのboard.c内の #include "retarget.h" をコメントアウトする。

#include <string.h>
#include "board.h"
// #include "retarget.h"
(2) 標準入出力をITMへリダイレクトする

アプリケーションのプロジェクトに下記のretarget_itm.cを追加する。

このソースファイルはNXPのサポートサイトで公開されていたものだが、同社のサイトはしばしばリンク切れになるので、ここに退避した。ライセンス的に再配布はOKのはず。

(3) nohostのライブラリを選択する

アプリケーションのプロジェクトの[Properties] > [C/C++ Build] > [Settings] > [Tools Settings]タブ > [MCU Linker] > [Managed Linker Script] で Redlib(nohost) を選択する。

(4) デバッグを開始してSWOの設定

まずプロジェクトをビルドしてデバッグを開始する。[SWO Trace Config]タブ (表示されていなければ、[Window] > [Show View] > [Other] > [SWO Trace] から選択して表示させる) で [ITM Console] の [+] ボタンをクリックし、ターゲットのクロック周波数を設定する。

f:id:licheng:20201027114757p:plain:w640

以上の設定で、printf関数の出力がLPCXpresso IDE[SWO ITM Console]に表示される。

f:id:licheng:20201027115003p:plain

LPCXpressoでセミホスティング

セミホスティングとは?

ARMマイコンでprintfデバッグをする場合、デバッグ用UART等に出力するのではなくデバッガのコンソールに出力する仕組み。標準出力だけでなく標準入力にも対応する。ターゲットにデバッグ用UARTが無い場合や、ソフトウェアを用意できてないときに有用。ただし速度がものすごく遅いのが難点。またデバッガが接続されていないときはprintf関数でスタックしてしまう。

LPCXpressoでセミホスティングの設定

(1) 標準入出力をUARTへリダイレクトしない

ボードライブラリのプロジェクトのboard.c内の #include "retarget.h" をコメントアウトする。

#include <string.h>
#include "board.h"
// #include "retarget.h"

または、ボードライブラリのプロジェクトの[Properties] > [C/C++ Build] > [Settings] > [Tools Settings]タブ > [MCU Compiler] > [Symbols] (MCUXpressoでは[Preprocessor])で DEBUG_SEMIHOSTING を定義してもよいが、めんどくさいので上記の方法でよかろう。

(2) セミホスティングのライブラリを選択する

アプリケーションのプロジェクトの[Properties] > [C/C++ Build] > [Settings] > [Tools Settings]タブ > [MCU Linker] > [Managed Linker Script] で Redlib(semihost) を選択する。

f:id:licheng:20201026203433p:plain:w600

以上の設定で、printf関数の出力がLPCXpresso IDEのConsoleに表示される。

f:id:licheng:20201027121247p:plain

関連用語

  • ITM(Instrument Trace Macrocell) : セミホスティングよりは高速にprintfを出力できるらしい。ただし、SWOピンの接続が必要なのと、Cortex-M0/M0+は非対応 (Cortex-M3以上が対応)らしい。
  • SWO(Serial Wire Output) : SWDインターフェースでSWCLKとSWDIO以外のもう一つのピン。
  • RTT(Real Time Transfer) : セミホスティングやITMより滅茶苦茶高速らしい。J-Linkでのみ使えるらしい。

いまさらLPC-Link2について

LPC-Link2について

LPC-Link2は、ファームウェアを書き換えることでCMSIS-DAP / J-Link / Redlink の3種類のデバッグプローブになれるボードです。LPC4370マイコンボードとしても使えます。

f:id:licheng:20130517110735j:plain:w400

J-linkとして用いる場合、ターゲットのデバイスはNXP社のマイコンに限定されます。CMSIS-DAPとして用いる場合はこのような制約は無いようです。

Redlinkというのは、かつてLPCXpresso IDEで用いられていたものです。しかしLPCXpresso v7.8.0以降はRedlinkにかわってCMSIS-DAPがデフォルトのデバッグプローブとなり、さらにLPCXpresso v8.1.0以降はRedlinkはサポートされなくなりました。そのため、現在ではRedlinkを用いる機会はほぼ無いと思われます。

LPC-Link2の使い方

  • JP1 : ショートだとSPI Flashからブートする。オープンだとUSBからブートする。
  • JP2 : ショートだとLPC-Link2からターゲットへ給電する。オープンだと給電しない。

f:id:licheng:20201014212536p:plain:w400

LPCXpresso IDEでの用いる場合、JP1をオープンにしてPCに接続します。デバッグ開始時にLPCXpresso IDEからLPC-LinkにCMSIS-DAPファームウェアがロードされます。これはLinkServerとよばれる仕組みで、もともとはRedlinkで用いられていたものです。CMSIS-DAPはSWD / JTAGのどちらにも対応します。MCUXpressoの場合も同様です。

他のIDEで用いる場合、後述の方法でCMSIS-DAPないしJ-LinkのファームをLPC-Link2に書き込んだ後、JP1をショートしてPCに接続すると各々のデバッグプローブとして機能します。この方法でCMSIS-DAPデバッガとしてLPCXpresso IDEで用いることもできます。MCUXpressoの場合はJ-Linkにも対応します。

LPC-Link2のファームウェアの書き込み方

  1. LPCScryptをダウンロードし、インストールします。
  2. Windowsの場合はドライバもインストールします。これはLPC Xpresso IDEをインストールする際にはいっしょにインストールされます。
  3. LPC-LINK2のJP1をオープンにしてPCに接続します。
  4. LPCScryptをインストールしたフォルダの下のscriptsフォルダ内にあるスクリプト(バッチ)を実行します。
  5. JP1をショートしてPCに接続すると、各々のデバッガプロープになります。

CMSIS-DAPファームウェアを書き込んだときのコンソール画面は次のようになります。LPCScryptの使い方の詳細については、インストールしたフォルダの下のdocsフォルダにドキュメントがあります。

f:id:licheng:20201015090457p:plain

メモ:LPC18xxマイコンのデバッグモード、ブートモード

デバッグモード

  • DBGENピンがHIGHのときSWDモード、LOWのときJTAGモード。
  • DBGENピンは内部で50kΩでプルアップされている。

ブートモード (内蔵Flashを持つ型番の場合)

  • 通常は内蔵Flashからブートする。
  • UART, NOR Flash, SPI Flash, Quad SPI Flash, USBからのブートにも対応。
  • リセット時にP2_7がLOWの場合、OTPのBOOT_SRCビットの値によってブートモードが決まる。
  • OTPがプログラムされていないか、BOOT_SRCビットが全てゼロなら、P2_9, P2_8, P1_2, P1_1の値でブートモードが決まる。

参照

詳細は以下のドキュメントを参照。

  • UM10430 LPC18xx ARM Cortex-M3 microcontroller User manual
  • LPC185x/3x/2x/1x 32-bit ARM Cortex-M3 MCU Product data sheet

LPCマイコン各種のIO設定について

LPCマイコンはローエンドからハイエンドまで規模がさまざまなので、基本的なIO設定もファミリによって微妙に異なる。以下、簡単にメモ。

※ すでにLPC8xxとLPC55xx以外はNXPの主流ラインナップから外れており、LPCXpressoのような安価なボードも入手性が悪くなってきています。当方はコンサバ指向なのでひきつづきやってますが。

LPC8xx

  • ピン数が少ないので、ピン機能はSWM(Switch Matrix)で自由に割り当てられる
  • プルアップやオープンドレインなどのピンモードはIOCONで設定する。
  • ピン名とGPIO名は一致する。(PIO0_y)
  • ただし、IOCONでは IOCON_PIOy のような定数でピンを指定する
  // LPCOpenの設定API
  Chip_SWM_MovablePinAssign(SWM_ピン機能, y);
  Chip_IOCON_PinMuxSet(LPC_IOCON, IOCON_PIOy, ピンモード);
    // ↑はピンモードの定数が用意されてないので代わりに下記を使用
    Chip_IOCON_PinSetMode(LPC_IOCON, IOCON_PIOy, PIN_MODE_ピンモード);
    Chip_IOCON_PinSetOpenDrainMode(LPC_IOCON, IOCON_PIOy, true/false);
  Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, 0, y);
  Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, y);

LPC11xx

  • ピン機能・ピンモードともIOCONで設定する。
  • ピン名とGPIO名は一致する。(PIOx_y)
  • ただし、IOCONでは IOCON_PIOx_y のような定数でピンを指定する
  // LPCOpenの設定API
  Chip_IOCON_PinMuxSet(LPC_IOCON, IOCON_PIOx_y, ピンモード | ピン機能);
  Chip_GPIO_SetPinDIRInput(LPC_GPIO, x, y);
  Chip_GPIO_SetPinDIROutput(LPC_GPIO, x, y);

LPC15xx

  • ピン機能・ピンモードともIOCONで設定する。
  • ピン名とGPIO名は一致する。(PIOx_y)
  // LPCOpenの設定API
  Chip_IOCON_PinMuxSet(LPC_IOCON, x, y, ピンモード | ピン機能);
  Chip_GPIO_SetPinDIRInput(LPC_GPIO, x, y);
  Chip_GPIO_SetPinDIROutput(LPC_GPIO, x, y);

LPC18xx

  • ピン数とペリフェラル機能が非常に多い
  • ピン名(Px_y)とGPIO名(GPIOz[w])がまったく一致しない
  • ピン機能・ピンモードはIOCONではなくSCUで設定する
  • 入力に設定する場合にピンモードに SCU_MODE_INBUFF_EN を必ず指定する
  // LPCOpenの設定API
  Chip_SCU_PinMuxSet(x, y, ピンモード | ピン機能);
  Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, z, w);
  Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, z, w);

新しいMS IMEのカスタマイズ

以前、MS IMEで[無変換]/[変換]キーの機能をカスタマイズする方法を書いた。

lipoyang.hatenablog.com

ところが、May 2020 Updateの新しいMS IMEでは設定がかなりシンプルなUIに変更されている。従来の「プロパティ」にかわって、新しいMS IMEでは「設定」というダイアログがある。

f:id:licheng:20200929233435p:plain

[無変換]/[変換]キーの機能をカスタマイズする場合、この「設定」から「キーとタッチのカスタマイズ」に進み、「キーの割り当て」で「各キーに好みの機能を割り当てる」をオンにして、「無変換キー」と「変換キー」の設定を変更すればよい。

f:id:licheng:20200929233922p:plain