STM32CubeIDEでSemihostingを使ってprintfを使う方法を解説します。
まずは下記の画像をご覧になってください。Semihostingを使うことでデバッグコンソールにprintf出力ができるようになります。
またUARTの線も使わないので省配線にもなるというメリットもあり、デバッグ作業がとても便利になります。ただし、速度は遅く処理の邪魔になりやすい点には注意してください。
以降では具体的にSemihostingでprintfをするための方法を解説していきます。
目次
1.前提条件
今回は下記の環境を前提に話を進めます。STLinkはNUCLEO-F401REに実装されているものをそのまま使いました。
- STM32CubeIDE ver.1.00
- NUCLEO-F401RE
2.printf用のプロジェクトの準備
2-1.プロジェクトの作成
まずは適当にプロジェクトを作成してください。Device Configuration Tool(CubeMX)で特別な設定は必要ありません。
2-2.syscall.cの無効化
Semihostingを使う場合はsyscall.cが競合してしまうので無効化しておきましょう。
- プロジェクトを右クリック→Properties
- C/C++ General→Path and Symbols→Source Locationタブ
- <プロジェクト名>/Src→Filterを選択して、Edit Filterボタンからsyscall.cを追加してください
2-3.リンカの設定
続いてリンカの設定を行います。まずはライブラリの追加です。
- プロジェクトを右クリック→Properties
- C/C++ Builde→Settings→Tool Settingsタブ→MCU GCC Linker→Libraries
- Libraries (-l)の『+ボタン』から『rdimon』を追加してください
次にライブラリの有効化の設定をします。
- プロジェクトを右クリック→Properties…
- C/C++ Builde→Settings→Tool Settingsタブ→MCU GCC Linker→Miscellaneous
- Other flagsの『+ボタン』から『-specs=rdimon.specs』を追加してください
3.printf用のコードを追加
3-1.printfの初期化
printfを使う前に初期化コードを入れておく必要があります。例えば、下記のように追加します。
main.c
/* USER CODE BEGIN 0 */ extern void initialise_monitor_handles(void); /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ initialise_monitor_handles(); /* USER CODE END 1 */
UARTを使った方法とは違い、setbuf()ではないことに注意してください。
3-2.printfの追加
実際にprintfを追加してみましょう。今回は定期的に『Hello World!!』するだけのプログラムにしました。
main.c
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ printf("Hello World!!\n"); HAL_Delay(1000); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
4.デバッグの設定
このプロジェクト用のデバッグ設定を作成します。
- プロジェクトを右クリック→Debug as→STM32 MCU C/C++ Application
- デバッガタブ→デバッグプローブで『ST-Link (OpenOCD)』を選択してください
続いて、このデバッグでSemihostingを使うための設定を追加します。
- Startupタブ→Initialization Commandsに『monitor arm semihosting enable』を追加してください
5.デバッグの実行
ここまでで準備は完了です。最後にDebugボタンを押してデバッグを実行してみましょう。
デバッグコンソールに出力されましたね!お疲れ様でした!
6.おわりに
本記事ではSTM32CubeIDEでSemihostingを使ってprintfを実現する方法をご紹介しました。
Semihostingを使うことで、UARTの線を使うことなくprintfが使えるようになります。また、出力はデバッグコンソールに行われるため、使い勝手は良いと思います。ただし、通信速度はあまり速くありません。
printfの使用頻度が少なく、printfをしても処理への影響が小さい時には便利な方法かと思います。