前回記事から約4か月もMicroPythonご無沙汰です。別処理系に手を伸ばしたせいで棚上げ状態。これではイケナイということでMicroPython再開でございます。しかし忘却力です。どうやってMicroPythonしたらよかったんだけ?まずはターゲットになるボードを取り出さないと。。。ラズパイPicoであります。
※「MicroPython的午睡」投稿順 Indexはこちら
今回は「MicroPythonのリハビリ」ということで、軽く、しかし過去やってなかった部分を触りたいと思います。使ってみるのは uctypes とな。ドキュメントへのリンクが以下に
uctypes – access binary data in a structured way
表面的には「Cの構造体」的なスタイルで、メモリ構造にアクセスするためのモジュールです。バイナリのデータ構造にアクセスするのに便利そうなモジュールであります。しかし、なんとメモリ番地を直接指定できてしまう危ない奴なんであります。この機能を「活用」すれば、ハードウエアのレジスタやメモリに直接アクセスが自由自在。その代りマイコンがクラッシュしても知らん、と。自分で良く確かめて使うべし、なのであります。
実験用のMicroPythonコード
今回、とりあえず「リードオンリ」にてアクセス実験。ま、読むだけならまあまあ大丈夫だろ~というところ。
読み取る対象は以下のハードウエアレジスタです。
-
- CPUコアであるArm Cortex-M0+のCPUIDレジスタ
- Sysinfoブロックの CHIP_IDレジスタ。JEDEC_JEP-106のIDを含む。知らんけど。
- Sysinfoブロックの PLATFORMレジスタ。実装方法が読み取れるみたい。
まあ、読み取り確認は値が知れている最初のCPUIDよめばOKですが。ソースが以下に。
import uctypes SYSINFO_BASE = 0x40000000 CHIP_ID = 0x00 PPB_BASE = 0xE0000000 CPUID = 0xED00 CHIP_ID_REG = { "CID": 0 | uctypes.UINT32, "PLT": 4 | uctypes.UINT32 } CPU_ID_REG = { "CPU": 0 | uctypes.UINT32 } def main(): cpu = uctypes.struct(PPB_BASE+CPUID, CPU_ID_REG) print("M0PLUS::CPU_ID : 0x{0:08x}".format(cpu.CPU)) cid = uctypes.struct(SYSINFO_BASE+CHIP_ID, CHIP_ID_REG) print("SYSINFO::CHIP_ID: 0x{0:08x}".format(cid.CID)) print("SYSINFO::PLATFORM: 0x{0:08x}".format(cid.PLT)) if __name__ == "__main__": main()
「Pythonのくせに」C風に、中カッコで括ったりして「構造体」っぽいものを定義している雰囲気を醸しているのが、猪口才というか、なんというかです。
そして構造体メンバへのアクセスよろしく読み取ればハードウエアのレジスタが読み取れます。当然、代入すれば書き込めますが、それはまた、次回以降に。
実機実行確認
最初の M0PLUS::CPU_ID ですが、
-
- 先頭の0x41は、Armインプリであることを示す
- 次の0x0は、メジャーリビジョンが0
- その次の0xCは、ARMv6-Mアーキテクチャであることを示す
- その次の0xC60は、Cortex-M0+
- 末尾の0x1はマイナーリビジョン、Patch 1
ということで予定通りの値が読めてます。
その次のSYSINFO::CHIP_IDはこれでよいのかどうか不明。なお、下12ビット0x927のところは、JEDECのマニュファクチャラ識別コードの筈。
PLATFORMのレジスタは最下位の2ビットのみが意味ありです。ビット0が立っていればFPGA、ビット1が立っていればASICだそうです。当然、ビット0は立っておらず、ビット1が立っておりますな。
なんだ、MicroPythonでもハードウエアのレジスタいじり放題じゃん。