実機を使ったCI – Raspberry Pi 5 × GitHub Actions × STM32

一般的な CI/CD はアプリケーションソフトウェアを対象としていますが、組み込み開発のような低レイヤのソフトウェアでは、GitHub Actions だけでは対応しきれません。特に、マイコンのファームウェア更新のような処理は、実機を伴うためクラウド上の CI では完結しません。

本記事では、GitHub Actions と Raspberry Pi を例に、実機の組み込みLinuxを含めた CI 構築する方法を紹介します。これにより、低レイヤの開発でも自動化を導入し、開発の効率と信頼性を向上させることができます!

用意したもの

RaspberryPi

Github Actionsでトリガーされたジョブを実行します。

またそのジョブの中で、STM32のファームウェア更新をします。

STM32

今回ファームウェア更新される側です。

Best Price Square
¥4,054 (2025/03/23 12:03時点 | Amazon調べ)

準備

UbuntuをインストールしたRaspberryPiの用意

GitHub Actions が sudo を求めるたびにパスワード入力を回避するため、パスワードなしで sudo を実行できるように設定 します。

sudo visudo

以下の行を追加

USERNAMEはRaspberryPiのユーザーネームです。

USERNAME ALL=(ALL) NOPASSWD: ALL

self-hosted runnerの設定

GitHub Actions のジョブを Raspberry Pi 上で直接実行するため、Self-Hosted Runner をセットアップします。

GitHub リポジトリの Settings → Actions → Runners に移動し、New self-hosted runner を選択。

RunnerのイメージにはLinux, ARM64を選択し, Download, Configureのコマンドを実行していきます.

  1. OS: Linux
  2. Architecture: ARM64
  3. 表示されたコマンドを Raspberry Pi で実行

run.shを実行すると, runnerが開始され, githubからのトリガーが来るのを待ち始めます.

GitHub Actions のログ

~/setup/actions-runner$ ./run.sh

√ Connected to GitHub

Current runner version: '2.321.0'
2025-01-19 02:43:25Z: Listening for Jobs

起動直後からサービスとして自動実行したい場合は、下記のコマンドを実行することで登録してくれます。

再起動後もRunnerを常に起動するには、以下のコマンドを実行

~/setup/actions-runner$ sudo ./svc.sh start

下記コマンドでサービスとしての実行状況を確認できます。active(running)であれば動作しています。

~/setup/actions-runner$ sudo ./svc.sh status

Self-Hosted Runner でジョブを実行

まず、GitHub Actions を設定して、Raspberry Pi 上で実行できることを確認しましょう。

.github/workflows/self-hosted-runner.yml

name: Test self-hosted Runner

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    # Runner側のラベルに合わせて指定
    runs-on: [ self-hosted, ARM64, raspi ]

    steps:
      # 1) ソースが必要ならチェックアウト
      - uses: actions/checkout@v3

      # 2) テスト用コマンドを実行
      - name: Just echo something
        run: |
          echo "Hello from Raspberry Pi!"
          uname -a

github actionsの設定ファイルにはruns-on: self-hostedを指定します.

以上の設定はHelloを出力するだけのサンプルソースですが, RaspberryPiで実行してくれます.

GitHub Actions のログ

CIが開始されると下記のように成功, 失敗の状態を表示してくれます.

2025-01-19 02:53:04Z: Running job: build
2025-01-19 02:53:21Z: Job build completed with result: Succeeded

STM32のファームウェア更新をして、テストをしてみる

次に、GitHub に .bin ファイルを push すると、自動で STM32 のファームウェアを更新 するCIを構築します!

.github/workflows/update_firmware.yml

name: Update STM32 Firmware

on:
  push:
    branches:
      - main
    paths:
      - "firmware/*.bin"

jobs:
  update-firmware:
    runs-on: self-hosted  # Raspberry Pi の self-hosted runner で実行

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt install -y stm32flash python3-gpiozero python3-serial

      - name: Run firmware updater
        run: |
          BIN_FILE=$(ls firmware/*.bin | head -n 1)
          echo "Using firmware: $BIN_FILE"
          python3 updater.py --bin "$BIN_FILE" --device /dev/ttyAMA0 --baudrate 115200

GitHub に .bin ファイルを push すると、Raspberry Pi 上の Self-Hosted Runner が updater.py を実行し、STM32 にファームウェアを書き込みます。

GitHub Actions のログ

Run BIN_FILE=$(ls firmware/*.bin | head -n 1)
Using firmware: firmware/test.bin
Entering bootloader mode...
STM32 is now in bootloader mode.
Waiting for /dev/ttyAMA0 to be ready...
/dev/ttyAMA0 is ready.
Flashing firmware...
stm32flash 0.7

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Size         : 11484
Interface serial_posix: 115200 8E1
Version      : 0x31
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0439 (STM32F301xx/F302x4(6/8)/F318xx)
- RAM        : Up to 16KiB  (6144b reserved by bootloader)
- Flash      : Up to 64KiB (size first sector: 2x2048)
- Option RAM : 16b
- System RAM : 8KiB
Write to memory
Erasing memory

Wrote and verified address 0x08000100 (2.23%)
Wrote and verified address 0x08000200 (4.46%)
Wrote and verified address 0x08000300 (6.69%)
Wrote and verified address 0x08000400 (8.92%)
Wrote and verified address 0x08000500 (11.15%)
Wrote and verified address 0x08000600 (13.38%)
Wrote and verified address 0x08000700 (15.60%)
Wrote and verified address 0x08000800 (17.83%)
Wrote and verified address 0x08000900 (20.06%)
Wrote and verified address 0x08000a00 (22.29%)
Wrote and verified address 0x08000b00 (24.52%)
Wrote and verified address 0x08000c00 (26.75%)
Wrote and verified address 0x08000d00 (28.98%)
Wrote and verified address 0x08000e00 (31.21%)
Wrote and verified address 0x08000f00 (33.44%)
Wrote and verified address 0x08001000 (35.67%)
Wrote and verified address 0x08001100 (37.90%)
Wrote and verified address 0x08001200 (40.13%)
Wrote and verified address 0x08001300 (42.35%)
Wrote and verified address 0x08001400 (44.58%)
Wrote and verified address 0x08001500 (46.81%)
Wrote and verified address 0x08001600 (49.04%)
Wrote and verified address 0x08001700 (51.27%)
Wrote and verified address 0x08001800 (53.50%)
Wrote and verified address 0x08001900 (55.73%)
Wrote and verified address 0x08001a00 (57.96%)
Wrote and verified address 0x08001b00 (60.19%)
Wrote and verified address 0x08001c00 (62.42%)
Wrote and verified address 0x08001d00 (64.65%)
Wrote and verified address 0x08001e00 (66.88%)
Wrote and verified address 0x08001f00 (69.10%)
Wrote and verified address 0x08002000 (71.33%)
Wrote and verified address 0x08002100 (73.56%)
Wrote and verified address 0x08002200 (75.79%)
Wrote and verified address 0x08002300 (78.02%)
Wrote and verified address 0x08002400 (80.25%)
Wrote and verified address 0x08002500 (82.48%)
Wrote and verified address 0x08002600 (84.71%)
Wrote and verified address 0x08002700 (86.94%)
Wrote and verified address 0x08002800 (89.17%)
Wrote and verified address 0x08002900 (91.40%)
Wrote and verified address 0x08002a00 (93.63%)
Wrote and verified address 0x08002b00 (95.86%)
Wrote and verified address 0x08002c00 (98.08%)
Wrote and verified address 0x08002cdc (100.00%) Done.
Firmware flashed successfully!
Firmware update succeeded.
Running application...
STM32 is now running the application.

まとめ

この仕組みを導入すれば、リモートでのファームウェア管理が効率化され、製品の保守性も向上します!

Raspberry Pi を Self-Hosted Runner に設定

  • GitHub Actions のジョブを Raspberry Pi で直接実行できる
  • run.sh を systemd や svc.sh で自動起動可能

GitHub Actions を活用して STM32 の CI/CD

  • .bin ファイルを push すると自動で Raspberry Pi に転送
  • stm32flash で STM32 のファームウェアを更新