WCHのRISC-VマイコンCH32Vを公式SDKを使って、VS CodeのPlatformIOで開発する

CH32V203をPlatformIOで開発するときにやっていることをまとめたものです。

tl;dr

  • WCHのRISC-VマイコンCH32Vシリーズは、STM32のペリフェラルRISC-Vに移植したようなマイコンで、割と安価に購入できるよ。秋月でも取り扱いがあるよ。
  • 組み込みファームウェアの開発プラットフォームである PlatformIO で、CH32Vを開発できるよ。
  • PlatformIOの公式のモジュールと違ってとっかかりのサポートが薄いけど、それがわかっていれば十分使えるよ。

WCHのRISC-VマイコンCH32Vシリーズとは

WCHから出ているRISC-Vマイコンであり、ペリフェラルの機能はSTM32シリーズにとても似せてあるものです。安価に購入でき、USB機能も持っていることから、私としては積極的に使ってきています。

その中でもCH32V203C8T6は、LCSCで USD 0.62-(約90円) で購入できます。

CH32V203C8T6 WCH(Jiangsu Qin Heng) | C3001172 - LCSC Electronics

https://www.lcsc.com/product-detail/C3001172.html

Aliexpressの公式ショップでも、USD 16.15/20pcsで扱っています。

20Pcs/Lot CH32V203 RISC-V MCU 144MHz 2*USB touchkey CAN - AliExpress

https://www.aliexpress.com/item/1005004350448639.html

これの更に良いところが、USB経由で書き込める機能を持っています。BOOT1をLowにし、BOOT0をHighにして電源を投入することで、USBで書き込める状態になります。

USBでの書き込みには、公式ツールWCHISPToolを使うか、wchispを使います。私は、CLILinuxMacOSでも利用できるwchispを使っています。

github.com

このシリーズの中でも、USB機能はなくても安価なCH32V003については、開発の仕方を記事にしたりしました。

74th.hateblo.jp

CH32V203と、CH32V003を、ProMicro型にしたマイコン開発ボードを、Boothで販売しています。

74th.booth.pm

74th.booth.pm

最近は、CH32X035という安価なマイコンが、CH32V203相当の機能がありながら、USB PD Sink機能もついていてかなり挑戦的なマイコンになっていて、気になっています。

20Pcs/Lot CH32X035 RISC-V USB PD MCU - AliExpress

https://www.aliexpress.com/item/1005005657432204.html

ということで、安価にUSBを使ったマイコンが欲しいならば、良さそうな選択肢といえます。

CH32Vシリーズの公式開発環境

CH32Vシリーズの公式の開発環境は、MounRiverStudioというEclipseをベースにした開発環境です。ここにgcc、OpenOCD、公式SDKが含まれています。

www.mounriver.com

公式SDK自体は、GitHub上で公開されています。openwchというGitHubユーザで、各MCUリポジトリが作られており、その中のC++というディレクトリに、MounRiverStudioのプロジェクトファイルという形で提供されています。なお、ライセンスはApache 2.0です。

github.com

Eclipseに抵抗がなければ、こちらの環境を使うのも良いでしょう。

VS Code上で開発できるPlatformIO

VS Codeをベースとした拡張機能として、マイコンの開発環境を整備したPlatformIOというプロダクトがあります。

Your Gateway to Embedded Software Development Excellence · PlatformIO

https://platformio.org/

Arduinoと同様に、そのマイコンをビルドするためのgccや、OpenOCD等のツールを自動でダウンロードして利用できる環境を一括して用意してくれます。

PlatformIOについては、以前VS Code Conference Japan 2021で『PlatformIO で シュッと Arduino 開発を高速化しよう Speed up your Arduino development with PlatformIO!』というタイトルで発表しました。

speakerdeck.com

PlatformIOをCH32Vシリーズで使う

このPlatformIOを使ってCH32Vシリーズを開発できるようにする環境(Platform)が、コミュニティでメンテナンスされています。

github.com

このインストール方法についても公式ドキュメントが用意されています。これをみながらインストールを進めることができます。若干公式ドキュメントは、Installだけで力尽きている感じがあります。

pio-ch32v.readthedocs.io

ただし、現状x86_64のWindowsMacOSLinuxで利用できますが、ラズパイのようなarm64では利用できません。MacOSではM1 Macでも特に問題なく利用できます(OpenOCDは動かない問題はありますが)。これは、RISC-Vにカスタム拡張が入っていて(RV32IMACXW)、カスタムのgccが必要であり、x86_64のビルドしか提供されていないのがあります。(いや、gccGNUなのにコード公開していないという話もあるのですが、OpenOCDのように請求したらいただけるのでしょうけれど、なんだかなと)

実際にどう使っているか

PlatformIOでは、Platformをインストールすると、プロジェクト作成ウィザードから、目的のボードやマイコンを選べるようになります。generic CH32V203C8T6を選ぶことができます。

さらに、フレームワークを選択します。私の場合は、noneos-sdkリアルタイムOSなしのSDKを選びます。

プロジェクトを作成するとVS Codeで、プロジェクトが開かれます。

platformio.ini に、選択した設定が記述されています。

; platfromio.ini

[env:genericCH32V203C8T6]
platform = ch32v
board = genericCH32V203C8T6
framework = noneos-sdk

公式のPlatformIOが整備しているPlatformであれば、この時点でビルド可能な状態になりますが、現状そうはなっていません。src、includeディレクトリが空になっています。

ここには、MounRiverStudioののSDKにあるUserディレクトリのコードをsrcに入れる想定になっています。 ただし、システムクロックの初期設定ファイルである system_ch32v20x.c、system_ch32v20x.h は除いて、ch32v20x_conf.h、ch32v20x_it.c、ch32v20x_it.h、main.cpp のみを入れるようにしてください。

すると、ビルドが通るようになります。

書き込みをする

PlatformIOではUploadボタン、もしくはコマンド「PlatformIO: Upload」を実行するとWCH-LinkE経由で書き込みができます。

このPlatformIOのCH32Vパッケージでは、複数のアップロードツール(OpenOCD、wchisp、minichlink)に対応しています。標準では、OpenOCDになっていますが、CH32V203が持つUSB経由で書き込む機能を利用する場合は、以下のようにupload_protocol=ispを指定します。

; platformio.ini

[env:genericCH32V203C8T6]
platform = ch32v
board = genericCH32V203C8T6
framework = noneos-sdk
upload_protocol = isp

公式デバッガWCH-Linkを使う場合に、MacOSだとOpenOCDが上手く動かない問題への対応として、私の場合はminichlinkを以下のように指定しています。

; platformio.ini

[env:genericCH32V203C8T6]
platform = ch32v
board = genericCH32V203C8T6
framework = noneos-sdk
upload_protocol = minichlink

STM32の開発時との違って面倒なところ

STM32では、STM32CubeMXを使うことで、クロックの設定、ペリフェラルの初期設定は、GUIでポチポチすると行うことができます。

しかし、CH32Vシリーズにはそのような機能はないため、構造体に設定を定義して公式SDKを呼び出して初期化する必要があります。

クロックの設定だけは、system_ch32v20x.c に定義されており、ビルドフラグで設定可能です。

https://github.com/openwch/ch32v20x/blob/main/C%2B%2B/Use%20MRS%20Create%20C%2B%2B%20project-example/CH32V203C8T6%2B%2B/User/system_ch32v20x.c

/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;              /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz_HSE;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz_HSE;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz_HSE;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_96MHz_HSE;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_120MHz_HSE;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSE
uint32_t SystemCoreClock         = SYSCLK_FREQ_144MHz_HSE;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSI
uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz_HSI;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSI
uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz_HSI;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSI
uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz_HSI;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSI
uint32_t SystemCoreClock         = SYSCLK_FREQ_96MHz_HSI;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSI
uint32_t SystemCoreClock         = SYSCLK_FREQ_120MHz_HSI;        /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSI
uint32_t SystemCoreClock         = SYSCLK_FREQ_144MHz_HSI;        /* System Clock Frequency (Core Clock) */
#else
uint32_t SystemCoreClock         = HSI_VALUE;                    /* System Clock Frequency (Core Clock) */

#endif

これを設定するには、platformio.iniを書き換えます。HSE=High Speed External、HSI=High Speed Internalで、内蔵のクロックを使う場合にはHSIを指定します。指定が無いと外部クロックを検出しようとして、検出できないと遅いHSIに自動で切り替わる機能があるため、適切に設定が必要です。

; platformio.ini
build_flags =
    -D SYSCLK_FREQ_96MHz_HSI=96000000

公式SDKの使い方を学ぶ

公式SDKには、ドキュメントは存在しません。しかし、元がSTM32の古いライブラリにちなんでいることもあり、下記の本が参考になります。というか、私は各ペリフェラルを使うために必要な作法を、この書籍を読んで理解するようにしています。

10年以上前の古い本ですが、CH32Vを使うには非常に参考になります。

例えば、UART TXを標準のピン以外でも使えるようにする、Alternate Functionsという機能があります。これを利用するためにレジスタを設定していましたが、動作しませんでした。この本を読んで、Alternate Functionsを使うためにはAlternate Functionsにクロックを設定する必要があることを知りました。STM32CubeMXだったらGUIでやって、生成してくれる範囲ですね。

また、WCHのGitHubリポジトリには、公式SDKを使ったサンプルコードも、EVT/EXAMというディレクトリにコミットされています。MounRiverStudioで読み込めるようになっています。多種多様に用意されているように見えますが、意外と簡単な内容になっています。

github.com

github.com

github.com

サンプルコードをPlatformIOで使う

PlatformIOでの開発においても、サンプルコードのUserディレクトリをsrcにコピーしてこればだいたい動作すると思います(system_ch32v20x.c、system_ch32v20x.hは除いてください)。ですが、中には簡単には動作しないものもあります。

例えば、CH32V203のUSBキーボードのサンプルが用意されていますが、User内に複数のディレクトリを持って構築されています。

github.com

この階層ディレクトリを認識できず、コンパイルできません。

その場合、なんとかlibに分離したりして動くように持っていきます。PlatformIOはlibにディレクトリを作ると、一つのライブラリとして認識します。各include文から各ライブラリの依存関係をツリーにして、その順にビルドしてくれます。そのため、User/USBLIBの中にあるCONFIG、USB-Driverを、lib/USBLIB-CONFIG、lib/USBLIB-Driverというライブラリとして切り出し、src、includeから参照するようにします。慣れが必要で、わかってくるとできる感じがします。

実際にこのサンプルコードを動作するようにしたのを以下にコミットしています。

github.com

また、一部、PlatformIOのCH32Vパッケージが利便性のため改変していることもあって、それが原因で動かないことがあります。その場合には、PlatformIOのパッケージのコードを見て、原因を探っていたりします。

github.com

PlatformIOのCH32Vパッケージの他の機能

system_ch32v20x.c、system_ch32v20x.hは、パッケージで提供されますが、書き換えたかったりすることもあると思います。

この辺りを設定で有効無効を設定できるようにはなっています。

github.com

たとえば、system_ch32v20x.c、system_ch32v20x.hを含めなくするには以下のように追記します。

; platformio.ini
board_build.use_builtin_system_code=false

終わりに、公式SDKを使ってみよう

使うのにIDEの制約から抵抗があった公式SDKも、PlatformIOで使えることを解説しました。

ちょっとした単機能キーキーボードのようなものであれば、安価なCH32V203をつかっても良いのではと思っています。

是非使ってみてください。その際には、ぜひ私の作成したCH32V203のProMicro開発ボードも使ってみていただけると嬉しいです。Boothでもキットを販売していますが、KiCadファイル自体はGitHubで公開しているので、自分で発注可能です。

74th.booth.pm

github.com