CH32V003J4M6マイコンとch32v003funを使ってみる
前回Platformio+RTOS環境でch32v203向けのプログラム環境を確認しました。
今回はch32v003について開発環境の確認してみます。ch32v003はRTOSサポートしてないので、直接レジスタを設定するOSレスな開発になります。その場合、ch32v003funというGithubリポジトリで開発環境とサンプルが一番揃っている感じなので、使い方を試してみました。
利用するマイコンは、8ピンのCH32V003J4M6です。ほかにWCH-LinkEが必要になります。
Github
開発環境のインストール
Win環境はいろいろ試してみようと思いましたが断念。WSLであればビルドはできるけど、USBに接続してアップロードするところについて、ツールを使わないと接続できない不便さで却下。結局Ubuntu22.04稼働するPCで作業しています。(ラズパイとかでも良いので、Ubuntu環境で作業できると捗ると思います。)
Install方法は以下を参考
自分の環境だと依存関係の問題が発生してました。
> sudo apt-get install build-essential libnewlib-dev gcc-riscv64-unknown-elf libusb-1.0-0-dev libudev-dev
:
以下のパッケージには満たせない依存関係があります:
libudev-dev : 依存: libudev1 (= 249.11-0ubuntu3.7) しかし、249.11-0ubuntu3.9 はインストールされようとしています
E: 問題を解決することができません。壊れた変更禁止パッケージがあります。
libudev-dev
が249.11-0ubuntu3.9
に対応した新しいパッケージがリポジトリになさそうです。sources.list
には以下の2つのリポジトリが指定されています。
deb http://jp.archive.ubuntu.com/ubuntu/ jammy main restricted
deb http://jp.archive.ubuntu.com/ubuntu/ jammy-security main restricted
いずれ上記リポジトリに反映されると思いますが、とりあえずもう一つ以下のリポジトリを追加したら。依存関係パスしてインストールできました。
deb http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse
> sudo apt update
> sudo apt-get install build-essential libnewlib-dev gcc-riscv64-unknown-elf libusb-1.0-0-dev libudev-dev
WCH-LinkEのセットアップ
モジュールのアップロードやデバッグでWCH-LinkEが必要になります。
WCH-LinkUtilityを使って1回だけRISC-Vモードに変更する必要がありますが割愛。
注意点として
- 必ず最新版のツールをDLして使う。
- 1回はファームウェアのアップデートしないといけないと思う。失敗するとゴミになるらしい。。(もう1個購入してファームウェアを書き換えることはできる)
UbuntuでWCH-LinkE使う場合、ひょっとするとパーミッションがなくて使えない可能性がある。毎回chmodでパーミッション変更はメンドクサイので以下手順で自動化してます。
WCH-LinkEをPCに刺したら、lsusb
でIDを確認する。
> lsusb
Bus 003 Device 005: ID 1a86:8010 QinHeng Electronics WCH-Link
上記デバイスが接続されたら、plugdev
グループのパーミッションを指定する。
cd /etc/udev/rules.d
sudo vi 10-wch-linke.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="8010", MODE="0666", GROUP="plugdev"
plugdev
グループに開発ユーザを追加。マシン再起動。
sudo gpasswd -a $USER plugdev
sudo chmod a+r /etc/udev/rules.d/10-wch-linke.rules
sudo reboot
CH32V003J4M6でBlinkサンプル
CH32V003のリファレンスマニュアル
ch32v003-01.png
ch32v003-02.png
サンプルのexamples/blink
を最小限まで減らしたコードです。5番ピンのPC1を出力にしてLEDを光らせてみる。
Makefile
all : flash
TARGET:=blink
include ../../ch32v003fun/ch32v003fun.mk
flash : cv_flash
clean : cv_clean
blink.c
#include "ch32v003fun.h"
#include <stdio.h>
int main()
{
SystemInit();
// Enable GPIOs GPIOC
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC;
// 0000000011110000を反転してクリア
GPIOC->CFGLR &= ~(0xf<<(4*1));
// 10MHz, Output Push Pull
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*1);
while(1)
{
// Turn on PC1
GPIOC->BSHR = (1<<1);
Delay_Ms( 250 );
// Turn off PC1
GPIOC->BSHR = (1<<(16+1));
Delay_Ms( 250 );
}
}
基本的にch32v003funはレジスタを直接設定しながら開発するスタイルで、隠蔽化されてないです。GPIOの設定とON/OFFする方法をリファレンス見ながら確認してみます。
まずSystemInit()
を最初に1回だけコールしています。お約束コードです。
#include "ch32v003fun.h"
#include <stdio.h>
int main()
{
SystemInit();
:
}
3.3.5.2 AHB Bus Peripheral Clock (HCLK)
AHB、APB1、APB2のバスでグループ化されていて、GPIOCはAPB2にカテゴリ化されているっぽい。このAPB2を有効化します。デフォルトでは、省エネのため無効化されていているみたいです。
// Enable GPIOs GPIOC
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC;
7.3.1.1 Port Configuration Register Low (GPIOx_CFGLR) (x=A/C/D)
PC1のGPIO設定
// 0000000011110000を反転してクリア
GPIOC->CFGLR &= ~(0xf<<(4*1));
// 10MHz, Output Push Pull
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*1);
リファレンスを見ると、クロックの設定とモードを指定する必要がある。
7.3.1.4 Port Reset/Set Register (GPIOx_BSHR) (x=A/C/D)
GPIOピンのON/OFF設定
// Turn on PC1
GPIOC->BSHR = (1<<1);
// Turn off PC1
GPIOC->BSHR = (1<<(16+1));
上位16ビットがOFF、下位16ビットがONと読み取れる。
ビルド&アップロード
ch32v003funはmake
するとコンパイルとアップロードをまとめてやってくれる仕組みですので、ハードウェア側のセットアップをあらかじめしておきます。(してなくてもコンパイルまではできると思いますが)
このあたりは、Makefileのカスタマイズとかすると、自分好みにできるとは思いますが、まだ理解が追い付いてないです。
CH32V003J4M6 | 回路 |
---|---|
VSS | WCH-LinkEのGND |
VDD | WCH-LinkEの3V3, GND間に1uFのコンデンサ |
PC1 | 10kΩ=>LED=>GND |
SWIO | WCH-LinkEのSWDIO |
なし | WCH-LinkEのSWCLK |
> make
riscv64-unknown-elf-gcc -o blink.elf ../../ch32v003fun/ch32v003fun.c blink.c -g -Os -flto -ffunction-sections -static-libgcc -march=rv32ec -mabi=ilp32e -I/usr/include/newlib -I../../ch32v003fun/../extralibs -I../../ch32v003fun -nostdlib -I. -Wall -T ../../ch32v003fun/ch32v003fun.ld -Wl,--gc-sections -L../../ch32v003fun/../misc -lgcc
riscv64-unknown-elf-size blink.elf
text data bss dec hex filename
460 0 0 460 1cc blink.elf
riscv64-unknown-elf-objdump -S blink.elf > blink.lst
riscv64-unknown-elf-objdump -t blink.elf > blink.map
riscv64-unknown-elf-objcopy -O binary blink.elf blink.bin
riscv64-unknown-elf-objcopy -O ihex blink.elf blink.hex
make -C ../../ch32v003fun/../minichlink all
make[1]: Entering directory '/home/ubuntu/work/ch32v003fun/minichlink'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/ubuntu/work/ch32v003fun/minichlink'
../../ch32v003fun/../minichlink/minichlink -w blink.bin flash -b
Found WCH Link
WCH Programmer is LinkE version 2.10
Chip Type: 003
Setup success
Flash Storage: 16 kB
Part UUID : ab-d0-ab-cd-13-f8-bc-5b
PFlags : ff-ff-ff-ff
Part Type (B): 07-13-bb-91
Read protection: disabled
Interface Setup
Image written.
一連の操作が成功して、Lチカできました。
PlatformIO経由だとCH32V200系、CH32V300系のサンプルは割とあるのですが、003系は少ないのとRTOS使えないのでレジストリ操作に終始するマイコン開発になる感じがします。その場合は、このch32v003funの開発環境を使うのが便利だと思います。
ch32v003funと関連あるほかのリポジトリ
ch32v003funとCH32V003を使ってUSBデバイスを開発しているリポジトリ。USB接続デバイス作成するときはここ参考にすると良いかもしれない。
次回は、ADC読み取り、CH32V003内蔵のオペアンプを使うプログラム?を作成する予定です。
Discussion