5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nerves on RPi5: OTA 後のブート時に SPI 初期化が早すぎる問題

Last updated at Posted at 2025-12-01

はじめに

Raspberry Pi 5 + Nerves の環境で、SPI 接続の LCD パネル(3.5")を使っていたときに、

  • mix burn で書き込んだファームウェアからのブート → 正常に表示される
  • mix upload(OTA 更新)したファームウェアからのブート → 画面が真っ黒のまま

という現象に遭遇しました。

ログを見ると、LCD ドライバの初期化中に Circuits.SPI.open/2{:error, :access_denied} を返していて、パターンマッチでクラッシュしていました。

どうやら OTA 経由のブートでは、起動直後にアプリ側が spidev0.0 を開こうとすると、
カーネル側の準備が整う前にアクセスしてしまうことがあるようです。

この問題に対して、リトライすることで安定起動を実現できました。それを軽くメモります。

症状

OTA(mix upload)で更新されたファームウェアからブートした直後、SPI デバイス /dev/spidev0.0 を開こうとした処理で、以下のようなエラーが発生しました。

{:ok, spi} = Circuits.SPI.open("spidev0.0")
# => {:error, :access_denied}

このエラーにより、プロセスがクラッシュし、LCD の初期化処理全体が失敗していました。

対処法

OTA 経由でのブートでは、カーネルが /dev/spidev0.0 をまだ使える状態にしていないうちにアプリ側が SPI を初期化しようとして失敗していると考えられます。

調べてみると、どうも理想的には、以下のような方法でSPI デバイスの準備完了を確認してから初期化すべきようです:

  • nerves_runtime の起動完了を待つ
  • /dev/spidev0.0 の存在やパーミッションをチェックする
  • udev のデバイス準備通知を受け取る仕組みを入れる

今回は依存の少ない簡単な方法として、Circuits.SPI.open/2 に数回リトライ処理を入れることで、アプリが安定して起動するようになりました。

修正後のコード例

リトライ処理を入れた簡易的な対応方法の一例です:

def open_spi(dev, attempts \\ 5)

def open_spi(_dev, 0), do: {:error, :retry_exceeded}

def open_spi(dev, attempts) do
  case Circuits.SPI.open(dev) do
    {:ok, spi} -> {:ok, spi}
    {:error, _reason} ->
      Process.sleep(200)
      open_spi(dev, attempts - 1)
  end
end

失敗しても 200ms 待って再試行することで、
SPI デバイスの準備が整うまで待機できるようにしています。

おわりに

OTA 経由のブート時、SPI デバイスの初期化タイミングによって
Circuits.SPI.open/2 が失敗するという問題に遭遇しました。

今回は簡易的にリトライ処理を入れることで回避しましたが、
場合によりnerves_runtime の初期化完了や /dev/spidev0.0 の状態をより確実に確認する仕組みを検討する必要があるかもしれません。

同様に RPi5 上で SPI デバイスを扱っていて、起動直後に謎のクラッシュに悩まされている方がいれば、本記事が何らかの手がかりになれば嬉しいです。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?