2023年3月5日日曜日

STM32ArduinoでCDCを利用しながらFreeRTOSとSTLinkのシリアル出力を利用


背景

2週間前にSTM32のnucleoの2番目のUSBポート(CDC: 仮想COMポート)でシリアル通信する方法を把握しました。
CDCを利用しつつFreeRTOSの組み合わせとSTLinkのシリアルポートでの通信を試したところ、どちらも標準設定では動かずひと手間必要でした。
備忘録を兼ねて対応内容を記事に残します。

使ったもの

  • stm32h753zi-nucleo
  • microB usbケーブル2本
  • プログラムを書き込むPC
    Ubuntu22.04にVSCodeとPlatformIOをインストールした環境を利用しました

STLinkのシリアル通信とCDCを同時利用: STLinkのシリアルの通信ピンを指定

CDCを使わない場合はSerialがSTLink経由のシリアル通信可能なインスタンスとして定義されますが、CDCを使う場合はピンが割り当てられない状態になるためライブラリ外で割り当て処理が必要です。

STM32H753ZI-nucleo(回路型番:UM2407 データシート参照)の場合、STLinkのシリアルポートにはPD8とPD93が割り当てられています。


STM32H753ZIT6におけるPD8とPD9はUSART3のTXとRXとして利用可能なピンです。(stm32h753zi.pdf参照


プログラムとしてはvariant_NUCLEO_H743ZI.hでSERIAL_UART_INSTANCEが3に指定されつつ利用するピンがPIN_SERIALがPD9とPD8で定義されます。
CDCを利用しない場合はSERIAL_UART_INSTANCEの値にしたがってWSerial.hでSerial3がSerialとして定義されます。
ピンの指定はSerialとして定義されたHardwareSerialインスタンスのコンストラクタで行われます。

CDCを有効にした場合、SerialはHardwareSerialではなくUSBSerailとして定義されるため、上記のピン指定処理が動きません。

新たにHardwareSerialを定義しても良いですが、CDC有効時もSerial3、PIN_SERIAL_RX、PIN_SERIAL_TXは定義されているので、この記事ではそれらを利用して通信する例を紹介します。

CDCを利用しつつSerial3にRXとTXを割り当てる下記のプログラムで、CDCとSTLinkでの同時通信が可能です。
platformio.ini
[env:nucleo_h743zi]
platform = ststm32
board = nucleo_h743zi
board_build.mcu = stm32h753zit6
framework = arduino
build_flags =
-D USBCON
-D USBD_USE_CDC
src/main.cpp
#include <Arduino.h>

void setup() {
Serial3.setRx(PIN_SERIAL_RX);
Serial3.setTx(PIN_SERIAL_TX);
Serial3.begin(115200);
Serial.begin(115200);
}

void loop() {
Serial3.println("hello from stlink at " + String(millis()));
Serial.println("hello from CDC at " + String(millis()));
delay(1000);
}

では動かしてみます。
上記のプログラムを書き込み、STLinkとCDCポートそれぞれの出力を確認します。
STLinkの方はbeginで指定した115200bpsで開く必要がありますが、CDCの方は自動で速度を合わせてくれます。
pio device monitor -b 115200 -p /dev/ttyACM0
hello from stlink at 176012
hello from stlink at 177012

pio device monitor -p /dev/ttyACM1
hello from CDC at 175012
hello from CDC at 176012

どちらからも出力を確認できました。

古い情報:  FreeRTOSとCDC(Virtual COM)を同時利用: マクロconfigMEMMANG_HEAP_NBを3に設定

2024.03.19時点のArduino_Core_STM32とFreeRTOSの組み合わせでは、この設定は無くても動作しました。(むしろ、あると時々動作停止しました。)
今となっては不要な情報ですが、関連情報の備忘録として残しておきます。

下記のようにbuild flagでconfigMEMMANG_HEAP_NBを3以上に設定するとFreeRTOSとCDCを同時に利用できます。
platformio.ini
lib_deps =
STM32duino FreeRTOS
build_flags =
-D USBCON
-D USBD_USE_CDC
-D configMEMMANG_HEAP_NB=3 ; required to use usb con and freeRTOS on stm32

configMEMMANG_HEAPはFreeRTOSで利用される変数で、標準は-1で定義されます。
CDCとheapの割り当てで競合するのだと思いますが、具体的にどの実装が問題になるのかまでは追えませんでした。

とりあえずFreeRTOSが利用するheapの番号を3にすれば動くと分かりました。

参考: HID will not work if STM32FreeRTOS.h is included. #16

終わり

CDCで出力しつつ、FreeRTOSを利用したり、STLinkでのシリアル出力を利用する方法を把握しました。
不具合に遭遇した時は戸惑いましたが、解決方法が分かって良かったです。

参考

2週間前の記事です。
STM32のnucleoの2番目のUSBポートは10Mbps(1MByte/s)弱でシリアル通信できる

CDCとFreeRTOSを共存させる設定を把握したgithubのissueです。
HID will not work if STM32FreeRTOS.h is included. #16

変更履歴

2024.03.19
configMEMMANG_HEAP_NBを3にする設定がなくても動くと分かったので、今は使わない古い情報と分かる注意文を追加しました。

0 件のコメント :