machine --- ハードウェア関連の関数
machine モジュールは、特定のボード上のハードウェアに関連する固有の関数を含んでいます。このモジュールのほとんどの機能はシステム上のハードウェアブロック(CPU、タイマー、バスなど)への直接的かつ無制限のアクセスと制御を実現します。誤って使用すると、誤動作、ロックアップ、ボードのクラッシュ、および極端な場合にはハードウェアの損傷を招く可能性があります。
メモリアクセス
このモジュールは、素のメモリアクセスに使う3つのオブジェクトを提供します。
- machine.mem8
メモリを8ビットで読み書きします。
- machine.mem16
メモリを16ビットで読み書きします。
- machine.mem32
メモリを32ビットで読み書きします。
目的のアドレスを指定するには、これらのオブジェクトのインデックス添字表記 [...] を使ってください。なお、アクセスするメモリのサイズに関係なく、アドレスはバイトアドレスです。
使用例(レジスタは stm32 マイクロコントローラに固有のものです):
import machine
from micropython import const
GPIOA = const(0x48000000)
GPIO_BSRR = const(0x18)
GPIO_IDR = const(0x10)
# PA2 を high に設定
machine.mem32[GPIOA + GPIO_BSRR] = 1 << 2
# PA3 を読取り
value = (machine.mem32[GPIOA + GPIO_IDR] >> 3) & 1
注記: 戻り値は符号付き整数です。たとえば ESP8266 の CPUID レジスタ読取りは次のようにします。
value = mem32[0x40001000]
ESP8266 の CPUID は本来、符号なしの32ビット整数であり、この機能で読み取った値は直感に反する(counter-intuitive)負の値になることがあります。
常に正の整数として読み取るには次のようにします。
value = mem32[0x40001000] & 0xffffffff
- machine.mem_backup(region=0)
すべてのポートで少なくとも ソフトリセット までの間保持される永続的なハードウェアメモリ領域に対する書き込み可能な
memoryviewを返します。バッテリーバックアップされたポートでは電源オフ後も保持されます。ポートごとの永続性の保証は異なります。後の表を参照してください。region は、アクセスするバックアップ領域を選択します(デフォルトは0、プライマリ領域)。
-1を指定すると、利用可能なすべての領域のタプルが取得されます。要素の型は、ポートのハードウェアアライメント要件によって異なります。バイト単位でアドレス指定可能なバックアップメモリを備えたポートでは
'B'(符号なし1バイト)、ワードサイズのレジスタでバックアップされたポートでは'I'(符号なし32ビット)となります。実行時にアクセス粒度を確認するにはmem.itemsizeを使ってください。合計サイズ(バイト単位)は
len(mem) * mem.itemsizeで表されます。ここでlen(mem)は要素数、mem.itemsizeは各要素のサイズです。たとえば、ワードサイズのレジスタが 4 つあるポートの場合len(mem)は 4、mem.itemsizeも 4 なので、合計は 16 バイトになります。4096 バイトのバイトアドレス指定可能なバックアップ SRAM を持つポートの場合、len(mem)は 4096、mem.itemsizeは 1 になります。ポータブルコードのためのクロスポート保証:
mem.itemsizeは1または4のいずれかです。有効なインデックスは0..len(mem)-1です。範囲外のアクセスはIndexErrorを発生させます。値はホストネイティブのバイトオーダーで格納されます。領域インデックスのセマンティクスは移植可能ではありません。特にstm32については、後述の注記を参照してください。使用例:
import machine mem = machine.mem_backup() mem[0] = 0x12345678 # 要素 0 への書込み print(hex(mem[0])) # 要素 0 の読取り print(len(mem)) # 要素数 print(mem.itemsize) # 要素のバイト長 print(len(mem) * mem.itemsize) # 利用可能な総バイト長 # 利用可能なすべての領域 for i, r in enumerate(machine.mem_backup(-1)): print(i, len(r), r.itemsize)
合計バイトサイズとバックアップ用ハードウェアはポートによって異なります:
ポート
バックアップ用ストレージ
総バイト長
バッテリーバックアップ
alif
バックアップ SRAM
4096
yes
esp32
RTC 低速メモリー
2048
no
mimxrt
SNVS LPGPR レジスタ(チップあたり4)
12-16
yes
nrf
POWER GPREGRET registers
1-2
no
rp2
ウォッチドッグ・スクラッチレジスター
28-60
no
samd
バックアップ RAM (SAMD51 のみ)
8192
yes
stm32
バックアップ SRAM + BKP レジスター (F4/F7/H5/H7/U5/N6)
2048-8192
yes
stm32
RTC BKP レジスター (その他のファミリー)
20-128
yes
注釈
esp32 と rp2 では ソフトリセット,
machine.reset(),machine.deepsleep()によるウェイクアップ後もデータは保持されますが、電源オフ時や電源オン時のリセット時にはデータが失われます。特に esp32 では、ほとんどの開発ボードにある EN/RESET ボタンを押すと、チップが電源オンリセットとして認識するため、データが失われます。ポートによっては、バックアップストレージを複数の領域に分割したり、ブートローダーやシステムファームウェアによって予約されているレジスタを除外したりする場合があります:
ポート
レジスター
注記
mimxrt
LPGPR[3]
除外; TinyUF2 で使用(使用する場合)
rp2
scratch[4]
除外; pico-sdk がリセット時に使用
rp2
powman scratch[0..7]
RP2350 のリージョン2のみ
stm32
BKP レジスター
BKPSRAM ファミリー(F4/F7/H5/H7/U5/N6)のリージョン1
利用可能な領域とそのサイズを確認するには
machine.mem_backup(-1)を使ってください。stm32 では、領域インデックスの意味はボード間で統一されていません。領域0は、BKPSRAM ファミリではBKPSRAM(
itemsize=1)、その他のファミリでは BKP レジスタ(itemsize=4)です。ポータブルなコードにするには、データ構造化の前にmem.itemsizeで分岐する必要があります。領域内のレジスタの中には、アクセス可能ではあるものの、慣例により予約されているものがあり、上書きしてはいけません。BKP レジスタファイルは、BKPSRAMファミリでは領域1、その他のファミリでは領域0です。
ポート
レジスター
何に予約されているか
stm32
BKP0R
Arduino ブートローダー (Portenta H7, Giga, Opta, Nicla)
stm32
BKP16R-BKP18R
STM32WB の
rfcore_firmware.pystm32
last BKP reg
クロック周波数(
MICROPY_HW_CLK_LAST_FREQ)stm32
BKP31R (N6)
mboot ブートローダーエントリー
このバッファはレジスタへの直接アクセスを可能にし、構造化レイアウトのために
uctypesと組み合わせられます。import machine, uctypes mem = machine.mem_backup() # uctypes による構造化アクセス(ボードの len(mem) を確認してください) layout = { "flags": (0 * 4, uctypes.UINT32), # レジスター 0 "counter": (1 * 4, uctypes.UINT32), # レジスター 1 } regs = uctypes.struct(uctypes.addressof(mem), layout) regs.flags = 0x01 print(regs.counter)
対応ポート: alif, esp32, mimxrt, nrf, rp2, samd, stm32
その他の関数
- machine.unique_id()
ボード/SoC の一意な識別子を持つバイト列を返します。基盤となるハードウェアが許せば、この値はボード/SoC の個体ごとに異なります。長さはハードウェアによって異なります(短い ID が必要な場合は、完全な値の部分文字列を使用してください)。一部の MicroPython ポートにおいて、ID はネットワークの MAC アドレスに対応します。
- machine.time_pulse_us(pin, pulse_level, timeout_us=1000000, /)
指定の pin のパルスを計時し、パルスの持続時間をマイクロ秒単位で返します。 pulse_level 引数には、低パルスを計時する場合に 0、高パルスを計時する場合に 1 を指定します。
ピンの現在の入力値が pulse_level と異なる場合、関数は最初にピン入力が pulse_level に等しくなるまで待機し(*)、次にそのピンが pulse_level に等しい時間を測ります(**)。ピンが既に pulse_level に等しい場合、計測はすぐに開始されます。
タイムアウトが発生した場合、上記の(*)の状態を待っていた場合は -2 を返し、上記の(**)の場合は -1 を返します。タイムアウト時間は両方のケースで同じで、 timeout_us (マイクロ秒単位)で指定します。
- machine.bitstream(pin, encoding, timing, data, /)
指定の pin をビットバンギングして data を送信します。引数 encoding には、ビットのエンコード方法を指定し、 timing にはエンコードに応じたタイミングを指定します。
サポートされているエンコーディングは次のとおりです:
0は "high low" パルス幅変調です。これは 0 と 1 のビットを最上位ビットから順に時限パルスとして送信します。timing は(high_time_0, low_time_0, high_time_1, low_time_1)の形式で、ナノ秒の4項目タプルでなければなりません。たとえば(400, 850, 800, 450)は 800kHz の WS2812 RGB LED のタイミング仕様です。
タイミングの精度はポートによって異なります。48MHz の Cortex M0 では、せいぜい +/-120ns 程度ですが、より高速なMCU(ESP8266, ESP32, STM32, Pyboard)では +/-30ns 程度になります。
注釈
WS2812/NeoPixel ストリップの制御については、上位の API である
neopixelモジュールを参照してください。
- machine.rng()
24ビットのソフトウェア生成乱数を返します。
対応ポート: WiPy
定数
クラス
- クラス Pin -- I/O ピンの制御
- クラス Signal -- 外部 I/O デバイスの制御と検知
- クラス ADC -- アナログ-デジタル変換
- クラス ADCBlock -- ADC ペリフェラルの制御
- クラス DAC -- デジタル-アナログ変換
- クラス PWM -- パルス幅変調
- クラス UART -- 二重シリアル通信バス
- クラス SPI -- シリアルペリフェラルインタフェース バスプロトコル(コントローラ側)
- クラス I2C -- 2線式シリアルプロトコル
- クラス I2CTarget -- I2C ターゲットデバイス
- クラス I2S -- IC間サウンド(Inter-IC Sound)バスプロトコル
- class CAN -- Controller Area Network protocol
- クラス RTC -- リアルタイムクロック
- クラス Timer -- ハードウェアタイマーの制御
- クラス Counter -- パルスカウンター
- クラス Encoder -- 直交デコード
- クラス WDT -- ウォッチドッグタイマー
- クラス SD -- セキュアデジタルメモリーカード(cc3200 ポートのみ)
- クラス SDCard -- SD メモリカード
- クラス USBDevice -- USB デバイスドライバー