趣味・電子工作のブログ

趣味・電子工作のブログ

Rasberry Pi Picoのデバック実行

下記の記事を見つけたので、VScode上でもデバック実行ができないかなと考えた。

結論としては、「WSL2」上でデバッグツール「gdb-multiarch」と「OpenOCD」を使ってwindowsの「VSCode」からGUIによるデバック実行ができた。

まだ一部改良の余地があるが手順は次の通りとなった。

  1. (初回)picoにpicoproveを書き込む
  2. (初回)WSLへソフトをインストールする。
  3. (毎回)picoをPCに接続する
  4. (毎回)windows のpower shellからwsl(ubuntu)へUSBのブリッジ接続設定をする。
  5. (初回のみ)Ubuntu上でUSBへの接続設定を行う
  6. (毎回)openocdの起動を行う
  7. (毎回)デバックを開始する。

かなり手順が短く、簡単にできる。 また、手順6まで進めばUSBを外さない限りは6,7を繰り返すことでコードの修正、デバックを繰り返すことができる。 必要な部材は、下記のようになっている

Raspberry Pi Picoを二台使用し、一台はdebugerとして使用し、もう一台が動作させるPicoとなる。 Picoをデバッガーにするのは初回のみで、以降は変更しなくてよい。

(初回)picoにpicoproveを書き込む

下記の記事を参考にインストールを行う。 RaspberryPi Picoをデバッガ(PicoProbe)で開発 - Kamuycikap - SentenceDataBase

WSL上で、適当な位置に下記のプロジェクトをクローンする。 GitHub - raspberrypi/picoprobe

git clone https://github.com/raspberrypi/picoprobe.git

クローンを行った後は下記のようなディレクトリとなる。

~/src/repo/picoprobe$ tree -L 1 ./
./
├── CMakeLists.txt
├── pico_sdk_import.cmake
└── src

ビルドを行うが、pico_sdkのパスを環境変数に設定する必要がある。 picoprobe/CMakeLists.txtに下記の一文を書き込むことで、Cmakeによって環境変数を加えられる。

...
cmake_minimum_required(VERSION 3.12)

set(ENV{PICO_SDK_PATH} "${CMAKE_SOURCE_DIR}/pico-sdk" )

include(pico_sdk_import.cmake)
...

set(ENV{PICO_SDK_PATH} "${CMAKE_SOURCE_DIR}/pico-sdk" )"${CMAKE_SOURCE_DIR}/pico-sdk"を変更することで自分の環境に合わせたパスを指定する。 今回は、picoprobeのプロジェクト内にpico-sdkをクローンした。

~/src/repo/picoprobe$git clone https://github.com/raspberrypi/pico-sdk.git
~/src/repo/picoprobe$ tree -L 1 ./
./
├── CMakeLists.txt
├── pico-sdk
├── pico_sdk_import.cmake
└── src

cmakeの拡張からbuildを行う。

f:id:Ikimon:20220208220247p:plain
build完了時のウインドウ

buildが完了すると、build下にpicoprobe.uf2が生成される。

~/src/repo/picoprobe$ tree -L 1 build/
build/
├── CMakeCache.txt
├── CMakeFiles
├── Makefile
├── cmake_install.cmake
├── compile_commands.json
├── elf2uf2
├── generated
├── pico-sdk
├── picoprobe.bin
├── picoprobe.dis
├── picoprobe.elf
├── picoprobe.elf.map
├── picoprobe.hex
├── picoprobe.uf2
├── pioasm
└── probe.pio.h

picoprobe.uf2をdebugger用のPicoに書き込む。

書き込みは前の記事を参考に、接続し、転送を行う。

Raspberry Pi Picoをマウントするには、bootボタンを押したままUSBを接続する。 その後、下記のコマンドを実行する。今回は、windows上でDドライブにRaspberry Pi Picoがマウントされたことを前提としている。

$ sudo mkdir /mnt/d
$ sudo mount -t drvfs D: /mnt/d

上記によって下記のようにlinuxRaspberry Pi Picoがマウントされる。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb        251G  4.6G  234G   2% /
tmpfs           3.1G     0  3.1G   0% /mnt/wsl
tools           238G  201G   38G  85% /init
none            3.1G     0  3.1G   0% /dev
none            3.1G  8.0K  3.1G   1% /run
none            3.1G     0  3.1G   0% /run/lock
none            3.1G     0  3.1G   0% /run/shm
none            3.1G     0  3.1G   0% /run/user
tmpfs           3.1G     0  3.1G   0% /sys/fs/cgroup
drivers         238G  201G   38G  85% /usr/lib/wsl/drivers
lib             238G  201G   38G  85% /usr/lib/wsl/lib
C:\             238G  201G   38G  85% /mnt/c
D:              128M   20K  128M   1% /mnt/d

最後に、$ cp build/src/pico-display/pico_display.uf2 /mnt/d/を行うとPicoにコピーされる。

コピーされたのち、一回Picoを抜いて再度挿すとコピーした実行ファイルが実行される。

(初回)WSLへソフトをインストール・セットアップ

「OpenOCD」と「gdb-multiarch」をWSLへインストールする。 ターミナルを起動して下記コマンドを実行する。

$sudo apt update

$sudo apt install openocd gdb-multiarch

(毎回)picoをPCに接続する

PicoをPCに接続する。

Pico同士の接続は下記のように行う。 左がpicoprobe搭載Picoデバッガー、右がデバック対象のPico

f:id:Ikimon:20220208124429p:plain
picoprobeとデバック対象のPicoの結線図

参照 https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

(毎回)windows のpower shellからwsl(ubuntu)へUSBのブリッジ接続設定をする

接続したときに、windowsとwslのUSBを中継する設定を行う。

環境によってはwindowsのpower shell上でusbipd-winのアップデートを行う必要がある。

> winget install --interactive --exact dorssel.usbipd-win

windowsのpower shell上でWSLと接続できるusbデバイスの情報を下記のコマンドで確認できる。

> usbipd wsl list
BUSID  DEVICE                                                        STATE
2-1    USB シリアル デバイス (COM3), Picoprobe                       Not attached
2-7    TOSHIBA Web Camera - FHD                                      Not attached
2-8    インテル(R) ワイヤレス Bluetooth(R)                           Not attached
3-2    Synaptics FP Sensors (WBF) (PID=0010)                         Not attached

picoprobeをWSLに接続する。

> usbipd wsl attach --busid 2-1

以上で接続できる。

(初回のみ)Ubuntu上でUSBへの接続設定を行う

Ubuntu上で管理者権限無しでpicoprobeにアクセスできるように設定する。 udevadmを使用するがWSLのUbuntu20.04では有効になっていないため有効化する。

balenalib/%%BALENA_MACHINE_NAME%%-ubuntu:focal udevadm issues - openBalena - balenaForums

$ sudo /lib/systemd/systemd-udevd --daemon

次に、picoprobeの接続を管理者権限無しでできるようルールを追加する。

$ sudo nano /etc/udev/rules.d/60-picoprobe.rules 

60-picoprobe.rulesの中

# Raspberry Pi Pico probe
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="0777",TAG+=">

この設定を読み込むために下記のコマンドを実行する。

$ sudo udevadm control --reload-rules 
$ sudo udevadm trigger 

以上でopenocdを使用するときに管理者権限は不要となる。

(毎回)openocdの起動を行う

OpenOCDの起動を行い、GDBとの接続ができるようにしておく。

$ openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl

(毎回)デバックを開始する

VScodeからlaunch.jsonを使用しGDBを起動できるようにする。

下記のリポジトリに例としてLEDチカチカプロジェクトを用意した。

GitHub - ikimon-dev/ledblink

以上でLEDのチカチカをデバック実行できるようにした。

windowsでのraspipicoの開発(続)

windowsでのraspipicoの開発(続)

汎用的なプロジェクト構成を構築

下記の記事で行った環境を使って、より汎用的なプロジェクト構成を構築する。

elehobby.hatenablog.jp

pico-sdkをサブモジュールとして追加し、クローンする。

一つのプロジェクトで完結して構成するため、よりプロジェクト全体を理解しやすくなる。

git submoduleの説明は下記の記事を参考にした。 端的に言うと下記の通り。

外部の git リポジトリを、自分の git リポジトリのサブディレクトリとして登録し、特定の commit を参照する仕組みです。

qiita.com

また、ビルド結果は「out of source ビルド」の考えをもとにbinフォルダに生成する。

qiita.com

生成ファルダとソースフォルダを分離することで、管理しやすくする。

下記がその作成したリポジトリとなる。

github.com

このリポジトリには、サブモジュールが含まれているため、クローンするには、下記のコマンドを使用する。

git clone --recursive https://github.com/ikimon-dev/ledblink.git

もし、 --recursive をつけ忘れてクローンした場合、下記のリンクを参考にgit submodule update --init --recursiveで サブモジュールもクローン出来る。

karoten512.hatenablog.com

クローンすると、下記の通りとなる。

~/src/repo/ledblink$ tree -L 3
.
├── CMakeLists.txt
├── src
│   └── ledblink
│       ├── CMakeLists.txt
│       └── main.c
└── third_party
    └── pico-sdk
        ├── CMakeLists.txt
        ├── CONTRIBUTING.md
        ├── LICENSE.TXT
        ├── README.md
        ├── cmake
        ├── docs
        ├── external
        ├── lib
        ├── pico_sdk_init.cmake
        ├── pico_sdk_version.cmake
        ├── src
        ├── test
        └── tools

ビルドを行うと、buildフォルダが作られ、~/build/src/pico-display/pico_display.elfが生成される。

windowsでのraspipicoの開発環境の構築

下記の手順に関してまとめる。

開発環境の構築

WSLのセットアップ

WSLのセットアップは、公式ページを参考にセットアップを行う。

Windows 10 バージョン 2004 以降 (ビルド 19041 以降) または Windows 11 を実行している必要がある。

docs.microsoft.com

管理者の PowerShell または Windows コマンド プロンプトを起動して、下記のコマンドを実行する。

wsl --install

Ubuntuがインストールされたので次に、Linux ユーザー情報を設定する。 WSL 開発環境を設定する | Microsoft Docs

[スタート] メニューを使用してディストリビューション (既定では Ubuntu) を開き、Linux ディストリビューションのユーザー名とパスワードの作成をする。

パッケージの更新とアップグレードを行う。

sudo apt update && sudo apt upgrade

ここまで出来たら、WSLのセットアップは完了。

WSLは2もあり、バージョンを変更する場合は下記を参照。

WSL のインストール | Microsoft Docs

VScodeのセットアップ

エディタにはVScodeを使用する。 下記からダウンロードとインストールを行う。

azure.microsoft.com

インストールまで行ったら、初めにリモート接続用の拡張機能を追加する。 日本語化は、Japanese Language Pack for Visual Studio Codeをインストールした。 ローカル環境に対して拡張機能タブでc/c++と検索して c/c++ extention packをインストールする。

f:id:Ikimon:20220117231619p:plain
拡張機能タブ

次に、リモートエクスプローラーから、WSLへ接続を行う。

f:id:Ikimon:20220117231753p:plain
リモートエクスプローラータブ

接続を行った後から、リモート先へ拡張機能を追加する。 下記の拡張をインストールした。

上記でエディタの環境構築は終了。

必要なツールのセットアップ

WSL上のUbuntuの環境を構築する。 VScode上から、WSLに接続してUbuntuを操作する。 下記の図のwindow+マークを選択し、wslに接続する。

f:id:Ikimon:20220118082111p:plain
WSLの選択

WSLへの接続が正しくされると下記のように表示される。

f:id:Ikimon:20220118082210p:plain
WSL接続完了

ctrl + @を押すとVScode上でターミナルが起動する。

最初に、パッケージのアップデート・アップグレードを行う。

sudo apt update && sudo apt upgrade

次に必要なパッケージをインストールする。

 sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential git

下記の資料を参考にした。 基本的なことは下記に書いてあり、Raspberry Piからプログラムするのが一般的だが、 現在、とても値上がりしていたり、入手しにくい状況のため、今回は、windowsからの入門にすることとした。

https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html#raspberry-pi-pico-cc-sdk https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf

LEDチカチカまでのプロジェクト作成ビルドまで

手順としては、下記のように行う。

  • pico-sdkをクローンする。
  • CmakeList.txtにインクルード、編集する。
  • C/C++のソースを編集する。
  • ビルドする。
  • Raspberry Pi Picoへ送る
pico-sdkをクローンする。

下記のコマンドを使用して、pico-sdkをクローンする。

git clone https://github.com/raspberrypi/pico-sdk.git

github.com

今回は下記のようなフォルダ構成とする。

$ tree -L 1 ./
./
├── LEDblink
└── pico-sdk
CmakeList.txtにインクルード、編集する。

LEDblinkフォルダ下には下記のようなフォルダ構成とする。

$ tree -L 1 ./LEDblink
./LEDblink
├── CMakeLists.txt
└── src

$ tree ./src
./src
└── pico-display
    ├── CMakeLists.txt
    └── main.c

LEDblink/CMakeLists.txtは下記のようにした。

cmake_minimum_required(VERSION 3.12)

set(ENV{PICO_SDK_PATH} "${HOME}/src/repo/pico/pico-sdk/" )

# Pull in SDK (must be before project)
include(../pico-sdk/external/pico_sdk_import.cmake)

project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")
    message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()

# Initialize the SDK
pico_sdk_init()

add_compile_options(-Wall
        -Wno-format          # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
        -Wno-unused-function # we have some for the docs that aren't called
        -Wno-maybe-uninitialized
        )

add_subdirectory(src/pico-ledblink)

基本的には、サンプルプログラムから引用した。

github.com

注目点は、下記の通り。

  • set(ENV{PICO_SDK_PATH} "${HOME}/src/repo/pico/pico-sdk/" )
  • include(../pico-sdk/external/pico_sdk_import.cmake)
  • add_subdirectory(src/pico-ledblink)

set(ENV{PICO_SDK_PATH} "${HOME}/src/repo/pico/pico-sdk/" )およびinclude(../pico-sdk/external/pico_sdk_import.cmake)は、サンプルを参考にPico-SDK使用するために設定する。

add_subdirectory(src/pico-ledblink)をして、プロジェクトを追加する。

LEDblink/src/CMakeLists.txt下は下記の通り。

add_executable(pico_ledblink
    main.c
    )

# pull in common dependencies
target_link_libraries(pico_ledblink pico_stdlib)

pico_ledblinkのビルドとpico_ledblinkにライブラリをリンクする。

C/C++のソースを編集する。
/**
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "pico/stdlib.h"

#define BACK_LIGHT_PIN 

int main() {
    const uint LED_PIN = PICO_DEFAULT_LED_PIN;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);
    while (true) {
        gpio_put(LED_PIN, 1);
        sleep_ms(250);
        gpio_put(LED_PIN, 0);
        sleep_ms(250);
    }
}

0.25秒おきに点滅するプログラムの完成。

ビルドする。

gcc-arm-none-eabiを使用してビルドを行う。

f:id:Ikimon:20220119211144p:plain
キットのスキャン

キットのスキャンを行い、gcc-arm-none-eabiを選択する。

f:id:Ikimon:20220119211338p:plain
キットとビルド

VScodeのウィンドウ下方に上記のように表示されていればいざ、ビルドする。

ビルドがされるとpico-ledblink.elf.build/src/pico-display/pico_display.elfに生成される。 このまま送っても動作しないため、.uf2に変換する。 変換するには、pico-sdk内にelf2uf2というツールがあるため、このツールを使用して変換する。

pico-sdkのプロジェクトを開き、プロジェクトをビルドする。 キットのスキャンを行い、gcc-arm-none-eabiを選択する。 そしてビルドすると、./pico-sdk/build/elf2uf2/elf2uf2が生成される。

そして、下記のコマンドを使用し.uf2に変換する。

../pico-sdk/build/elf2uf2/elf2uf2 build/src/pico-display/pico_ledblink.elf build/src/pico-display/pico_ledblink.uf2

この変換は、下記のサイトを参考にした。

mickey-happygolucky.hatenablog.com

Raspberry Pi Picoへ送る。

Raspberry Pi Picoをパソコンに接続し、linux内でマウントを行うことで転送する。

qiita.com

上記のサイトを参考にマウントを行った。

Raspberry Pi Picoをマウントするには、bootボタンを押したままUSBを接続する。 その後、下記のコマンドを実行する。今回は、windows上でDドライブにRaspberry Pi Picoがマウントされたことを前提としている。

$ sudo mkdir /mnt/d
$ sudo mount -t drvfs D: /mnt/d

上記によって下記のようにlinuxRaspberry Pi Picoがマウントされる。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb        251G  4.6G  234G   2% /
tmpfs           3.1G     0  3.1G   0% /mnt/wsl
tools           238G  201G   38G  85% /init
none            3.1G     0  3.1G   0% /dev
none            3.1G  8.0K  3.1G   1% /run
none            3.1G     0  3.1G   0% /run/lock
none            3.1G     0  3.1G   0% /run/shm
none            3.1G     0  3.1G   0% /run/user
tmpfs           3.1G     0  3.1G   0% /sys/fs/cgroup
drivers         238G  201G   38G  85% /usr/lib/wsl/drivers
lib             238G  201G   38G  85% /usr/lib/wsl/lib
C:\             238G  201G   38G  85% /mnt/c
D:              128M   20K  128M   1% /mnt/d

最後に、$ cp build/src/pico-display/pico_display.uf2 /mnt/d/を行うとPicoにコピーされる。

コピーされたのち、一回Picoを抜いて再度挿すとコピーした実行ファイルが実行される。