PlatformIO で Raspberry Pi Pico の PIO の開発をする


## tl; dr

- 公式の Raspberry Pi Pico Platform を使う
- PIO ASM をビルドするには pioasm を使う
- 自動でビルドされるように次の gist を参照する https://gist.github.com/hexeguitar/f4533bc697c956ac1245b6843e2ef438 
- `pico/stdio.h` が解決できないのは、PlatformIO の Arduino Ⅱは含まれていないので、入れる

## 公式の Raspberry Pi Pico Platform を使う

Raspberry Pi Pico と PlatformIO でググると wizio-pico を使う記事が散見されますが、公開されていたリポジトリがなくなっていて、現状どのようにメンテされているかわかりませんでした。wizio-pico の方は、自動で PIO ASM をビルドする機能もあったようです。

ここでは PlatformIO 公式の　Raspberry Pi Pico Platform を使います。

新規 Project の作成で、Raspberry Pi Pico をboardとして選択すると自動でインストールされます。

## PIO ASM

PIO のプログラムには専用のアセンブラ言語書きます。これは PIO ASM と呼ばれています。

PIO ASM をビルドするには、Raspberry Pi Pico の SDK のリポジトリに含まれている pioasm を使います。

次の節で説明するパッケージを利用することで、ビルドツールが どうにかしてビルドしてください。Linuxであれば以下でビルドできます。

```
git clone https://github.com/raspberrypi/pico-sdk
cd pico-sdk/tools/picoasm

make
```

個別にプログラムをビルドするには、出力形式を指定します。

```
pioasm -o c-sdk src/blink.pio blink.pio.h
```


## 自動で PIO ASM がビルドされるようにする

PIO ASM を自動でビルドされるようにするスクリプトが以下の gist で公開されています。

https://gist.github.com/hexeguitar/f4533bc697c956ac1245b6843e2ef438

このスクリプトを利用すると、`pio run -t buildprog` をした時などに自動で変換されるようになります。

このスクリプト中では https://registry.platformio.org/tools/earlephilhower/tool-pioasm-rp2040-earlephilhower のパッケージに含まれている pioasm を利用するようになっています。

## プログラム中で xx.pio.h を読み込ませる

これを組み込んで PlatformIO のビルドをすれば、利用できるようになります。

ただし、Arduinoの場合には、インルードする "hardware/pio.h" から参照される "pico/stdio.h" が見つからずにエラーになります。

```
src/stdio.c:16:10: fatal error: pico/stdio.h: No such file or directory
   16 | #include "pico/stdio.h"
      |          ^~~~~~~~~~~~~~
compilation terminated.
Compiling .pio/build/pico/FrameworkArduino/Tone.cpp.o
*** [.pio/build/pico/src/stdio.c.o] Error 1
```

このコード自体は、以下にあります。

https://github.com/raspberrypi/pico-sdk/tree/master/src/rp2_common/pico_stdio

PlatformIO の framework-arduino-mbed に含まれている pico-sdk には、pico_stdio は含まれていないようです。
とりあえず、src と include に上記リポジトリのディレクトリのファイルを入れてやり過ごしました。

あとは、生成された PIO のバイナリプログラムを呼び出して実行するようにします。

```cpp
#include "Arduino.h"
#include "stdio.h"
#include "blink.pio.h"
#include "hardware/pio.h"
#include "hardware/clocks.h"

void setup()
{
  // copy https://www.digikey.com/en/maker/projects/raspberry-pi-pico-and-rp2040-cc-part-3-how-to-use-pio/123ff7700bc547c79a504858c1bd8110

  static const uint led_pin = 25;
  static const float pio_freq = 2000;

  // PIO インスタンス (0 or 1)
  PIO pio = pio0;

  // ステートマシン取得
  uint sm = pio_claim_unused_sm(pio, true);

  // 複数命令入れる場合 offset が使える
  // が、自動でオフセット入るようではある
  uint offset = pio_add_program(pio, &blink_program);

  // クロックを指定
  float div = (float)clock_get_hz(clk_sys) / pio_freq;

  uint pin = 5;

  // コンフィグ
  pio_sm_config c = blink_program_get_default_config(offset);

  // GPIO を PIO で使うように初期化
  pio_gpio_init(pio, pin);

  // このPIOプログラムで使う最初のピンと、ピンの数を指定
  // PIOにおいてピンは連続した番号でしか使えない
  sm_config_set_set_pins(&c, pin, 1);

  // 各ピンの方向を指定
  // PIOプログラムでもできるか、32命令しか入らないので、事前に指定しておく
  pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);

  // クロック数を指定
  sm_config_set_clkdiv(&c, div);

  // ステートマシンの初期化
  pio_sm_init(pio, sm, offset, &c);

  // ステートマシンの開始
  pio_sm_set_enabled(pio, sm, true);
}

void loop()
{
}
```

## その他にはまったこと

ARM の SBC である Rock5B 上の Linux で開発しようとしたところ、Raspberry Pi Pico Platform がインストールできませんでした。toolchain-gccarmnoneeabi が arrch64 非対応とのことですが、最新のパッケージであれば利用できるため、直接バージョンを指定します。

```toml
# platformio.ini
[env:pico]
platform = raspberrypi
board = pico
framework = arduino
upload_port = /dev/ttyACM0
platform_packages = toolchain-gccarmnoneeabi@~1.100301.220327
extra_scripts = pre:scripts/pioasm.py
```

## おわりに

以上で、PlatformIO の Arduino でも PIO を使うことができました。

## 参考

- PIO の使い方の記事。LチカのPIOのASMも載っている https://www.digikey.com/en/maker/projects/raspberry-pi-pico-and-rp2040-cc-part-3-how-to-use-pio/123ff7700bc547c79a504858c1bd8110
- PlatformIO の extra_script を使ったビルドの解説 https://gist.github.com/hexeguitar/f4533bc697c956ac1245b6843e2ef438