ベンダー製IDE不要、16キロバイトのRISC-Vチップ
CH32V003はWCHのエントリークラスRISC-Vマイコンで、RV32EC命令セットで動くQingKe V2Aコア、16 KBのフラッシュ、2 KBのSRAMを搭載し、価格はこのサイトで既に紹介している定番の8051ボードよりも安いくらいです。STC89C52RCのような内蔵UARTブートローダは持っておらず、代わりにプログラミングとデバッグはどちらもWCH-LinkEという小さなUSBプローブ経由で行い、1本のデバッグ線でチップと通信します。
WCHがこのチップ向けに提供しているものはすべて、自社製のEclipseベースIDEであるMounRiver Studioの利用を前提としています。このページでは別の道を用意します。STC89C52RC + SDCC + Geanyのページで既に使っているのと同じ、専用IDEを使わないミニマルなワークフローです。すなわち、単体で動くGNU RISC-Vクロスコンパイラ、Makefileまたはバッチファイル、独立した2つ目のGeanyプロファイル、そして手作業で残る唯一のステップとしてWCH自身の小さな書き込みGUIを使います。
キットの中身と、見当たらないDIPソケットの謎
AVRや8051用のプログラマを使ったことがあれば、プログラマを直接差し込むZIFソケットやDIPヘッダがあるものと自然に思うかもしれません。しかしCH32V003のボードにはそのようなソケットはなく、そもそも必要ありません。 WCH自身の評価ボードマニュアルにもはっきりと書かれています。デバッグインターフェースは「ダウンロード、シミュレーションデバッグ、シングルワイヤ通信のためのものであり、SWDIOをPD1に接続するだけでよい」と。
QingKe V2Aコアが使うのは独自のシングルワイヤ・デバッグインターフェースであり、STM32系でおなじみの2線式ARM SWDプロトコルではありません。PD1という1本の信号線だけで、プログラミングとデバッグの通信をすべてまかないます。これに電源とグランドを加えれば、WCH-LinkEとボード間の接続は、ボードにすでに用意されているヘッダピンに挿す普通のジャンパ線3本だけで完成します。専用ソケットもアダプタも特別なコネクタの購入も不要です。
| WCH-LinkE 側ピン | ボード側ピン(ヘッダ P1) | 用途 |
|---|---|---|
| 3V3 | VCC | 電源。両方の電源レールの電圧が一致していると確認できていない限り、USB給電と同時に行わないこと。 |
| GND | GND | 共通グランド。 |
| SWDIO / RMS | PD1 | シングルワイヤ・デバッグ/プログラミング(SWIO)。 |
| SWCLK / TCK | 接続不要 | 未使用 — CH32V003はシングルワイヤ方式のみ。 |
「GCC」に関する補足 — なぜもう1つ別のGCCが必要なのか
GCCのマニュアルには、対応している他のあらゆるアーキテクチャと並んでRISC-V向けのオプション(-march、-mabiなど)が記載されているため、すでに手元にあるgcc.exeにそれらのフラグを渡すだけで良いように思えるかもしれません。しかし、それはできません。GCCのバイナリは、それぞれがただ1つのターゲット向けにビルドされているからです。多くの人がgfortranなどに使っているWindows向けGNUツールチェーンはx86_64-w64-mingw32をターゲットにビルドされており、生成されるのはネイティブのWindows実行ファイルです。そこにはRISC-V用のコード生成機能はそもそも含まれていません。
必要なのは、もう1つ別のGCCビルドです。コンパイラのファミリーは同じでも、--targetがまったく異なり、riscv-none-elf-gcc.exe、riscv-none-elf-objcopy.exeのように、それぞれ固有のプレフィックスの付いたバイナリとして配布されています。ファイル名にプレフィックスが付いているため、同じPATH上にあっても普通のgcc.exeやgfortran.exeと衝突することはありません。この構成ではさらに一歩進めて、PATHそのものを使わないようにしています。以下のMakefileとバッチファイルでは、RISC-Vツールチェーンの場所を明示的な変数として指定するため、既存のGNU Toolsのインストール環境には一切手を加えません。
おすすめの配布版は、無料でスタンドアロンのxPack GNU RISC-V Embedded GCC(riscv-none-elf-gcc)です。zipを展開して、そのbinフォルダのパスを控えておけば準備完了です。
WCH-LinkUtility による書き込み
コマンドライン用の書き込みツールがビルドに組み込まれるまでの間は、WCH-LinkUtilityの小さなGUIで書き込みを行います:
WCH-LinkUtility.exeを起動し、Core: RISC-V、Series: CH32V003、Addr: 0x8000000を設定する。- Erase All、Program、Verify、Reset and Runはすべてチェックしたままにする(標準的な「書き込んですぐ実行」の組み合わせ)。
- Target Fileで、下記のビルドで生成される
.hexファイルを指定する。 - 上表の通りにWCH-LinkEを配線してUSBに接続し、ステータス行に
Connected RISC-V mode WCH-Link Cnt:1と表示されることを確認する。 - 一連の操作を実行し、Result Collectに
Succeed:1 | Total:1と表示されるのを確認する。
ツールチェーン構成
STCの場合と同様、構成要素は3つです:
- xPack GNU RISC-V Embedded GCC —
riscv-none-elfをターゲットとするスタンドアロンのクロスコンパイル用GCCビルドで、Makefileまたはバッチファイルから実行する。インストーラ不要。 - Geany — SDCC/8051用にすでに設定済みのものとは別の、独立した2つ目のプロファイル(独自の
-c設定パスで起動)。Build Commandsもこのチップ用のバッチファイルに紐付けてある。 - WCH-LinkUtility — WCH自身の小さな書き込みGUI。コマンドライン版の書き込みツールに置き換わるまでの間、唯一の手作業ステップとして使用する。
ツールチェーンのフラグと、それぞれが必要な理由
CH32V003がRV32ECであるという情報だけでは、GCCに渡す設定としては不十分です:
- CSRおよび
fence.i命令 — 最近のbinutilsでは、これらは基本ISA文字列から切り離され、個別の拡張として扱われるようになりました。WCH自身のコアアクセス用コードは両方を使用するため、実際に動作するアーキテクチャ文字列は、データシートだけから想像される単純なrv32ecではなく-march=rv32ec_zicsr_zifenceiになります。 - ABI — レジスタ数を16本に削減した
E呼び出し規約に合わせて-mabi=ilp32eを指定する。 - Cライブラリのサイズ —
-lcだけを指定した場合に読み込まれるデフォルト(フル版)のnewlibは、このプロジェクト自体のコードをリンクする前の時点で、すでに16 KBのフラッシュ容量を約35 KBもオーバーしてしまいます。--specs=nano.specs(newlib-nano)を追加することで、printf対応を含むblinkサンプル全体でもtext 6.9 KB / RAM 704 Bまで収まります。
このMakefileとフラグの組み合わせは、単にドキュメントを元に書いただけでなく、実際に最初から最後まで動作確認済みです。xPackのriscv-none-elf-gcc 14.2.0でエラーなくコンパイル・リンクでき、ターゲットの16 KB/2 KBという容量制限にも十分な余裕を残して収まる、実際に動作するイメージが生成されました。
+-------------------------+
| Write main.c (GPIO, |
| pulled from WCH's own |
| GPIO_Toggle example) |
+-------------------------+
|
v
+-------------------------+
| riscv-none-elf-gcc |
| -march=rv32ec_zicsr_ |
| zifencei -mabi=ilp32e |
| --specs=nano.specs |
| -> .elf -> .hex |
+-------------------------+
|
v
+-------------------------+
| WCH-LinkUtility: |
| Erase All / Program / |
| Verify / Reset and Run |
+-------------------------+
|
v
+-------------------------+
| PD0 toggles every |
| 250 ms |
+-------------------------+
サンプルコード:GPIO点滅(Blink)
void GPIO_Toggle_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_30MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
int main(void)
{
u8 i = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
GPIO_Toggle_INIT();
while(1)
{
Delay_Ms(250);
GPIO_WriteBit(GPIOD, GPIO_Pin_0, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
}
}
CH32V003EVT.ZIP\EVT\EXAM\GPIO\GPIO_Toggleからそのまま持ってきたものです。WCHのパッケージに含まれる423個のサンプルソースファイルすべてを確認したところ、無関係な2つのSPIサンプルにわずかな非英語の句読点が紛れ込んでいた(修正済み)以外は特に問題は見つかりませんでした。このサンプルにはそうした問題もありません。WCH自身のサンプルソースはもともと英語で書かれており、ここで実際に行った作業は、それを取り巻く独自のスタンドアロン・コマンドラインビルドシステムを構築することでした。
Geany のビルドコマンド設定
STCのワークフローと同様、Geanyはビルドコマンドをシェルを介さず直接呼び出すため、バッチファイルの実行には同じくcmd /cプレフィックスが必要です:
- Label: Build
- Command:
cmd /c build_ch32v003.bat
任意設定:printf出力を見る(UARTデバッグ)
サンプルコード内のprintf呼び出しはUSART1(PD5 TX、115200 8N1)経由で出力され、実際に見るにはUSB-シリアル変換アダプタが必要です(点滅そのものはアダプタの有無に関係なく動作します)。おすすめの部品は正規のFTDI FT232RLで、CH340系のモジュールは避けます。理由は、このサイトで既に紹介しているSTC89C52RCボードのCH340用VSPドライバのときと同じです:
- FT232RLは生産終了(EOL)になっておらず、手はんだや自作基板への実装がしやすいSSOP-28パッケージで提供されており、Windowsには何年も前からネイティブのVCPドライバが同梱されています。差し込むだけでCOMポートとして認識され、手動でのドライバインストールは不要です。
- CH340系のアダプタは、自分の作業台での開発用途であれば全く問題ありません(実際、STC89C52RCボードのブートローダとの通信にもCH340を使っています)。ただしUSB-シリアル変換チップというカテゴリ全体には、Windowsのドライバ更新がクローン品や偽造品を密かにブロックしてきたという実際の前例があります。FTDI自身による悪名高い2014年のドライバ更新が偽造FT232チップに対して行ったのがまさにこれで、PL2303でも2012年頃に同様のことがありました。正規のCH340シリコンに現時点でこのリスクが当てはまるかどうかについては、ここでは断定しません。ポイントは、他人のWindowsマシンに渡す部品において、数ドルの節約のために賭けに出るべきではないということです。
- まとめると:自分用の試作にはCH340、動作を期待するエンドユーザーに渡すものにはFTDI(FT232RLまたは新しいFT230X)、という使い分けです。
これはこのチップに限った選択ではなく、このサイトのガイド全体を通じた一貫した方針です。
詳細な解説の入手
完全版ガイドでは、xPack GCCのインストール、注釈付きの完全なMakefileとbuild_ch32v003.bat、Geanyのビルドコマンドの正確な設定、スクリーンショット付きのWCH-LinkUtility操作手順、そしてこのツールチェーンの組み合わせを初めて使ったときに実際に発生するビルドエラー(zicsr/zifencei不足、フル版newlibによるフラッシュ容量オーバーなど)をもとにしたトラブルシューティングを扱っています。
この先の展開
このページでは意図的に「書き込みはGUIツール、ビルドはコマンドライン」という段階で止めています。自然な次のステップは、STC89C52RCのページでSTC-ISPをスクラッチから書いたCフラッシャーに置き換えたのと同様に、WCH-LinkE用のコマンドライン書き込みツールを用意し、make flashをmake allと同じくらい実用的なターゲットにすることです。WCH-LinkUtility自体のプロトコルは公開文書化されていませんが、コミュニティのプロジェクト(特にオープンソースのch32v003funプロジェクトに含まれるminichlink)がすでにこれをリバースエンジニアリングしてオープンソース化しており、この最後のループを閉じる価値が出てきたときの論理的な次の一手となります。