i.MX シリーズ向け U-Boot のビルド環境構築と起動手順解説

ブートローダーの役割と移植アーキテクチャ

ARM ベースの Linux 組み込みシステムにおいて、プロセッサの電源投入直後に実行される最初のソフトウェアはブートローダー(Bootloader)である。その主要な責務はクロック初期化、DRAM コントローラのセットアップ、そしてストレージデバイス(eMMC/NAND/SDカード等)からカーネルイメージをメモリ領域へ展開し、エントリポイントをジャンプさせることだ。PC アーキテクチャでいう BIOS/UEFI に相当する存在であり、NXP 製 i.MX シリーズのような SoC では標準的な U-Boot が広く採用されている。

公式レポジトリのソースコードは汎用的なサポートに留まるため、実機開発ではベンダーが独自に HAL やデフォルト設定をオーバーライドしたポートバージョンを使用するのが一般的である。本稿では、i.MX6ULL 系プロセッサを搭載したカスタム評価ボードを対象に、既存の移植版 U-Boot をビルドし、SD メモリ経由で起動させるまでの一連の手順を解説する。

Cross-Compilation 環境の準備とスクリプト最適化

Ninja/Make システムを用いたビルドには ncurses ライブラリが必須となる。Ubuntu ベースのホスト環境であれば以下のコマンドで依存パッケージを導入できる。

sudo apt-get update && sudo apt-get install -y libncurses-dev flex bison

ワークスペースを作成し、配布されたアーカイブを展開する。
以降のビルドフローでは、クロスコンパイラパス、ターゲット構成ファイル、並列ジョブ数を明示的に定義することでミスを防ぎ、再現性を高めるアプローチを取る。

#!/bin/bash
# build_uboot.sh: i.MX6ULL Target U-Boot Build Script

export CROSS_COMPILE="arm-linux-gnueabihf-"
export ARCH="arm"
export TARGET_CONFIG="mx6ull_14x14_ddr512_emmc_defconfig"
export JOB_COUNT=$(nproc) # ホストコア数に基づいて自動調整

echo "[1/3] Cleaning previous build artifacts..."
make distclean

echo "[2/3] Applying target configuration: ${TARGET_CONFIG}"
make "${ARCH} CROSS_COMPILE=${CROSS_COMPILE}" "${TARGET_CONFIG}"

echo "[3/3] Compiling U-Boot (Parallel jobs: ${JOB_COUNT})..."
make V=1 "${ARCH} CROSS_COMPILE=${CROSS_COMPILE}" -j"${JOB_COUNT}"

if [ $? -eq 0 ]; then
    echo "Build completed successfully. Output binary: u-boot.imx"
else
    echo "Build failed. Please check compiler path or dependencies."
    exit 1
fi

このスクリプトは単なるコマンドの羅列ではなく、変数管理とエラーチェックを組み込んだものに変更している。`distclean` で中間ファイルを削除し、`defconfig` でハードウェア固有のオプション(メモリアクセスタイミングや周辺デバイスの有効化)を読み込む。最後に `-j` オプションでマルチコア活用を図る。スクリプトを実行可能にして呼び出す。

chmod +x build_uboot.sh
./build_uboot.sh

イメージヘッダの変換(u-boot.bin → u-boot.imx)

純粋な ELF/binary ファイルである `u-boot.bin` は、i.MX シリーズの ROM プログラムにより直接実行できない。起動プロセスを確立するためには、IVT(Image Vector Table)、DCD(Device Configuration Data)、および BROM ヘッダを含むカプセル化形式に変換する必要がある。これは通常、ツールチェーンに含まれる `mkimage` ユーティリティによって自動化される。

  • IVT: エントリアドレス、データ・タイプ、サイズ等のメタデータを含む構造体。
  • DCD: リフレッシュレートや IO 設定など、外部メモリ初期化のためのビットマップリスト。
  • BROM Header: ブートメディアの種類や読み込み先アドレスを指定する固定フォーマット。

ビルド成功後、ディレクトリルートに生成される `u-boot.imx` が実際に書き込むべき最終イメージとなる。

メディアへの書き込みとファームウェア起動検証

i.MX シリーズのブートマジックを用いた書き込みツール(例:imxdownload または nxptools)を通じて SD カードへ転送する。デバイスノードの誤指定によるデータ破損を防ぐため、以下のように入出力先を厳密に確認する処理を含む。

#!/bin/bash
# flash_sdcard.sh
TARGET_IMG="u-boot.imx"
DEVICE="/dev/mmcblk0" # 実際のマウントポイントに合わせて変更必須

if [ ! -b "$DEVICE" ]; then
    echo "Error: Block device $DEVICE not found."
    echo "Usage: lsblk | grep mmcblk"
    exit 1
fi

chmod +x ./imxdownload
echo "Flashing $TARGET_IMG to $DEVICE ..."
./imxdownload "$TARGET_IMG" "$DEVICE"
echo "Flash operation finished."
sudo sync

書き込み完了後、対象基板の DIP スイッチまたはショートジャンパーを「SD ブート」モードに設定する。USB-TTL ケーブルで UART0 ポートに接続し、ターミナルエミュレータ(baud: 115200, 8N1)を開く。リセットキーを押下すると、以下のような初期化シーケンスが表示される。

U-Boot 2016.03 (Jul 15 2024 - 15:57:22 +0900) for i.MX6ULL-EVK

CPU:   Freescale i.MX6ULL rev1.2 at 396 MHz
Reset cause: POR
Board: MX6ULL 14x14 EVK
I2C:   ready
DRAM:  512 MiB
PMIC:  PFUZE300 DEV_ID=0x33 REVID=0x11
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   FEC1
Hit any key to stop autoboot:  0 
=>

各出力項目の技術的意味合いを以下に整理する。

出力内容技術的意味
rev1.2 at 396MHz silicon revision および現在の CPU クロック周波数。初期状態は低クロック駆動であることが一般的。
Reset cause: PORPower-On Reset による起動を示す。POR_B ピンのロジックハイレベル状態を検出。
FSL_SDHC: 0, 1SysTick 互換の MMC コントローラ検出。コントローラ 0 は外部 SD/MMC、1 は eMMC パスに該当。
*** Warning - bad CRC...NVRAM/EEPROM 内の环境变量に不整合が発生した旨。初回起動時またはフラッシュ消去後に常時表示される。
FEC1Ethernet MAC コントローラが認識された状態。MAC アドレスは U-Boot env の ethaddr で別途割り当てが必要。

カウントダウンタイマー(デフォルト 3 秒)内で Enter キーを入力すると、自動的にカーネル展開フローがスキップされインタラクティブシェルが起動する。ここで環境変数の編集(`setenv`)、ネットワーク転送(`dhcp`/`tftp`)、メモリダイアグニクス(`md`/`mm`)、パーティショニング操作(`fatload`/`ext4load`)などが可能になる。特に `fdt addr` や `bootm` といったサブコマンドは、デバイスツリーブロックの操作や二次ブートロードの実行において必須となる。

タグ: U-Boot cross-compilation NXP-i.MX6ULL embedded-linux BootLoader

7月26日 22:40 投稿