REPLが何とか動作するようになった、Raspberry Pi用のベアメタル版MicroPythonですが、次は「Lチカ」をやってみました。
C言語でのLチカは以前行いましたが、これをREPLからできるようにします。
理想的には、machineモジュールを実装してPinオブジェクトを実装して、PinオブジェクトでGPIOを制御する…となりますが、最初から全部作るのはなかなか荷が重いので、いろいろ調べた結果、STM32の「stm」モジュール相当を実装してみることにしました。
stmモジュールはSTM32用のMicroPythonでメモリへの直接アクセスの手段を提供します。
以下に解説がありますが、要するに
stm.mem32[address]
という形式でaddressへのアクセスができます。
mem32でなくmem16やmem8を使うと、16ビットや8ビット単位でのアクセスが可能です。
値を代入すれば、addressへ書き込むこともできます。
これを使えば、GPIOレジスタへの読み書きができるので、GPIOへの入出力ができます。
というわけで、stm32用のmodstm.cをほぼそのまま使用してrpi mcuというモジュールを追加してみました。(追記:rpiはボードの名称を表していますが、今回のモジュールはボードではなくCPUに依存するので名称を変更しました)
モジュールのコードはこちらです。
MicroPythonにモジュールを追加するお作法については、以下のページが詳しいです。
Adding a Module — MicroPython Development Documentation 1.0 documentation
Book/text.md at master · PyConPL/Book
概ね、
・新しいモジュールのためのCソースファイルを作り、Makefileに追加する
・Cソースの中で、mp_obj_module_t型の定数を宣言する
・その定数をmpconfigport.hの中でextern宣言して参照できるようにする
・mpconfigport.hの中でMICROPY_PORT_BUILTIN_MODULESへ、
{ MP_ROM_QSTR(MP_QSTR_モジュール名), MP_ROM_PTR(&上記の定数) }
を追加する
という感じです。
mp_obj_module_t型は、モジュールで使用する関数や定数の名称を保持するmp_obj_dict_t型のメンバ変数を持っており、関数等はこれを介して呼び出されます。
このモジュールを使って、Raspberry Pi Zero Wのボード上のLEDをオン・オフしてみます。
以前の記事に書いたとおり、オンボードのLEDはGPIO47に接続されています。
GPIO47を出力モードにするには
・GPFSEL4のbit 21を1に
これを点灯させるには、GPIO47にLを出力するので
・GPCLR1のbit15を1に
消灯するにはGPIO47にHを出力するので
・GPSET1のbit15を1に
設定します。
MicroPythonのコードで書くと、それぞれ以下のようになります。
レジスタの名前は定義していませんので、アドレスをベタ書きしています。
以下の記事によると、Raspberry Pi 1/Zero/Zero Wでは0x20200000から始まっていたレジスタが、Raspberry Pi 2では0x3F200000からに変わっているそうなので、やはりアドレスではなくレジスタの名前が使えるようにするのが良さそうです。
Step01 – Bare Metal Programming in C Pt1 – Valvers
モジュールでの定数値の定義の仕方がまだよく分かっていないので、次回に持ち越しにしておきます。
(1/6追記)
GPIO関係のレジスタのアドレスを定数として追加しました。
mcu.mem32[mcu.レジスタ名]でレジスタへアクセスできます。
コメント