Arduino を使わないという選択
世の中、ほぼ Arduino 一択という状況になってしまったと言っても過言では無いです。
自分が考えるに、良い面と、そうではない面があると思います。
「良い面」は、非常に簡単に言うと、「敷居を極限まで下げた」と言えるのかもしれません。
アプリケーションを作るのに必要な知識だけでマイコンを動かせます。
Arduino は易しいですが、マイコンを独自で動かす事も実はそんなに難しくありません。
実際、「独自」にマイコンを動かして、「main」関数まで来るには、色々と、行わなければならない事や知識が必要です。
Arduino では、これらの知識は「不要」と分類されており、アプリケーションを作るユーザーが考える必要はありません。
※これは、マイコンが違っても、Arduino 環境下では、同じように使う事が出来ます。
Arduino は一応 C++ ですが、元が、AVR と言う 8/16 ビットマイコンからスタートした為、最新の C++ コンパイラを利用できません。
世の中にある、スケッチは、この制限により、C++ とは言えない物が多く、互換性を考えて、今でも、古いスタイルでプログラミングをしています。
自分も昔は、C 言語が主流で、C++ はオマケ程度でしたが、PC でアプリケーションを作るプロジェクトで仕事をした時、C++ を勉強しなおしました。
そこから、数十年、今では、C++ 以外でプログラムを作る事が苦痛になっています。
※ C++ は非常に難しい部分があるので、独学では限界があります、良い師と、時間が必要ですが、最近は、「勉強会」も頻繁に行われており、「学ぶ」には、かなりハードルが下がりました。
また、最高のコンパイラもフリーで利用出来ます。
組み込みマイコンでも、C++ を積極的に使いたいので、国産で、高性能なマイコンを探しました。
ARMが嫌いな訳では無く、単純に、日本人なのに、「わざわざ外国のマイコンを使うのはおかしいだろう」という思いがありました。
昔から、日立は好きで、H8やSHを良く使っていました、しばらくしてルネサスに統合されました。
最近は、RXマイコンを推しているようです、RXマイコンは多分三菱由来のマイコンと思いますが、非常に優れた、マイコンである事が直ぐに判りました。
開発環境も、gcc をサポートしており、十分実用になる事が判りました。
そこから C++ を積極的に利用した組み込みマイコン用フレームワークを整備して、現在に至っています。
※このフレームワークは、いくつかのプロジェクトで利用しています、その関係もあり、ライセンスを MIT にしています。
開発環境の整備
ルネサス社の E2 Studio は、無料版に制限(128Kバイトまでしかバイナリーを作れない)があり、CC-RX コンパイラでは、C++11、C++14, C++17 などの C++ ソースをコンパイルする事が出来ない為、独自にビルドした gcc-6.4.0 を使います。
※ルネサス社は、独自に、gcc-4.8 ベースの開発環境も用意していますが、4.8 系では、C++14, C++17 をコンパイルする事が出来ない。
C++11, C++14, C++17 はそれぞれ、2011 年、2014 年、2017 年に C++ 標準化委員会が策定した仕様を網羅したバージョンです。
年度が更新する(3年毎)度に、より良い機能が使えるようになっており、わざわざ古い仕様の C++ を使う理由は無いと思います。
※ C++17 は 2017 年の仕様です、今は 2020 年なので、ある程度「枯れて」いると言えると思います。
RX72N Envision kit の内蔵 E2-Lite を使って、マイコン内蔵フラッシュプログラムを書き換えするには、Windows 環境が必須となります。
コマンドラインによる開発環境を著しく敬遠する人がいますが、「慣れ」の問題であり、GUI 環境を覚えるよりハードルは低いと思われます。
MSYS2 を利用しています。
gcc のビルドに関しては、hirakuni45 github RX、又は gcc、g++を使ったルネサスRXマイコン開発を参照の事。
Renesas Flash Programmer v3 をインストールしてください。
ソースコードの編集には、VSCode が便利です、馴染みのテキストエディターが無いのなら(あっても)インストールお勧め。
※設定や、使い方は、ぐぐって~
ソースコードの取得
関係フレームワークなど一式を、github からクローンします。
※「D:/Git/RX」にクローンしています。
W10.~ % cd /d/Git
W10./d/Git % git clone git://github.com/hirakuni45/RX.git
他に「boost」が必要です。
W10./d/Git % pacman -S mingw-w64-x86_64-boost
FIRST_sample
FIRST_sample ディレクトリ、RX72N に移動します。
W10./d/Git ~ % cd RX/FIRST_sample
W10./d/Git/RX/FIRST_sample % cd RX72N
ソースコードをビルドします。
W10./d/Git/RX/FIRST_sample/RX72N % make
W10./d/Git/RX/FIRST_sample/RX72N % ls
led_sample.elf led_sample.lst led_sample.map led_sample.mot Makefile release
ビルドされた「led_sample.mot」ファイルを、Renesas Flash Programmer で、RX72N Envision kit に書き込みます。
RX72N Envision kit USR LED が 0.25 秒間隔で点滅する。
Flash Programmer v3 の設定
- PC と RX72N Envision kit の「ECN1」をマイクロUSBで接続します。
- 電流不足になる場合、外部にACアダプタを接続する必要があります。
- SW1 の 2 番をOFFにします。
- 新規プロジェクトを作成し、RX72x を選択します。
- E2 emulator Lite を選択
- FINE を選択
- 1,500,000 bps を選択
- 供給しない を選択
- リセット端子をHi-Z を選択
- 接続出来たら、先ほどビルドしたファイルを選択して、書き込みます。
ソースコードを眺める
ソースコードは、複数のRXマイコン用に実装されており、「SIG_RX72N」が機種依存部分となっています。
#include "common/renesas.hpp"
namespace {
/// ベースクリスタルの定義
/// LED 接続ポートの定義
#if defined(SIG_RX71M)
typedef device::system_io<12'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT0, device::bitpos::B7> LED;
#elif defined(SIG_RX72M)
typedef device::system_io<12'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT0, device::bitpos::B7> LED;
#elif defined(SIG_RX72N)
typedef device::system_io<16'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT4, device::bitpos::B0> LED;
#elif defined(SIG_RX64M)
typedef device::system_io<12'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT0, device::bitpos::B7> LED;
#elif defined(SIG_RX65N)
typedef device::system_io<12'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT7, device::bitpos::B0> LED;
#elif defined(SIG_RX63T)
typedef device::system_io<12'000'000> SYSTEM_IO;
typedef device::PORT<device::PORTB, device::bitpos::B7> LED;
#elif defined(SIG_RX24T)
typedef device::system_io<10'000'000, 80'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT0, device::bitpos::B0> LED;
#elif defined(SIG_RX66T)
typedef device::system_io<10'000'000, 160'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT0, device::bitpos::B0> LED;
#elif defined(SIG_RX72T)
typedef device::system_io<8'000'000, 192'000'000> SYSTEM_IO;
typedef device::PORT<device::PORT0, device::bitpos::B1> LED;
#endif
}
int main(int argc, char** argv);
int main(int argc, char** argv)
{
SYSTEM_IO::setup_system_clock();
LED::OUTPUT(); // LED ポートを出力に設定
while(1) {
utils::delay::milli_second(250);
LED::P = 0;
utils::delay::milli_second(250);
LED::P = 1;
}
}
RX マイコンは、内部にクロックジェネレータがあり、起動した場合には、内部の発信器で、最低限の状態で起動します。
そこで、RX72N の動作を最高性能に切り替える為、フレームワークの助けを借ります。
SYSTEM_IO::setup_system_clock();
この API を呼ぶ事で、RX72N は最大の 240MHz で動作します。
「SYSTEM_IO」は、以下のように定義されており、外部 16MHz のクリスタルを接続している設定です。
typedef device::system_io<16'000'000> SYSTEM_IO;
240MHz の指定は、Makefile でされており、ソースをコンパイルする時に、定数を指定しています。
※「F_ICLK」の値
USER_DEFS = SIG_RX72N \
F_ICLK=240000000 \
F_PCLKA=120000000 F_PCLKB=60000000 F_PCLKC=60000000 F_PCLKD=60000000 \
F_FCLK=60000000 F_BCLK=120000000
※これらの定数を使って、内部で、クロックジェネレータの設定を自動で行います。
※詳しくは、system_io.hppを参照の事。
LED の定義では、PORT テンプレートクラスにより、1ビットのポートとしています。
※この場合、PORT4 の B0 で、ボード上のユーザーLEDに接続されています。
typedef device::PORT<device::PORT4, device::bitpos::B0> LED;
LED ポートを出力に指定します。
LED::OUTPUT(); // LED ポートを出力に設定
LED ポートに「0」、「1」を送る。
LED::P = 0;
...
LED::P = 1;
0.25 秒の間隔を作るのはソフトウェアータイマーによるものです。(あまり正確ではありません)
※250ミリ秒
utils::delay::milli_second(250);
このように、非常に簡単にオリジナルプログラムを走らせる事が出来ます。
次回、SCI を利用したプログラムを解説する予定です。