environment of the Arduino, by the ch32fun, for the UIAPduino


先日から,UIAPduinoのためのch32funによるArduinoの環境の開発を進めている. AlexanderManderaさんの環境は, そのような環境の一つであるので,そのコードを調べてみたところ,以下のようにして作られていることが分かった. まず,その中心となる開発環境の ch32funは,古いversionであるch32v003funを使っている. そして, ArduinoCoreAPIを組み込んでいるが,特にその中のHardwareSerialを書き換えて,Serialを実現している. コンパイルのオプションなどを指定しているplatform.txtなどは arduino-wch58x を参考にして作られている. i2c関係はhalというフォルダに入っているので,hardware abstraction layerのことだろうが,そのコードの起源は分からなかった.

この環境の利点を活かしつつ,UIAPduinoが使い易くなる環境を作りたいと考えていたが,少しずつ形になって来たので,そのことについて説明したい. 今回,新たな環境を構築するにあたって, 最新のch32funを使い,Arduinoの基本的な機能をArduinoと同じように使えるようにすることを,基本的な目標とした. また, 部品として使うch32funやArduinoCoreAPIなどのファイルは,できるだけ変更せずそのまま利用して,手を加えたファイルがどれかが分かりやすいようにする方針とした.

個人的に使うArduino環境は,~/Arduino/にファイルを置くことによって作ることができる. UIAPduinoに書き込みができるように, ~/Arduino/tools/minichlink/に,UIAPduinoのminichlinkを置き, ~/Arduino/hardware/wch/001/の下に,様々なファイルを配置して,Arduino IDEから使えるようにした. platform.txtは主にarduino-wch58xなどを,boards.txtはUIAPduinoなどを参考にして,作成した. cores/arduino/ch32fun/とcores/arduino/api/には,オリジナルのフォルダの内容をそのまま使った. ch32funが参照するcores/arduino/funconfig.hの中には,

#define FUNCONF_SYSTICK_USE_HCLK 1

を指定すると,以前起こったdelayなどが1/8になる問題が解消された. variants/CH32V003/pins_arduino.hには,ch32funのピンの定義を活かしつつ,Arduinoのピンの指定方法への橋渡しをするように記述した. コンパイルの後のリンクのときに,定義の一部が参照できないというエラーが出て,Arduino.hなどをいろいろといじって動くようになったが,よく理解できていない. cores/arduino/wiring_digital.cppやwiring_analog.cppは,ch32funのarduino-likeな書き方を最大限活用して,比較的コンパクトに書くことが出来た. その中で,以前の環境では使えなかったADCやPWMを実装した. ADCを簡単に使うためのコードは,extralibs/ch32v003_GPIO_branchless.hにも含まれているのを見つけたが,他の部分が干渉しそうだったので,funAnalogReadなどを使う方が無難だと判断した. PWMは,ピンのsetting変更は行わずに,とりあえず十個ぐらいのピンで使えるように書いたが,pinのmodeをOUTPUTでは無く,OUTPUT_AFにしないといけないことに気がつくのに,時間がかかってしまった. UIAPduinoでは,PWMは3つのピンで出来ると書いてあって,USBやRSTやSWIOで使うピンを除外しても7つは使えると思うけど,さらに相補的な出力を除いても4つになるのに,なぜA1がPWMを使えないことになっているのかな. 相補的な出力も,単独で使う場合には普通に使えるっぽいので,活用すれば良いように思うけど,何か理由があるのかも知れない. Serialはch32fun.cなどのコードを参考にしてcores/arduino/SerialUART.cppを作って,api/HardwareSerialとapi/RingBufferを活用して実現した. rv003usbのuart_cdc.cで作ったシリアル変換をつかって動作チェックをしたのだけど,そこに残ったバグに気が付くのにも苦労した. i2cについては,ArduinoCoreAPIを使っているmageavrのWire.cppから, ch32funのextralibs/ssd1306_i2c.hを参考に作った関数を呼び出すようにして,それらのファイルをlibraries/Wire/の中に入れた. SPIについては,同様にmegaavrのSPI.hとSPI.cppを変更して,ch32funのextralibs/ch32v003_SPI.hの関数を呼び出すようにした. しかし,リンクのときに, undefined reference to `operator delete(void*, unsigned int)' と出てしまう. あと少しで動きそうだけど,Arduinoのversionのせいかも知れない.

新たに作った環境の十分な動作チェックはまだだが,最低限の機能についてはArduinoとほぼ同じ感覚で使えるようになったと考えている. 以前の環境に比べて,以下の点が進歩したと思う. まず,ADCとPWMが新たに使えるようになり,i2cがWireから使えるようになった. SPIも,あと一歩だと思うけど,私はあまり使わないので,今は許して下さい. 細かい点では,ADCなどの指定がArduinoと同じようにできるようになったし, SerialはArduinoCoreAPIを変更しないで実現した. 欠点としては,少しコンパイルサイズが大きくなった点が気になるが,ch32funを新しくした影響なのかな. 新たに作った環境でblink.inoをコンパイルしたときの,binファイルのサイズは2040byteとなり,以前に比べて二割ほど大きくなったが,WCHの環境よりはるかに小さいので,十分使えるレベルだと思う. serialとi2cを使うプログラムは,13.9kだったので,まあflashには収まるサイズになった. 多数の機能を使ったら,flashのサイズを超えるかも知れないので,今後の検証が必要だろう.

次のステップとして,rv003usbを使えるようにできないかを模索する予定である. それには,ArduinoIDEのファイルの扱いについて,さらに理解を深めないといけないだろう. メニューからオプションでUSBを使う指定をしたときだけ,rv003usbを組み込むようにしたいけど,そのためには,どこにどうファイルを配置すれば良いのかを調べる必要がある. CDCまたはHIDを使ったprintを使えるようになれば,実用性が非常に大きくなるだろう. バグが減ってきたら,いずれは何らかの形で公開したいが,githubの使い方を覚えるのも面倒なので,どうしようかな.