みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

秋月の「アレ」をYoctoProjectで遊ぶ(u-boot起動まで)

はじめに

すべては「ふが」のアイコンでおなじみの某氏からのこんなメッセージから始まった。

本稿の「アレ」とは秋月電子で売っている「無線モジュール付きSoc基板+白色プラスチックケース」という商品のことだ。この時点では購入もしておらず、手を出す気もなかった。しかし煽られた衝動的に購入ボタンをポチッとしてしまった。

※ 2023/3/25時点ですでに通販での取り扱いはなくなっているようだ。

BeagleBone用のイメージを作成

YoctoProjectでBeagleBone向けのイメージを作成する。 使用するブランチはkirkstone。

Pokyの取得

作業ディレクトリの作成し、pokyを取得する。

$ mkdir -p ~/yocto/aki-soc
$ cd ~/yocto/aki-soc
$ git clone git://git.yoctoproject.org/poky.git -b kirkstone

BeagleBoneはPokyのリファレンスボードに入っているため、追加のレイヤは(この時点では)ない。

環境変数の設定

$ source poky/oe-init-build-env

local.conf

MACHINEにbeaglebone-yoctoを設定する。

MACHINE ?= "beaglebone-yocto"
DL_DIR = "${TOPDIR}/../downloads"

ビルド

まず、最低限ブートに必要な機能だけあればよいのでcore-image-minimalを作成する。

$ bitbake core-image-minimal

初回起動(失敗)

SDカードブート

SDカードにイメージを書き込んでブートしてみる。

虚無が見えた。

UARTブート

インターネッツで調べたところ、SDカードを差し込まずに電源を投入するとCCCCCCCCCが出続けるらしい。

これはUART越しにu-bootを送り込んで起動するモードになっていることを示すらしい。

WindowsであればTeraTermで書き込めるらしい。LinuxではFirsts steps with AM335xの方法がわかりやすい。

しかし虚無が見える。

u-bootの修正

このあたりの情報からOSD335Xをカスタム基板でU-bootを動かすまで(メモ)に行き着いて、RobertCNelsonさんのBootloader-Builderを見つけた。

Bootloader-BuilderはAM335x向けのu-bootをビルドするためのツールで、いくつかのパッチを適用している。 Bootloader-Builderで作成したMLOとu-bootを先程作成したcore-image-minimalを書き込んだSDカードのものと差し替えて見るとu-bootまで起動することがわかった。

U-Boot SPL 2021.10-00003-g92b221314b (Mar 23 2023 - 00:00:07 +0900)
Trying to boot from MMC1


U-Boot 2021.10-00003-g92b221314b (Mar 23 2023 - 00:00:07 +0900)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB

このツールで適用しているパッチの中から1つずつ試していき、このパッチが有効であるところまではわかった。

meta-am3352-akiの作成

動くu-bootの作成方法がわかったので、この基板向けのレイヤを作成する。名前は適当に「meta-am3352-aki」とする。

$ bitbake-layers create-layer meta-am3352-aki
$ rm -rf ./meta-am3352-aki/recipes-example
$ bitbake-layers add-layer ./meta-am3352-aki

マシン定義

まずはマシン定義を作成する。

$ mkdir ./meta-am3352-aki/conf/machine

meta-am3352-aki/conf/machine/am3352-aki.confを下記の内容で作成する。

MACHINEOVERRIDES =. "beaglebone-yocto:"
require conf/machine/beaglebone-yocto.conf

とりあえずこれでbeaglebone-yoctoのマシンと同等の内容でam3352-akiというマシンが定義される。

u-bootのレシピ

このパッチをYoctoProjectが提供するu-bootに適用する。そのままでは当たらないので手パッチする。

From 389cc4d07be03ef77614d7b8c8fdb7f8e8aeae9b Mon Sep 17 00:00:00 2001
From: Robert Nelson <robertcnelson@gmail.com>
Date: Thu, 21 Oct 2021 16:06:34 -0500
Subject: [PATCH] NFM-Production-eeprom-assume-device-is-BeagleBone-Bl

Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
Signed-off-by: Yusuke Mitsuki <mickey.happygolucky@gmail.com>
---
 board/ti/am335x/board.c        |  4 ++--
 board/ti/am335x/board.h        |  9 +++++++--
 board/ti/am335x/mux.c          |  6 ++++--
 board/ti/common/board_detect.c | 12 ++++++++++++
 configs/am335x_evm_defconfig   |  2 +-
 include/configs/am335x_evm.h   |  8 ++++++++
 6 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index e8555de9c9..348ca65761 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -272,7 +272,7 @@ const struct dpll_params *get_dpll_ddr_params(void)
 
    if (board_is_evm_sk())
        return &dpll_ddr3_303MHz[ind];
-  else if (board_is_pb() || board_is_bone_lt() || board_is_icev2())
+   else if (board_is_pb() || board_is_bone_lt() || board_is_icev2() || board_is_blank_bone_lt())
        return &dpll_ddr3_400MHz[ind];
    else if (board_is_evm_15_or_later())
        return &dpll_ddr3_303MHz[ind];
@@ -548,7 +548,7 @@ void sdram_init(void)
    if (board_is_evm_sk())
        config_ddr(303, &ioregs_evmsk, &ddr3_data,
               &ddr3_cmd_ctrl_data, &ddr3_emif_reg_data, 0);
-  else if (board_is_pb() || board_is_bone_lt())
+   else if (board_is_pb() || board_is_bone_lt() || board_is_blank_bone_lt())
        config_ddr(400, &ioregs_bonelt,
               &ddr3_beagleblack_data,
               &ddr3_beagleblack_cmd_ctrl_data,
diff --git a/board/ti/am335x/board.h b/board/ti/am335x/board.h
index c2962111c1..0932bf8bfc 100644
--- a/board/ti/am335x/board.h
+++ b/board/ti/am335x/board.h
@@ -48,10 +48,15 @@ static inline int board_is_bben(void)
    return board_is_bone_lt() && !strncmp(board_ti_get_rev(), "SE", 2);
 }
 
+static inline int board_is_blank_bone_lt(void)
+{
+   return board_ti_is("A335BLNK");
+}
+
 static inline int board_is_beaglebonex(void)
 {
-  return board_is_pb() || board_is_bone() || board_is_bone_lt() ||
-         board_is_bbg1() || board_is_bben();
+   return board_is_pb() || board_is_bone() || board_is_bone_lt() || 
+          board_is_bbg1() || board_is_bben() || board_is_blank_bone_lt();
 }
 
 static inline int board_is_evm_sk(void)
diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c
index fed737fa09..9a6cba3733 100644
--- a/board/ti/am335x/mux.c
+++ b/board/ti/am335x/mux.c
@@ -427,7 +427,9 @@ void enable_board_pin_mux(void)
        configure_module_pin_mux(rmii1_pin_mux);
        configure_module_pin_mux(spi0_pin_mux);
    } else {
-      /* Unknown board. We might still be able to boot. */
-      puts("Bad EEPROM or unknown board, cannot configure pinmux.");
+       puts("Unknown board: assuming BeagleBone Black.");
+       configure_module_pin_mux(mii1_pin_mux);
+       configure_module_pin_mux(mmc0_pin_mux);
+       configure_module_pin_mux(mmc1_pin_mux);
    }
 }
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c
index de92eb0981..6008f848c0 100644
--- a/board/ti/common/board_detect.c
+++ b/board/ti/common/board_detect.c
@@ -288,6 +288,17 @@ int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr)
 
    rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
                   sizeof(am_ep), (uint8_t *)&am_ep);
+   if (rc < 0) {
+       ep->header = TI_EEPROM_HEADER_MAGIC;
+
+       strlcpy(ep->name, "A335BLNK", TI_EEPROM_HDR_NAME_LEN + 1);
+       ti_eeprom_string_cleanup(ep->name);
+
+       strlcpy(ep->version, "EMMC", TI_EEPROM_HDR_REV_LEN + 1);
+       ti_eeprom_string_cleanup(ep->version);
+
+       goto already_read;
+   }
    if (rc)
        return rc;
 
@@ -310,6 +321,7 @@ int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr)
    memcpy(ep->mac_addr, am_ep.mac_addr,
           TI_EEPROM_HDR_NO_OF_MAC_ADDR * TI_EEPROM_HDR_ETH_ALEN);
 
+already_read:
    return 0;
 }
 
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 4dc5d0fe34..075e50d066 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -9,7 +9,7 @@ CONFIG_DISTRO_DEFAULTS=y
 CONFIG_SPL_LOAD_FIT=y
 # CONFIG_USE_SPL_FIT_GENERATOR is not set
 CONFIG_OF_BOARD_SETUP=y
-CONFIG_BOOTCOMMAND="run findfdt; run init_console; run finduuid; run distro_bootcmd"
+CONFIG_BOOTCOMMAND="run eeprom_program; run findfdt; run init_console; run finduuid; run distro_bootcmd"
 CONFIG_LOGLEVEL=3
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_ARCH_MISC_INIT=y
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 7fb1b3a3e3..66c614c5b3 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -126,6 +126,14 @@
            "setenv fdtfile am335x-bone.dtb; fi; " \
        "if test $board_name = A335BNLT; then " \
            "setenv fdtfile am335x-boneblack.dtb; fi; " \
+       "if test $board_name = A335BLNK; then " \
+           "if test -e mmc 0:1 /boot/.eeprom.txt; then " \
+               "load mmc 0:1 ${loadaddr} /boot/.eeprom.txt;" \
+               "env import -t ${loadaddr} ${filesize};" \
+               "echo Loaded environment from /boot/.eeprom.txt;" \
+               "run eeprom_program; " \
+           "fi;" \
+           "setenv fdtfile am335x-bonegreen.dtb; fi; " \
        "if test $board_name = A335PBGL; then " \
            "setenv fdtfile am335x-pocketbeagle.dtb; fi; " \
        "if test $board_name = BBBW; then " \
-- 
2.34.1

この内容で/tmp/0001-NFM-Production-eeprom-assume-device-is-BeagleBone-Bl.patchを作成して、次のコマンドを実行する。

$ recipetool appendsrcfile ./meta-am3352-aki virtual/bootloader /tmp/0001-NFM-Production-eeprom-assume-device-is-BeagleBone-Bl.patch

これでu-bootのレシピが作成される。

この状態でcore-image-minimalを作成し、u-bootが起動することを確認する。

U-Boot SPL 2022.01 (Jan 10 2022 - 18:46:34 +0000)
Trying to boot from MMC1


U-Boot 2022.01 (Jan 10 2022 - 18:46:34 +0000)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x EVM
DRAM:  512 MiB
WDT:   Started wdt@44e35000 with servicing (60s timeout)
NAND:  0 MiB
MMC:   OMAP SD/MMC: 0
Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... <ethaC
Net:   eth2: ethernet@4a100000, eth3: usb_ether
Hit any key to stop autoboot:  0 
=> 

この時点でカーネルは起動しない。

まとめ

長くなったので一旦区切る。ここまでのまとめ。

  • ふがさんに煽られたので気絶してポチった
  • BeagleBone向けのイメージで起動すると思ったが起動しなかった
  • RobertCNelsonさん最高!
  • meta-am3352-akiを作った
  • u-bootまでは起動した