前回で開発環境が構築できましたので、早速例題を実行してみたいと思います。
Picoの一番の見所はPIO(プログラマブルI/O)と思いますので、まずはPIOを学習したいと思います。

PIOの例題は、いろいろありますが、まずはじめは「hello_pio」から行きたいと思います。
「hello_pio」は基板上のLEDを0.5秒ごとに点滅させるプログラムですが、0.5秒の時間稼ぎはメインCPUが担当して、[1]or[0]の書き込みだけをpioが担当しています。

例題のサンプルプログラムはpicoフォルダーの直下のpico-examplesフォルダーの中に収められています。
フォルダー構造は次のようになっています。(hello_pioの例です)

pico-examples
 |-pio
 | |−hello_pio >> ソースプログラム hello.c など
 |
 |−build
   |−pio
     |−hello_pio >> ここでmakeを実行すると、実行ファイルが
               生成される

まず、編集するためのエディタを立ち上げます。同じ名前で保存するので、上書き保存ができればなんでもOKです。
ソースファイルは、
~/pico/pico-examples/pio/hello_pio/hello.c
ですが、原本を修正するので、念の為、原本のバックアップを取っておきます。
ここでは hello.c.orgとしました。
$ cp ~/pico/pico-examples/pio/hello_pio/hello.c ~/pico/pico-examples/pio/hello_pio/hello.c.org

OpenOCD(SWD経由)で書き込みデバックするので、OpenOCD用picoをターゲット用picoに接続し、RaspberryPiにUSBで接続しておきます。
端末を1つ開き、OpenOCDを起動します。

$ cd ${PICO_SDK_PATH}/../openocd
$ src/openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl

「Info : Listening on port 3333 for gdb connections」が最後に表示されたら端末を最小化しておきます。

また、端末を1つ開きます。コンパイルするために「make」を実行します。
ソースを編集するごとに「make]を実行するので、端末は開いたままにし、エディタで上書き保存したら、makeします。

$ cd ${PICO_SDK_PATH}/../pico-examples
$ cd build/pio/hello_pio
$ make

makeしたら、実行ファイルが生成されているのでgdbで書き込み実行します。
ソースを編集することに実行ファイルを読み込むので、gdbは終了せず、端末は開いたままにします。

$ cd ${PICO_SDK_PATH}/../pico-examples
$ cd build/pio/hello_pio
$ gdb-multiarch hello_pio.elf

gdbで最初にOpenOCDに接続します。

(gdb) target remote localhost:3333

実行ファイルを読み込みます。

(gdb) load

picoをリセットし、実行します。

(gdb) monitor reset init
(gdb) c

実行を停止します。
Ctrlキーを押しながらcキーを押します。

終了するには、detachしたのち、quitします。

(gdb) detach
(gdb) quit

プログラムの確認は次のようになります。
 1、ソースプログラムを編集、上書き保存
 2、makeを実行し、実行ファイルを作成
 3、GDBで、loadで実行ファイル読み込み、monitor reset initでリセット、
   cで実機プログラム実行、Ctrl+cで停止、GDBコマンドでいろいろ確認
 4、納得のいくまで、1から繰り返し!

hell.cでわかったこと

1、PIO pio = pio0;  pioは2グループあるので、pio0及びpio1が指定可能
          一つのpioには4つのステートマシーン(sm)がある。

2、hello_program_init(pio, sm, offset, 22);
  最後の引数は、GPIOの指定なので、GP番号を指定すると、出力端子を変
  えることができる。上の例では、GP22(29pin)に下記のようにLEDを接
  続することで点滅することができる。
   GP22(29pin)−抵抗1KΩ−(アノード)LED(カソード)−GND
3、sleep_ms(500);
  点滅周期を変えられる。単位はmS、上記は500ms
4、pio_sm_put_blocking(pio, sm, 1);
  pio_sm_put_blocking(pio, sm, 0);
  指定のpioの指定のステートマシーン(sm)のFIFOに「1」or「0」を
  送る。

いっぽう、hello.pio(pioアセンブラ)では、
loop:
 pull
 out pins, 1
 jmp loop

となっており、pio_sm_put_blockingからおくられたデータはFIFO(Tx)に保存されているので、pull命令で、FIFO(Tx)からOUTシフトレジスタに転送される。
out pins, 1でOUTシフトレジスタの1bitだけをGPIOピンに出力する。
その繰り返しで、システムクロックでFIFOから1bitだけGPIOへ出力する。

このhello.cとhello.pioでは、まだPIOの真価が発揮されていませんね。
pio_blinkでは、pioで時間稼ぎしているので、メインCPUは、時間稼ぎのプログラムを呼ぶ必要がなくなり、CPUの使用効率が上がります。
次回は、pio_blinkを見てみたいと思います。

おすすめの記事