chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

4月のパッチ(Windows Update)を当てたらブルーバックで起動しない->復旧できたが、KB5001330はどうやっても当たらない

4月のWindows Updateを当てるためPC再起動すると、ブルーバックになってOSが起動しない状況に。

エラーコードは、0xc000021aで、ググると、パッチ適用に失敗してドライバ不整合の場合に出ることがあるそうだ。復旧方法が紹介されていたので、その記事を参考に以下を行った。

  1. スタートアップ設定から、セーフモード起動を指定
  2. セーフモード起動時、オプション7(ドライバ署名の強制を無効にする)を選択

上記操作で、Windowsは起動できた。起動してみると、パッチ適用のための再起動待ちになっていた。(適用前の状態で起動されたような感じ)

ここで再起動すると、また同じ0xc000021aのエラーになるのでは?と思えるのだが、、

復旧のためには、以下を実行せよとあった

sfc /scannow

とりあえず実行してみる。

$ sfc /scannow

システム スキャンを開始しています。これにはしばらく時間がかかります。

システム スキャンの検証フェーズを開始しています。
検証 100% が完了しました。

Windows リソース保護により、破損したファイルが見つかりましたが、それらは正常に修
復されました。
オンライン修復の場合、詳細は次の場所にある CBS ログ ファイルに含まれています
windir\ Logs\CBS\CBS.log (たとえば C:\Windows\Logs\CBS\CBS.log)。オフライン修復
の場合、
詳細は /OFFLOGFILE フラグによって指定したログ ファイルに含まれています。

ログが大きすぎて、ざっと読んでも何が問題だったのか分からず

$ pwd
/cygdrive/c/Windows/Logs/CBS

DESKTOP-TRNV8F8 /cygdrive/c/Windows/Logs/CBS
$ ls -ltr
total 16200
-rwxr-x---+ 1 SYSTEM SYSTEM   883689 Apr 15 10:05 CbsPersist_20210415010926.cab
-rwxr-x---+ 1 SYSTEM SYSTEM      740 Apr 17 12:01 FilterList.log
-rwxr-x---+ 1 SYSTEM SYSTEM 60642221 Apr 17 21:28 CbsPersist_20210417122815.log
-rwxr-x---+ 1 SYSTEM SYSTEM   290495 Apr 17 21:44 CBS.log

DESKTOP-TRNV8F8 /cygdrive/c/Windows/Logs/CBS
$ head -10 CBS.log
2021-04-17 21:28:15, Info                  CBS    TI: --- Initializing Trusted Installer ---
2021-04-17 21:28:15, Info                  CBS    TI: Last boot time: 2021-04-17 21:25:55.500
2021-04-17 21:28:15, Info                  CBS    Starting TrustedInstaller initialization.
2021-04-17 21:28:15, Info                  CBS    Lock: New lock added: CCbsPublicSessionClassFactory, level: 30, total lock:4
2021-04-17 21:28:15, Info                  CBS    Lock: New lock added: CCbsPublicSessionClassFactory, level: 30, total lock:5
2021-04-17 21:28:15, Info                  CBS    Lock: New lock added: WinlogonNotifyLock, level: 8, total lock:6
2021-04-17 21:28:15, Info                  CBS    Ending TrustedInstaller initialization.
2021-04-17 21:28:15, Info                  CBS    Starting the TrustedInstaller main loop.
2021-04-17 21:28:15, Info                  CBS    TrustedInstaller service starts successfully.
2021-04-17 21:28:15, Info                  CBS    No startup processing required, TrustedInstaller service was not set as autostart

DESKTOP-TRNV8F8 /cygdrive/c/Windows/Logs/CBS
$ tail -10 CBS.log
2021-04-17 21:44:19, Info                  CBS    CbsCoreFinalize: CbsEsdUnload
2021-04-17 21:44:19, Info                  CBS    CbsCoreFinalize: CbsTraceInfoUninitialize
2021-04-17 21:44:19, Info                  CBS    CbsCoreFinalize: CbsEventUnregister
2021-04-17 21:44:19, Info                  CBS    CbsCoreFinalize: AppContainerUnload
2021-04-17 21:44:19, Info                  CBS    CbsCoreFinalize: WdsUnload, logging from cbscore will end.
2021-04-17 21:44:19, Info                  CBS    Ending TiWorker finalization.
2021-04-17 21:44:19, Info                  CBS    Ending the TrustedInstaller main loop.
2021-04-17 21:44:19, Info                  CBS    Starting TrustedInstaller finalization.
2021-04-17 21:44:19, Info                  CBS    Lock: Lock removed: WinlogonNotifyLock, level: 8, total lock:6
2021-04-17 21:44:19, Info                  CBS    Ending TrustedInstaller finalization.

はたしてOSが起動できるのか不安なのだが、、再起動しろとあるので再起動してみる。再起動はできた。が、、Windows Updateを確認すると、「2021-04 x64 累積プログラム(KB5001330)を適用するため再起動しろ」と出ている。そこで、もう一度再起動してみる。やっぱり当たらない。ドライバの不整合を回避する手順を導入したから、KB5001330はどうやっても当たらないのかも。どうしたものか。4月のパッチはブルーバックになる症状が報告されているらしい。(あるあるで、)パッチ当てたら不安定になることがあるのは知っていたけど、ブルーバックで起動しなくなるとは。。
障害対応すると勉強にはなるのだけど、土曜日の半日がつぶれてしまった。。しかも、パッチ適用が宙ぶらりんという。。
このままにしておくと、「起動しましょう」と言われ続けるので、、一定の期間は更新しないオプションを有効化した。

■今回の気づき

  1. 回復ポイントに戻してもドライバ異常の場合?は復旧できない
  2. 作成途中の資料やソースでもマメにバックアップを取る(ミラーするぐらいの勢いが必要かも)
  3. アクセス権限が強い(Windows\Users配下か?)と別のPCから吸い上げることができない
  4. エラーコードを指定してググると有用な情報に到達できる(今回だと、0xc000021aで検索)

■ご参考URL
0xc000021aエラー発生時の対処法
エラー 0xc000021a で Windows が起動できない時の対処方法 - ぼくんちのTV 別館

修復コマンドの説明
Windowsのシステム修復機能「sfc /scannow」を試してみよう - ぼくんちのTV 別館

RP2040のPIOで2bitバスで入力を受け付ける

ロータリエンコーダのドライバをPIOで作ってみようと思い、まずは、2bitバスを入力できるように設定してみる。
IN命令により2bit分をPin6,Pin7から入力してISRに格納、PUSH命令でISRからRX FIFOにPUSHする。while文でgetメソッドでFIFOから読み取る。

            PUSH        IN                   2bitバス
[RX FIFO]<---[ISR]<-------(Pin6, Pin7) <-------/---- [ロータリエンコーダ]

以下がテストプログラム。

#
#  PIO  IN  test 
#

from machine import Pin
from rp2 import PIO, StateMachine, asm_pio

PIO_IN_PIN0  = Pin(6, Pin.IN, Pin.PULL_UP)
PIO_IN_PIN1  = Pin(7, Pin.IN, Pin.PULL_UP)

@asm_pio(in_shiftdir=PIO.SHIFT_LEFT)
def ingo():
    in_(pins, 2)
    push()

sm = StateMachine(0, ingo, freq = 2000, in_base=PIO_IN_PIN0)
sm.active(1)

while True:
   print(hex(sm.get()),end="")

実行結果は以下。GP6,GP7はPULL UPしているのでIOに何も接続していない時はHとなり、0x3が続く。ジャンパでGNDに接続するとLになり、0x2,0x1,0x0等に変化する。

0x30x30x30x30x30x30x30x30x30x30x30x30x30x30x30x30x30x30x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x20x00x00x0

RP2040のPIOを引き続き調べる

PIOでロータリエンコーダのドライバを作ってみたいと思い調査
使い慣れているMicroPythonでPIOを叩きたい。やりたいのは、エンコーダからの2本のパラレル信号を受けたいのだが。。簡単に処理するには、2つのIOを束ねてバス幅2bitとして扱いたい。英語表現では、multiple consecutive pins (複数の連続するピン)となって、RP2040のSDKではIOのbaseに加え、バス幅を指定できるようなのだが、、MicroPythonからバス幅を指定できるかどうか。。
MicroPython版のPIOライブラリはあまり仕様の説明がないような。。。
ソースを見ながら推測する(CによるAPI仕様があまり分かっておらず)
Gitのソース*1を参考にしながらrp2.StateMachineで指定可能な引数は以下だろう

prog, freq, jmp_pin, 
in_base, out_base,set_base, sideset_base,
in_shiftdir, out_shiftdir,
push_thresh, pull_thresh,    

かなりできなさそうな印象。

間違っているかもしれんが、Pi Pico C/C++SDKに、sm_config_set_out_pinsの仕様が書かれていて、out_baseがPin番号で、out_countがビット幅と思ってるのだが。。それとも、out_countとは、単にout_baseからのオフセット値??

4.1.15.3.13. sm_config_set_out_pins

static void sm_config_set_out_pins (pio_sm_config *c,
uint out_base, uint out_count)

Picoをロジアナにしてしまうサンプルがあり、ここでもバス幅をcountで指定しているので、入力のIOを束ねることができるようだ。

uint16_t capture_prog_instr = pio_encode_in(pio_pins, pin_count);

rp2040-logic-analyzer/rp2040-logic-analyzer.c at main · gamblor21/rp2040-logic-analyzer · GitHub

これをMicroPythonから設定したいのだが、、

多分無理そうなのでこれ以上は追わない。忘れるので覚書

smオブジェクトへの操作

put FIFO(TX FIFO)への書き込み
get FIFO(RX FIFO)からの読み込み

PIOアセンブラ内で使える命令(主に出力)

pull FIFO(TX FIFO)からシフトレジスタ(OSR)への読み込み
out シフトレジスタ(OSR)から任意のリソースへのシフト

PIOアセンブラ内で使える命令(主に入力)

in シフトレジスタ(ISR)をシフトしてから任意のリソースから読み込み
push シフトレジスタ(ISR)からFIFO(RX FIFO)への書き込み

データ操作

set 任意のリソースへの任意の値の書き込み
mov 任意のリソース間の値の移動

実行制御

jmp 条件付きjump

jmp命令で使える条件

"not_x" (!x) ,  "x_dec"  (x--),    "not_y" (!y),  "y_dec" (y--), "x_not_y"  ( x != y),
"pin":,  "not_osre"  (OSR),

設定できる4系統の入出力

  • in_base(アセンブラ内ではout pinsとして指定(例:in_(pins, 1)),
  • out_base(アセンブラ内ではin pinsとして指定(例:out(pins, 1)),,
  • set_base, (set命令により操作されるPIN (例:set(pins, 0)))
  • sideset_base,(アセンブラ内でsideset操作するとsideset_baseで指定したPINから出力(例:.side(0x1))

分からないのは、、movの時はどの設定が使われる??
仕様書を確認すると、movでsourceがpinsの場合はin_base、destがpinsの場合はout_baseとあった。合理的な設計だ。。

さらに調べていると、、出力はバスとして束ねられるが、入力は束ねられのか?

  • static void sm_config_set_out_pins (pio_sm_config *c, uint out_base, uint out_count)
  • static void sm_config_set_in_pins (pio_sm_config *c, uint in_base)

PIOレジスタ仕様書にも、OUT_COUNTのフィールドがあるけど、IN_COUNTというのがない。だから、、2本の信号を受け取りたかったら、ステートマシンを2つ動かす必要がある??本当??しかし、、ロジアナサンプルでも入力を束ねていたから、それができないはずはない。暗黙で入力はバス幅32なのでは??とも思えるのだが。。そんなはずはないか。

ロジアナサンプルで入力バスを指定しているのは以下の関数

 inline static uint pio_encode_in(enum pio_src_dest src, uint value) {
     valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
     return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, value);
 }

inlineで展開されていて、最後は以下の関数のようだ

inline static uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) {
    valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS)
    uint32_t major = _pio_major_instr_bits(instr_bits);
    if (major == pio_instr_bits_in || major == pio_instr_bits_out) {
        assert(arg2 && arg2 <= 32);
    } else {
        assert(arg2 <= 31);
    }
#endif
    return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
}

参照先
https://raspberrypi.github.io/pico-sdk-doxygen/pio__instructions_8h_source.html

これは、PIOアセンブラなのか??
あらためてソースを読み直すと、、下記となっており、PIO用の命令を生成して、.instructionsに渡している。だから、PIOの命令を使ってバス幅を指定しているようだ。そんな命令あったか?? それにしても興味深い。。PIO命令で入力のバス幅を指定する??そんなの可能か?

    uint16_t capture_prog_instr = pio_encode_in(pio_pins, pin_count);
    struct pio_program capture_prog = {
            .instructions = &capture_prog_instr,
            .length = 1,
            .origin = -1
    };
    uint offset = pio_add_program(pio, &capture_prog);

IN命令を読み直すと、Bit countフィールドを指定すると、in_baseで指定したPinから指定分をシフトしながら読み込んでくれると書かれていた。(in/outのbitってどういう意味かイマイチわからんと思って放置していた)結局そういうことか。

IN always uses the least significant Bit count bits of the source data. For example, if PINCTRL_IN_BASE is set to 5, the
instruction IN 3, PINS will take the values of pins 5, 6 and 7, and shift these into the ISR. First the ISR is shifted to the left
or right to make room for the new input data, then the input data is copied into the gap this leaves. The bit order of the
input data is not dependent on the shift direction.

これは実にありがたい仕様だ。。

IN命令は、常にソースデータの最下位ビットカウントビットを使用します。 たとえば、PINCTRL_IN_BASEが5に設定されている場合、IN 3, PINSの命令を実行すると、ピン5、6、および7の値を取得し、これらをISRにシフトします。 最初にISRが左または右にシフトされて新しい入力データ用のスペースが確保され、次に入力データがこの隙間にコピーされます。 入力データのビット順序はシフト方向に依存しません。

調べてないけど、outも同じような考え方だろうか。。あっちはOUT_COUNTがあるのだが。。
out命令はin命令とちょっと違うようだ。

A 32-bit value is written to Destination: the lower Bit count bits come from the OSR, and the remainder are zeroes.

初めにちゃんとマニュアル読まなかったから遠回りしたけど*2、なんとかドライバ開発ができそうな気がしてきた。応用の効く仕様で実装されていることに感謝!!

MicroPython PIOサンプル
https://github.com/micropython/micropython/tree/master/examples/rp2


安定版だと以下のエラーが出るので、unstable版で試す

=== @asm_pio(in_shiftdir=PIO.SHIFT_LEFT)
=== def ingo():
===     in_(pins, 2)
===     push()
===
===
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "rp2.py", line 228, in asm_pio
  File "rp2.py", line 36, in __init__
ImportError: no module named 'array'

*1:https://github.com/micropython/micropython/blob/master/ports/rp2/rp2_pio.c

*2:しかもなんとなく分からない仕様を放置していた

RP2040のPIOを使ってモールス符号を出力する(その2)

前回の試作では、ドット(・)とダッシュ(ー)のみPIOで出力して、スペースはtimerで待たせていた。このため、FIFOに先読みされてしまって、Pythonによるスペースの待ち時間のタイミングと、PIOによる・ーの発生タイミングがずれる問題があった。これを解消するには、スペースの待ち時間もPIOで処理させる必要があった。その問題を解決したサンプルが以下。ステートマシン内で、ドット(・)、ダッシュ(ー)、スペースを生成させることで、タイミングのずれを解消している。ステートマシンのコードは実質アセンブラなのでどうしてもスパゲッティになってしまう。

from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
import utime

@asm_pio(set_init=PIO.OUT_LOW,out_shiftdir=PIO.SHIFT_RIGHT)
def cond_test():
    set(y, 0x00)
    pull()
    out(x, 4)          # mov 4bit
    jmp(x_not_y,"space")

    #
    label("cw_start")
    out(x,4)           # mov next 4bit to x
    label("dash")
    set(pins, 1) 
    label("dashloop")  
    set(y, 0xf)
    label("waitloop0")
    nop()                [0x1f]   # wait
    jmp(y_dec, "waitloop0")
    jmp(x_dec, "dashloop")
    set(x,0x1)
    jmp("space")

    # 
    label("space_asit")
    out(x,4)           # mov next 4bit to x

    # space
    label("space")
    set(pins, 0)   
    label("spaceloop")
    set(y, 0x14)
    label("waitloop1")
    nop()                [0x1f]   # wait
    jmp(y_dec, "waitloop1")
    jmp(x_dec, "spaceloop")

sm = StateMachine(0, cond_test, freq = 7000, set_base=Pin(25))
sm.active(1)

while True:
  sm.put(0x10)  # dot
  sm.put(0x10)  # dot
  sm.put(0x10)  # dot
  sm.put(0x03)  # space
  sm.put(0x50)  # dash
  sm.put(0x50)  # dash
  sm.put(0x50)  # dash
  sm.put(0x03)  # space

Pico(RP2040)のPIOでモールス点滅サンプルを作ってみた

RP2040のPIOを理解するためいろいろテストしていて、文字列を入れるとモールス符号にして点滅するサンプルを作ってみた。
問題点としては、、点滅パターンをFIFOに入れるのだけど、FIFOでバッファしてしまって先読みのような状態になってcharacter間の空白がうまく働かない。空白をメイン側でwaitしているのがまずい。waitもPIO内で実装するように変えるべき。

#
# CW by PIO of RP2040
#

from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
import utime

LED = 25

CODE = { 'A' : ".-", 
         'B' : "-...",  
         'C' : "-.-.", 
         'D' : "-..", 
         'E' : ".", 
         'F' : "..-.", 
         'G' : "--.", 
         'H' : "....", 
         'I' : "..", 
         'J' : ".---", 
         'K' : "-.-", 
         'L' : ".-..", 
         'M' : "--", 
         'N' : "-.", 
         'O' : "---", 
         'P' : ".--.", 
         'Q' : "--..", 
         'R' : ".-.", 
         'S' : "...", 
         'T' : "-",          
         'U' : "..-", 
         'V' : "...-", 
         'W' : ".--", 
         'X' : "-..-", 
         'Y' : "-.--",  
         'Z' : "--..",  
}


@asm_pio(set_init=PIO.OUT_LOW)
def cw_out():
    pull()
    mov(x, osr)

    # signal (dot or dash)
    set(pins, 1) 
    label("dashloop")  
    set(y, 0xf)
    label("waitloop0")
    nop()                [0x1f]   # wait
    jmp(y_dec, "waitloop0")
    jmp(x_dec, "dashloop")

    # space
    set(pins, 0)   
    set(y, 0x14)
    label("waitloop1")
    nop()                [0x1f]   # wait
    jmp(y_dec, "waitloop1")

sm = StateMachine(0, cw_out, freq = 6000, set_base=Pin(25))
sm.active(1)

def morse(str):
    for ch in str:
        print(ch, end="")
        if ch == " ":
            utime.sleep(3)
        else:
            morse_chr(ch)
            utime.sleep(1.5)

def morse_chr(ch):
    for ptn in CODE[ch]:
        for ch in ptn:
            if ch == '.':
                sm.put(1)
            elif ch == '-':
                sm.put(4)


morse("A B C HELLO")

子供(大学生だが)のノートPCのHDDをSSDに載せ替え

子供のノートPCがHDDアクセス集中で??で動かなくなるとのことで、HDD->SSDの載せ替えをやってみる。
PCはThinkPadのX260で、入っているHDDは、WD5000LPLX 。いつものように、、SSDを買ってきて、外付けディスクとしてマウントしてボリュームコピーして入れ替える。以前載せ替えに使ったのと同じ、WDの2.5インチ500G SSDにする予定。

今入っているHDD:
WD HDD 内蔵ハードディスク 2.5インチ 500GBHDD( WD Black WD5000LPLX SATA3.0 7200rpm 32MB 7.0mm)

載せ替え予定のSSD
Western Digital SSD 500GB WD Blue PC PS4 2.5インチ 内蔵SSD WDS500G2B0A-EC

USB<->SATAの下駄をさしてSSDを接続したが、Dドライブに出てこない*1Windowsの「ディスクの管理」には初期化されてないDドライブが見えているので、ボリューム(パーティションだったか?)を作って、NTFSで初期化した(確か)。この操作により空のDドライブができた。
クローン操作については当初、EaseUSのサイトから無料版バックアップツールをDLしたが、クローン操作も無料では使えないようであった(操作ミスかもしれませんが)。窓の杜からDLすると同じV13.0だが、こちらはクローン操作にロックがかかっておらず問題なくクローン操作できた。
「EaseUS Todo Backup」無料のイメージバックアップソフト - 窓の杜

X260はオプションで内蔵バッテリーを付けたので、BIOSから内蔵バッテリーの電源をOFFにしてから蓋を開ける。確かに、バッテリー側に爪がかみ合わさっている部分がある。開け方としては、ノートの手前側の隙間から段々と広げてゆくように開ける必要あり。奥のバッテリー側から開けようとすると爪を飛ばしてしまうと思う。

X260の裏ブタをはずしたところ。

HDDをはずしてSSDに入れ替えた。

全部組み立ててから起動しないとなるのは嫌なので、仮配線でブートしてみた。エラーが出ることなくOSは起動できた。だが。。SSDなのにあんまり体感的に早くない。娘も、別に変わらんなーという始末。。確かに起動ももっさりしているし、ファイルのセーブも普通だし。クリーンインストールだと速さも違うのだろうけど、今までのHDDも結構いい性能だったということか。。あとは、固まらくなったという改善に期待したい。

というわけで、、ThinkPadの蓋を開けて中身を見ることができたのは良かったけど、SSDに載せ替えしてもあまり体感的なスピードアップは感じられず達成感が得られない結果となった。



■ご参考URL
HDD->SSDミラーリングは無料版のeaseusを使う予定(以下はクローン機能も有償かと)
EaseUS®完璧な無料データバックアップソフト - EaseUS Todo Backup Free
窓の杜からDLしたらクローン機能には鍵かかってなかった。
「EaseUS Todo Backup」無料のイメージバックアップソフト - 窓の杜

*1:前回どうだったか忘れた

Raspberry Pi Picoに搭載されているRP2040のPIOをMicroPythonから叩きたい・・が、、あまり仕様が分からない

RP2040はWiFi/BLEがないので、どう使ったらいいのやらと思っていたけど、プログラミングできるステートマシンが搭載されたPIOが熱いと思う。多分。
CからPIOを叩くのが本筋かもしれないが、コンパイルしないといかんので面倒で、Try&Errorをなんどもやりたい場合はMicroPytonが便利と思う。なんだけど、、MicroPython版でPIOを叩くための情報があまりない。サンプルソースもあるにはあるけど、説明がないので、細かい部分がどうなっているのかわからない。仕様もStateMachine用のアセンブラとちょっと違ってるように思えるのだけど。。Pythonでputを使ってるけど、アセンブラにはPULL/OUTはあるけどPutは無いのでは?? 勉強中だから勘違いかもしれんが。Raspberry Pi Pico Python SDKとかいろいろ仕様書を読むのだけど、MicroPythonの表記法とPIOのハードウエアアーキテクチャが頭の中でリンクしないというか。。

sm.put(ar,8) というのが、8bitを除いて残り24bit(単位がbitかbyteか正確には理解できていません)を渡すということらしいが、、putって一体何・・


■追記
putはTxFIFOへの書き込み操作らしい。RxFIFOからの読み込みは、getの様だ。FIFOのR/W時にどれだけのbit数が欲しいのかを引数で指定するのだろう。多分。(単位はbit? byte??) 該当のソースコードは多分以下なのだが、、Python->Cの呼び出しシーケンスが分かっておらず、読み解けない。。

micropython/rp2_pio.c at master · micropython/micropython · GitHub

// StateMachine.put(value, shift=0)
STATIC mp_obj_t rp2_state_machine_put(size_t n_args, const mp_obj_t *args) {
    rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(args[0]);
    uint32_t shift = 0;
    if (n_args > 2) {
        shift = mp_obj_get_int(args[2]);
    }
    uint32_t data;
    mp_buffer_info_t bufinfo;
    if (!mp_get_buffer(args[1], &bufinfo, MP_BUFFER_READ)) {
        data = mp_obj_get_int_truncated(args[1]);
        bufinfo.buf = &data;
        bufinfo.len = sizeof(uint32_t);
        bufinfo.typecode = 'I';
    }
    const uint8_t *src = bufinfo.buf;
    const uint8_t *src_top = src + bufinfo.len;
    while (src < src_top) {
        uint32_t value;
        if (bufinfo.typecode == 'B' || bufinfo.typecode == BYTEARRAY_TYPECODE) {
            value = *(uint8_t *)src;
            src += sizeof(uint8_t);
        } else if (bufinfo.typecode == 'H') {
            value = *(uint16_t *)src;
            src += sizeof(uint16_t);
        } else if (bufinfo.typecode == 'I') {
            value = *(uint32_t *)src;
            src += sizeof(uint32_t);
        } else {
            mp_raise_ValueError("unsupported buffer type");
        }
        while (pio_sm_is_tx_fifo_full(self->pio, self->sm)) {
            // This delay must be fast.
            mp_handle_pending(true);
            MICROPY_HW_USBDEV_TASK_HOOK
        }
        pio_sm_put(self->pio, self->sm, value << shift);
    }
    return mp_const_none;
}

■追記

jmp命令で使える条件

    # jmp condition constants
    "not_x": 1,
    "x_dec": 2,
    "not_y": 3,
    "y_dec": 4,
    "x_not_y": 5,
    "pin": 6,
    "not_osre": 7,

GitHubより
micropython/rp2.py at master · micropython/micropython · GitHub


■ご参考URL

なんとなく活動記録。様のPIOまとめ記事
Raspberry Pi Pico(RP2040)のPIOについて備忘録(MicroPython)

「Get started with MicroPython on Raspberry Pi Pico」
HackSpace magazine
一見初心者向けの入門書のようだけど、最後の付録の章ではPIOについてもかなり詳しく書いている。これを見ながら勉強したが、、、分かり切らない。