CH32VのオレオレArduino環境を作ろう その1 環境準備

概要

CH32のRISC-Vチップを触っていますが、微妙にArduino環境が使いにくいのでオレオレ環境を勉強しながら作っていきたいと思います。

置き場の確保

最初に置き場の確保です。GitHubの個人アカウントに置くとなんとなくカッコ悪いので専用の場所を利用したいと思います。別アカウントを作るのも考えましたがGitHubではOrganizationという組織を作る機能が最初からありました。無料で作れるので「CH32 RISC-V User Group」という団体を勝手に作り、そこを置き場にしてみたいと思います。

CH32 RISC-V User Group
CH32 RISC-V User Group has 11 repositories available. Follow their code on GitHub.

出来上がったページが上記になります。いろいろ作り途中ですが、最初に状況をまとめるところに時間がかかりしぎました。。。

構成を考える

Arduino IDEで環境を作る場合にはボードマネージャーを利用します。ボードマネージャーではコアとなるコンパイルに必要なファイルなどと、ビルドに使うためのツール群に分かれています。

GitHub - openwch/arduino_core_ch32: Core library for CH32duino
Core library for CH32duino. Contribute to openwch/arduino_core_ch32 development by creating an account on GitHub.

openwchで管理されているarduino_core_ch32をベースとして環境構築をしていきたいと思います。CH32系の開発をする場合にはビルドツールとしてはgccなどを利用しますがMounRiverに付属しているものが最新で、Arudinoのものは古いものでした。古いとCH32L103などの新しいボード向けにはビルドできないので、新しいものを準備する必要があります。

GitHub - ch32-riscv-ug/MounRiver_Studio_Community_miror: Mirror site of MounRiver Studio Community(MRS Community)
Mirror site of MounRiver Studio Community(MRS Community) - ch32-riscv-ug/MounRiver_Studio_Community_miror

そのためのリポジトリを作成しました。GitHubの場合リポジトリの中にはあまり大きなファイルを置けないので、すべてリリースの中に置きました。

Release v1.91(v170) 2024-02-29 Setup · ch32-riscv-ug/MounRiver_Studio_Community_miror
MounRiver Studio Community V170->MRS V1.91 BASE(miror)

SetupとついたリリースはMounRiver自体のファイルになります。中国サイトからダウンロードすると重いので、とりあえずそのままGitHubにもミラーしておきます。

Release v1.91(v170) 2024-02-29 Toolchain · ch32-riscv-ug/MounRiver_Studio_Community_miror
MounRiver Studio Community V170->MRS V1.91 BASE(miror)(copy)http:...

Toolchainとついたリリースがビルドで利用するファイル群になります。LinuxとMacはToolchainのみでの提供があるのですが、WindowsはMounRiverをセットアップしてから自分でToolchainを取り出す必要があります。そのためセットアップ直後のディレクトリからWindowsで必要なToolchainを圧縮したものもリリースに追加しています。

あとArduino IDEだとツール単位で圧縮されている必要があるので、バラして圧縮したファイルもリリースに追加してあります。これでビルドツールの準備はできました。

コアの準備(noneOS)

GitHub - ch32-riscv-ug/arduino_core_ch32_riscv_noneos: CH32 Risc-V noneOS for Arduino IDE (not ArduinoAPI)
CH32 Risc-V noneOS for Arduino IDE (not ArduinoAPI) - ch32-riscv-ug/arduino_core_ch32_riscv_noneos

まずはArduino IDEで、EVTがそのまま動く環境を作りました。EVTとはCH32系のSDKのことでサンプルプログラムとSDKがセットになったようなものになります。openwchで管理されているarduino_core_ch32環境にも入っているのですが内容が古かったです。最新版をダウンロードしてある程度かんたんに更新できるようにしています。手作業は面倒なのと失敗するんですよね。

いろいろなやり方があると思いますが、完成物はリリースにありリポジトリには作成するためのツールしかありません。作成物にPRだされても次回の自動更新で消えちゃうので、パッチファイルをおいてパッチを当てています。これだとEVTを更新してもパッチが当てられますし、パッチが失敗した場合には原因がわかりやすいです。

#include "debug.h"

#ifdef __cplusplus
extern "C" {
#endif

void setup();
void loop();

#ifdef __cplusplus
}
#endif

Arduino.hにはシンプルにEVTのdebug.hを読み込んでいるだけです。Arduino系のコードは一切ないのでpinModeなどの関数群はすべて利用できません。

#include "Arduino.h"

void c_main( void ) __attribute__(( weak ));
void c_main( void )
{
}

int main(void)
{
    c_main();

    setup();

    for (;;)
    {
        loop();
    }
}

main.cは上記です。Arduino IDEで動くようにsetupとloopを呼び出しているだけです。ただEVTと同じようにC言語だけで組みたい人もいると思いますのでc_mainを呼び出しています。

#include "debug.h"

void c_main() {
  uint8_t i = 0;

  SystemCoreClockUpdate();
  Delay_Init();
  USART_Printf_Init(115200);
  printf("SystemClk:%u\r\n", (unsigned int)SystemCoreClock);
  printf("ChipID:%08x\r\n", (unsigned int)DBGMCU_GetCHIPID());
  printf("C main TEST\r\n");

  while (1) {
    Delay_Ms(250);
    i++;
    printf("i = %d\r\n", i);
  }
}

c_main.cみたいなファイルを準備して、C言語でEVT的なプログラムも可能です。

void GPIO_Toggle_INIT(void) {
  GPIO_InitTypeDef GPIO_InitStructure = { 0 };

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void setup() {
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  SystemCoreClockUpdate();
  Delay_Init();
  USART_Printf_Init(115200);
  printf("SystemClk:%d\r\n", SystemCoreClock);
  printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID());
  printf("GPIO Toggle TEST\r\n");
  GPIO_Toggle_INIT();
}

void loop() {
  static u8 i = 0;
  Delay_Ms(250);
  GPIO_WriteBit(GPIOA, GPIO_Pin_0, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
  printf("GPIO_WriteBit %d\n", i);
}

一般的なプログラムは上記となります。Arduino IDEを利用していますが、Arduino系の処理系ははいっていないのでEVTの処理をそのままそれっぽくもって来ています。

Arduino Coreの準備

EVTベースで動く環境ができましたので、それを下にArduino Coreの実装をしていきたいと思います。

GitHub - ch32-riscv-ug/arduino_core_ch32_riscv_arduino: CH32 Risc-V for Arduino IDE
CH32 Risc-V for Arduino IDE. Contribute to ch32-riscv-ug/arduino_core_ch32_riscv_arduino development by creating an acco...

作ったリポジトリが上記です。noneOSの最新版をコピーしてきて、その上にArduino Coreを構築しています。

#if defined(CH32V003)
#define OUTPUT_PIN PC1
#define INPUT_PIN PC2
#else
#define OUTPUT_PIN PA1
#define INPUT_PIN PA2
#endif

void setup() {
  printf("setup\n");
  pinMode(OUTPUT_PIN, OUTPUT);
  pinMode(INPUT_PIN, INPUT_PULLUP);
}

void loop() {
  static PinStatus output = LOW;
  output = (output == LOW) ? HIGH : LOW;
  printf("loop\n");
  digitalWrite(OUTPUT_PIN, output);
  printf(" output = %d\n", output);
  printf(" input = %d\n", digitalRead(INPUT_PIN));
  delay(1000);
}

現状Arduino Coreの中でpinModeとdigitalWrite、digitalReadだけ実装してみました。あとは個別の処理を実装していけばいいのですが、細かいところは次回以降に書きたいと思います。

ボードの情報集約

Arduino Coreを実装していると、元になっているEVTのコードを参考したいときがあります。そこで最新版のEVTをミラーしているサイトを作りました。openwchにもあるのですが、あちらには依存したくなかったのと、プログラムで必要な情報をトップページに集約したかったからです。

このページはまだ未完成なのですが、データシートから表をいろいろもってきて手で修正しているので非常に時間がかかっています。

まとめ

今回は環境を作ったところで力尽きたので次回以降からオレオレ環境を作るときの注意点などを書いていきたいと思います。

しかしCH32は現状でも6種類の開発ボードがあります。CH32V006が増えたので更に増えていくはずです。個別に動作確認をしているのでArduino Core対応はかなりの鬼門になります。そしてopenwchで管理されているarduino_core_ch32環境は構造的に限界がきていると思います。EVTを最新に保つのだけでもかなりつらそうな構成になっていました。

コメント