MacからCH32V203C8T6にUSBで書き込む

# 0. はじめに

[前回の記事](https://qiita.com/nak435/items/c018bf464d29ecea3246)で、CH32V203C8T6についてのあれこれを書きましたが、どれもWindowsPCで行なったものでした。
自分のメインPCはMacなので、ビルドや書き込みもMacから行いたい。今回はそんなことをまとめました。

```shell:使用したMac
% uname -a
Darwin Mac-mini.local 22.5.0 Darwin Kernel Version 22.5.0: Thu Jun  8 22:22:19 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T8103 arm64

% sw_vers
ProductName:		macOS
ProductVersion:		13.4.1
ProductVersionExtra:	(c)
BuildVersion:		22F770820d
```


# 1. VSCode + PlatformIO

https://qiita.com/masashi_214/items/2bbd60ff88e8143e8cf0

↑こちらの記事が参考になります。

新規プロジェクト作成時の`Board`には`genericCH32V203C8T6`を選択し、[公式Lチカ](https://github.com/openwch/ch32v20x/tree/main/EVT/EXAM/GPIO/GPIO_Toggle)から`main.c`をコピー。コンパイルは問題なし。

しかし、何度やっても原因不明のエラーで書き込みができませんでしたが、HSIの設定を変えたところ書き込みができるようになりました。HSIの設定が原因とは考えられないですが、タイミングがその時だったので・・・謎です。


|書き込み失敗|![scr6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/de68f3d6-2af7-64a7-424a-6842ae4a9fc6.png)|
|-|-|
|書き込み成功|![scr7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/c93509d9-9984-896a-8a94-2aa406f76fd8.png)|





## 1.1 動作クロックの設定

[Lチカのプログラムを、外部クロックなしのMCUに書き込んだ](#補足)ところ、LEDの点滅が遅かったので、[前回の教訓](https://qiita.com/nak435/items/c018bf464d29ecea3246#lチカを試す)からHSIを設定しました。今回の`system_ch32v20x.c`のフルパスは↓こちら。
```shell:system_ch32v20x.cのフルパス
/Users/USERNAME/.platformio/packages/framework-wch-noneos-sdk/System/ch32v20x/system_ch32v20x.c
```

このファイル（`HSE`72MHzになっていた）を`HSI`に設定することで、プログラム通りの点滅速度になりました。

PlatformIOからだと、USBによる書き込みは出来ない（知らないだけかも？）ので、次の`wchisp`を試します。


#### 補足）

:::note warn
上記の「動作クロック未設定のプログラム」は、まだPlatformIOからの書き込みがエラーでできなかったので、（`firmware.bin`は出来ていたので）次の`wchisp`を使って書き込みました。

:::



# 2. wchisp

[`wchisp`](https://github.com/ch32-rs/wchisp)は、`WCHISPTool`のRust版です。

このコマンドを使うためには、Rust環境を構築する必要があります。
↓こちらの記事を参考に設定しました。

https://qiita.com/notakaos/items/9f3ee8a3f3a0caf39f7b


## 2.1 Rust環境構築

詳細は省きますが、次のコマンドを順に投入しました。

1. brew install rustup-init
2. rustup-init
3. source "$HOME/.cargo/env"

ちなみに、今回インストールされたバージョンは、次の通り。

```shell
% rustup --version
rustup 1.26.0 (2023-04-05)

% rustc --version
rustc 1.71.0 (8ede3aae2 2023-07-12)

% cargo --version
cargo 1.71.0 (cfd3bbd8f 2023-06-08) 
```

## 2.2 `wchisp`のインストール

cargoでインストールします。

```shell
% cargo install wchisp
```

バージョンを確認しました。

```shell
% wchisp --version
wchisp 0.2.2
```

## 2.3 CH32V203C8T6にUSBで書き込んでみる

- まずは、USBデバイスとして認識しているかを確認

```console
% wchisp probe
04:46:49 [INFO] Found 1 devices
04:46:49 [INFO] hint: use `wchisp info` to check chip info
Device #0: CH32V203C8T6[0x3119]
```

ちゃんと認識しているようです。

```shell
%  wchisp info
04:47:03 [INFO] Chip: CH32V203C8T6[0x3119] (Code Flash: 64KiB)
04:47:03 [INFO] Chip UID: 23-3B-5B-BC-CD-AB-4B-A3
04:47:03 [INFO] BTVER(bootloader ver): 02.60
04:47:03 [INFO] Code Flash protected: false
04:47:03 [INFO] Current config registers: a55a3fc000ff00ffffffffff
RDPR_USER: 0xC03F5AA5
  [7:0]   RDPR 0xA5 (0b10100101)
    `- Unprotected
  [16:16] IWDG_SW 0x1 (0b1)
    `- IWDG enabled by the software, and disabled by hardware
  [17:17] STOP_RST 0x1 (0b1)
    `- Disable
  [18:18] STANDBY_RST 0x1 (0b1)
    `- Disable, entering standby-mode without RST
  [23:22] SRAM_CODE_MODE 0x0 (0b0)
    `- CODE-192KB + RAM-128KB / CODE-128KB + RAM-64KB depending on the chip
DATA: 0xFF00FF00
  [7:0]   DATA0 0x0 (0b0)
  [23:16] DATA1 0x0 (0b0)
WRP: 0xFFFFFFFF
  `- Unprotected
```

- 問題なさそうなので、Hexファイルを書き込んでみます

前回、`WCHISPStudio`でビルドして作成されたhaxファイル`GPIO_Toggle.hex`を使い（WindowsからMacにコピーして）、`wchisp flash haxファイル`で書き込みします。

```shell
% wchisp flash ~/Downloads/GPIO_Toggle.hex    
04:48:07 [INFO] Chip: CH32V203C8T6[0x3119] (Code Flash: 64KiB)
04:48:07 [INFO] Chip UID: 23-3B-5B-BC-CD-AB-4B-A3
04:48:07 [INFO] BTVER(bootloader ver): 02.60
04:48:07 [INFO] Code Flash protected: false
04:48:07 [INFO] Current config registers: a55a3fc000ff00ffffffffff
RDPR_USER: 0xC03F5AA5
  [7:0]   RDPR 0xA5 (0b10100101)
    `- Unprotected
  [16:16] IWDG_SW 0x1 (0b1)
    `- IWDG enabled by the software, and disabled by hardware
  [17:17] STOP_RST 0x1 (0b1)
    `- Disable
  [18:18] STANDBY_RST 0x1 (0b1)
    `- Disable, entering standby-mode without RST
  [23:22] SRAM_CODE_MODE 0x0 (0b0)
    `- CODE-192KB + RAM-128KB / CODE-128KB + RAM-64KB depending on the chip
DATA: 0xFF00FF00
  [7:0]   DATA0 0x0 (0b0)
  [23:16] DATA1 0x0 (0b0)
WRP: 0xFFFFFFFF
  `- Unprotected
04:48:07 [INFO] Read Downloads/GPIO_Toggle.hex as IntelHex format
04:48:07 [INFO] Firmware size: 7168
04:48:07 [INFO] Erasing...
04:48:07 [INFO] Erased 8 code flash sectors
04:48:08 [INFO] Erase done
04:48:08 [INFO] Writing to code flash...
██████████████████████████████████████████████████████████████████████ 7168/716804:48:08 [INFO] Code flash 7168 bytes written
04:48:09 [INFO] Verifying...
██████████████████████████████████████████████████████████████████████ 7168/716804:48:09 [INFO] Verify OK
04:48:09 [INFO] Now reset device and skip any communication errors
04:48:09 [INFO] Device reset
```

書き込みが完了して、再びLチカが始まりました。

次に、今回`PlatformIO`でビルドした`firmware.bin`を書き込んでみます。

```shell
% wchisp flash .pio/build/genericCH32V203C8T6/firmware.bin
05:57:38 [INFO] Chip: CH32V203C8T6[0x3119] (Code Flash: 64KiB)
05:57:38 [INFO] Chip UID: 23-3B-5B-BC-CD-AB-4B-A3
05:57:38 [INFO] BTVER(bootloader ver): 02.60
05:57:38 [INFO] Code Flash protected: false
05:57:38 [INFO] Current config registers: a55a3fc000ff00ffffffffff
RDPR_USER: 0xC03F5AA5
  [7:0]   RDPR 0xA5 (0b10100101)
    `- Unprotected
  [16:16] IWDG_SW 0x1 (0b1)
    `- IWDG enabled by the software, and disabled by hardware
  [17:17] STOP_RST 0x1 (0b1)
    `- Disable
  [18:18] STANDBY_RST 0x1 (0b1)
    `- Disable, entering standby-mode without RST
  [23:22] SRAM_CODE_MODE 0x0 (0b0)
    `- CODE-192KB + RAM-128KB / CODE-128KB + RAM-64KB depending on the chip
DATA: 0xFF00FF00
  [7:0]   DATA0 0x0 (0b0)
  [23:16] DATA1 0x0 (0b0)
WRP: 0xFFFFFFFF
  `- Unprotected
05:57:38 [INFO] Read .pio/build/genericCH32V203C8T6/firmware.bin as Binary format
05:57:38 [INFO] Firmware size: 7168
05:57:38 [INFO] Erasing...
05:57:38 [INFO] Erased 8 code flash sectors
05:57:39 [INFO] Erase done
05:57:39 [INFO] Writing to code flash...
██████████████████████████████████████████████████████████████████████ 7168/716805:57:39 [INFO] Code flash 7168 bytes written
05:57:39 [INFO] Verifying...
██████████████████████████████████████████████████████████████████████ 7168/716805:57:39 [INFO] Verify OK
05:57:39 [INFO] Now reset device and skip any communication errors
05:57:39 [INFO] Device reset
%
```

こちらも書き込みが完了して、問題なくLチカが始まりました。



# 3. WCHISPTool_CMD

WCH社が公式に提供しているコマンドラインツールがあり、これのMac版が使えるはず。ダウンロードは以下のURLから行う。

[https://www.wch.cn/downloads/WCHISPTool_CMD_ZIP.html](https://www.wch.cn/downloads/WCHISPTool_CMD_ZIP.html)

<img width="200" alt="scr2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/57271a06-3150-9447-fbb6-6ae7910892b9.png" />

『下载（ダウンロード）』をクリックすると`WCHISPTool_CMD.ZIP`がダウンロードされる。


## 3.2 マニュアルを確認する

ダウンロードしたZIPを解答すると、`WCHISPTool_CMD Command Line Programming Tool Instruction.pdf`という名前のPDFファイルがある。これが英語版の取説。

p.5「4. macOS Platform」からMacの場合のコマンドの使い方の説明がある。これによると、「4.1.1 USB ダウンロード モード」「4.1.2 シリアルポート ダウンロード モード」（_ここでの「ダウンロード」は、マイコンへの「書き込み」のこと_）とあるので、USBでの書き込みを試す。



## 3.3 USB ダウンロード モード

次のコマンドで実行可能なようだが、`Config.ini`ファイルが必要らしい。

```shell:Exsample
sudo ./WCHISPTool_CMD -p 0x02131000 -c Config.ini -o program -f Target.hex
```

### 3.3.1 `Configuration file`ファイル

マニュアルのp.2に説明があった。これによると、`WCHISPStudio`の機能にある`Save UI Config`で作るとのこと。

WindowsでWCHISPStudioを起動し、メニューからSave UI Configを選択、保存ダイアログが表示されるので適当な名前をつけてconfigファイルを保存した。

![scr3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/0f5ca3cd-ea32-5001-c6e4-a989a8e5105f.png)

### 3.3.2 `WCHISPTool_CMD`コマンドの所在

`WCHISPTool_CMD`コマンドは、macOS/README.mdによると、Xcodeでビルドしてカスタマイズできると説明があるが、標準のコマンドは`macOS/bin/WCHISPTool_CMD`にある。

![scr5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/71ad6402-d7da-b802-5635-35152188e95a.png)

ただし、実行権限がないので、chmodで付与する。
```shell
% ls -l
-rw-r--r--@ 1 USERNAME  staff  406432  6  1 13:45 WCHISPTool_CMD

% chmod +x WCHISPTool_CMD

% ls -l
-rwxr-xr-x@ 1 USERNAME  staff  406432  6  1 13:45 WCHISPTool_CMD  
```
 
### 3.3.3 マニュアルの説明に従う

「4.1.1 USB ダウンロード モード」に従い、以下の操作を行う。


#### ① USBをつなぐ

> MCU が BOOT ダウンロード モードであり、USB デバイスの PID が 0x55e0 であることを確認してください

#### ② USBデバイスのロケーションIDを確認

> システムレポート -> ハードウェア -> USB でデバイスを見つけます。 USB デバイス ツリー内のロケーション ID を次の図に示します

BOOTを`1`にてマイコンボードをMacにつなぎ、システム情報で確認する。
![scr4-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/47efa82e-aa6f-0c98-9018-c707ffcd8a02.png)
上記スクショの通り、
- 製品ID：0x55e0
- 場所ID：0x00133000

を確認した。

#### ③ ダウンロード命令の実行

configファイルとhexファイルがあるディレクトリに移動して、以下のコマンドを投入。

```shell
% sudo ./WCHISPTool_CMD/macOS/bin/WCHISPTool_CMD -p 0x00133000 -c CH32V203_233B5BBCCDAB4BA3.ini -o program -f GPIO_Toggle.hex 
Password:

=====ISP_Command_Tool=====

TOOL VERSION:  V3.50

p:0x00133000
b:0
v:0
c:CH32V203_233B5BBCCDAB4BA3.ini
o:0
f:GPIO_Toggle.hex

{"Device":0x00133000", "Status":"Fail", "Code":6, "Message":"Fail to find any valid isp device"}

```

`Fail to find any valid isp device`（デバイスが見つからない）エラーとなった。

マイコンをリセット後、再度、Bootモードにてコマンドを投入したが、同じエラーである。
念のため、Xcodeでビルドしたコマンドを使用してみたが、結果は同じ。


シリアル接続で試すも、同じ結果。

```shell
% sudo ./WCHISPTool_CMD/macOS/bin/WCHISPTool_CMD -p /dev/cu.usbmodem8D568F0612342 -b 115200 -c CH32V203_233B5BBCCDAB4BA3.ini -o program -v boot -f GPIO_Toggle.hex

=====ISP_Command_Tool=====

TOOL VERSION:  V3.50

p:/dev/cu.usbmodem8D568F0612342
b:115200
v:1
c:CH32V203_233B5BBCCDAB4BA3.ini
o:0
f:GPIO_Toggle.hex

{"Device":/dev/cu.usbmodem8D568F0612342", "Status":"Fail", "Code":6, "Message":"Fail to find any valid isp device"}
```

Xcodeでトレースすると、次の関数がエラーとなっている。
```c++
iDevCnt = WCH55x_EnumDevices(AfxDnDev, DEV_MAX_NUMBER, &BtChipSeries, &BtChipType, &IsPreBTV230);
```

`WCH55x_EnumDevices`は受け取るものだけで、特に渡しているパラメタが無いので、環境が疑われる。

Xcodeのプロジェクトで`App Sandbox`に`USB`を追加してみると、`_libsecinit_appsandbox.cold`で例が発生・・・

`App Sandbox`周りが怪しいので、後日、もう少し調べてみます。





# 4. おわりに

`VSCode + PlatformIO`で、ビルドとリシアルによる書き込みができました。また、`WCHISPTool_CMD`コマンドはまだ使えませんが、`wchisp`コマンドでUSBでの書き込みができたので、当初の目的は達成できました。

Rust環境も作れたので、RISK-Vコアだし、今後、Rustで何かやってみたいと思います。

#### 以上