前回はMicroPythonのuctypesモジュールを使って、ラズパイPicoのCPUレジスタを直接読んでみました。しかし読み取りだけ、書き込みもビットフィールド・アクセスもやってないです。直接IO制御するなら練習しておかないと。今回はメモリ上のバイトアレイを練習相手に書き込みとビットフィールド操作をやってみます。
※「MicroPython的午睡」投稿順 Indexはこちら
※以下に掲載のMicroPythonスクリプトはラズパイPico上の以下のバージョンのMicroPythonインタプリタで動作確認しています。
MicroPython v1.15 on 2021-04-18; Raspberry Pi Pico with RP2040
今回使用の uctypesモジュールについてのドキュメントへのリンクは以下に
uctypes – access binary data in a structured way
実験用のMicroPythonコード
今回は、書き込みも行うので、念のためIO相手ではなく、メモリ(SRAM)アクセスとしました。
-
- メモリ上に bytearray 8バイト分を確保する。
- ワード(4バイト)x2つの構造体(STRUCT1)を定義
- 1ワードの中の4ビットのみをアクセスする構造体(STRUCT2)を定義
- それぞれの構造体を確保したバイトアレイ上に「おいて」読み書きアクセス
という段取りです。ついては確保したbytearrayがSRAM上のどこにあるのかも印字するようにいたしました。
import uctypes buf = bytearray(8) STRUCT1 = { "field0" : 0 | uctypes.UINT32, "field1" : 4 | uctypes.UINT32, } STRUCT2 = { "bf0" : 0 | uctypes.BFUINT32 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN, } def initBuf(): for i in range(8): buf[i] = i def main(): initBuf() adr = uctypes.addressof(buf) print("ADR : 0x{0:08x}".format(adr)) sct1 = uctypes.struct(adr, STRUCT1) print("field0 : 0x{0:08x}".format(sct1.field0)) print("field1 : 0x{0:08x}".format(sct1.field1)) sct1.field0 = 0x87654321 sct1.field1 = 0xFEDCBA98 print("field0 : 0x{0:08x}".format(sct1.field0)) print("field1 : 0x{0:08x}".format(sct1.field1)) sct2 = uctypes.struct(adr, STRUCT2) print("bf0 : 0x{0:01x}".format(sct2.bf0)) sct2.bf0 = 0xA print("bf0 : 0x{0:01x}".format(sct2.bf0)) print("field1 : 0x{0:08x}".format(sct1.field0)) if __name__ == "__main__": main()
実験結果
上記のソースを実機ラズパイPico上で走らせた結果が以下に。
まず最初のADRは、バイトアレイのメモリアドレスです。ラズパイPicoの場合0x20000000からSRAMの筈。アレイはSRAM上にあるようです。
そこにSTRUCT1を被せてUNIT32型のフィールド、field0とfield1を読み取っています。初期値としてバイトアレイには下からバイト値0,1,2,3,4,5,6,7を書き込んであるので、これを32ビット幅で読み出した結果は一致しています。
その後、field0に0x87654321、field1に0xfedcba98を書き込んでから読み出してます。ちゃんと読み書きできてるみたい。
続いて同じバイトアレイに今度はSTRUCT2を被せ、LSBから数えて8ビット目から4ビットの値をbf0に読み取ってます。0x3と正しく読めています。
そのビットフィールドに0xaを書き込んでから読み出すと0xa。さらに先ほどのSTRUCT1のfield0をつかって32ビットで読み出すと、0x87654a21と、ビットフィールドの部分のみ書き換わっていることが分かります。
ま、予定通り。