コンシューマー向けロボットへのLinuxポーティングと安定化を1年半手掛けました。コンシューマ向けハードにふさわしいシームレスな起動シークエンスの実装なども行いました。
アピールポイント
- Linux Kernelのデバイスドライバ等のスタックを理解し、カーネルに手を入れて安定性を向上した
- Xilinx ZynqMPで動作するLinux Kernelに手を加えた
- 製品として世に出せるクオリティに作り込むため、ブートローダからLinux Kernel、ひいてはFPGAのロジックまでスタックの全体に手を入れた
- まだLinuxを動作させていない特注基板にDebianをポーティングし、独自のrootfs(Linuxディストリビューション)を構築した
- 電気回路設計者とコミュニケーションをとりながら、電気とソフトの境目を吟味してデバッグした
- FPGAのIPブロックを用いた設計およびVerilog-HDLによるRTL開発ができ、クロックドメインや機能ブロックをトータルで見据えた実装をした
背景
Xilinx ZynqMPを用いた高度な装置(複数のMCUやセンサを含む)の開発案件がありました。FPGAが使用された主な背景は、高負荷な計算のFPGAへのオフロードと、多数の外部ICとのコミュニケーションのために通常のSoCでは用意されていない数のPHY(SPI, I2C, I2S, USB, GbEなど)が必要であったことが挙げられます。
この装置に向けたロジック合成、Linuxディストリビューション(ブートからuserspaceまで)の移植、その後のトラブル対応、仕様変更による追加実装を私が対応しました。
要件
- Xilinx社が提供するYocto Linux BSPからDebianへの移植
- Linux Kernelの移植
- MCUやDSPとの疎通(via SPI, I2S, I2C, etc.)
苦労した実装・バグ
FPGAとLinux Kernelは低レイヤーでの戦いになるため、実装ができてもデバッグがしにくく難攻不落のバグも時々遭遇しました。
苦労した実装: 映像出力回路
液晶画面があり、動作中はGPUで描画されたリッチな情報表示がなされます。しかしFPGAが起動を開始してから10〜30秒間はLinuxのブートが完了しておらず、何も表示できません。これはまずいということでブートシークエンスの各フェーズについて吟味し、最終的に「起動開始の瞬間からFPGA単体で映像信号を生成し、GPUの準備が整ってから映像信号をスイッチする」という実装をしました。
これには映像信号生成回路を手で実装する必要があったためVerilogで記述しました。容量が非常に限られるFPGAロジックへの画像埋め込みのために、減色とRLEを用いた画像圧縮・Verilog変換プログラムをPythonで記述し、現実的なリソース消費量での実装に成功しました。もちろん、映像信号生成部では走査信号に同期してリアルタイムでRLEの伸張を行うようなロジックを実装しています。
苦労したバグ: SPI起因のKernel Panic
一部MCUとの通信においてSPIを用いていました。この物理層はFPGAで実装されていて、極めて高速(SCLK 10MHz+, 300 Bytes/transaction)な通信を行っていました。ある日、「システムを起動してから1時間でKernel Panicする」という問題報告があり調査したところ、ばらつきはあるものの平均50〜100分でKernel Panicが発生していました。
長いデバッグの後、最終的に、SPI PHY内部の送受信バッファが16 Bytesと小さすぎて異常な回数の割込みが発生しており、これがある運の悪いタイミングになるとKernel Panicが発生すると判明しました。バッファ量を増加し、割込み回数の減少を実験的に確認したあとは発生しなくなりました。解決まで実に1ヶ月の時間がかかり、流石に肝を冷やしました。