simotin13's message

simotin13といいます。記事の内容でご質問やご意見がありましたらお気軽にコメントしてください\^o^/

yoctoでビルドしたイメージをBeagleBoneBlackで動かす~【kirkstone的令和最新版】~

2019年にyoctoに入門してみたという記事を書いていましたが、久しぶりにyoctoを触ってみると yocto project も4.x系がリリースされており記事を書いた当時と状況が変わっています。

mcommit.hatenadiary.com

2019年に書いた記事の内容に沿って、yoctoでビルドしたイメージをBeagleBoneBlackで動かそうとした動かなかったので改めて最近のyoctoでビルドしたイメージをBeagleBoneBlackで動かす手順について触れておきたいと思います。

kirkstoneを使ったビルド

今回の記事では直近のLTSとして公開されている Kirkstone(4.0)を使ったビルドしてみます。

公式サイトからはQuick Buildの記事が公開されています。
docs.yoctoproject.org

環境構築

$ sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm python3-subunit mesa-common-dev zstd liblz4-tool

Poky の入手

kirkstoneのブランチを指定してcloneします。
ここでは以前の記事と同様に、ホームディレクトリ直下にyoctoというフォルダを作り、その中でPokyをcloneします。
BeagleBoneBlackのビルド用の環境は build_bbb としています。

# ビルド用ディレクトリ作成とpokyの入手
$ cd ~
$ mkdir yocto
$ cd yocto
$ git clone -b kirkstone git://git.yoctoproject.org/poky.git
$ source ./poky/oe-init-build-env build_bbb

local.conf の変更とビルドの実行

BeagleBoneBlackをターゲットとしてビルドする場合、 build_bbb/conf/local.conf の中でコメントアウトされている

MACHINE ?= "beaglebone-yocto"

をコメントインします。この手順は2019年当時と変わっていません。

local.confの変更後、

bitbake core-image-minimal

を実行するとビルドが始まります。
ビルドにかかる時間は使用しているPC環境によると思いますが、手元の環境 CPU:Intel i5-8500、メモリ:16GB、SSD:1TB では2時間程度で完了しました。
ビルドしたときはPCの性能で時間がかかるというよりはカーネルのダウンロードに時間がかかっていました。

重要!SDカードへのイメージの書き込み手順

ビルドまでの手順は基本的に前回の記事とあまり違いはありませんでした。
しかしSDカードへのイメージの書き込み手順については注意が必要です。
背景として、最近(2023年時点)u-bootではuEnv.txtを使ったブートができなくなっており、代わりに extlinux.conf を使ってブートするのが一般的になっているようです。

SDカードのデバイスファイルについて

以下のステップでは、ビルドマシンでSDカードを認識させる必要がありますがここではSDカードが /dev/sdb として認識されているものとしてコマンド例を記載しますが、皆さんの環境に合わせて読みかえてください。

手っ取り早く試したい人向け~ddコマンドによるイメージの書き込み~

ビルドしたイメージをSDカードに書き込み、BeagleBoneBlackで動作させる場合、SDカードのBOOT用のパーティションとrootfs用のパーテイションにいくつかのファイルを配置する必要があります。パーティションの作成を含めるとこれらは微妙に面倒です。

手っ取り早く動かしたい人は ビルド時に生成されたwicファイルをddコマンドで書き込むことで以下の手順を踏まずにイメージを書き込むことができます。

$ cd ~/yocto/build_bbb/tmp/deploy/images/beaglebone-yocto
$ dd if=core-image-minimal-beaglebone-yocto.wic of=/dev/sdb bs=4M

この dd コマンドで書き込みを行った方は、以下のステップは不要です、書き込みが終わったSDカードをBeagleBoneBlackに挿して起動するステップに進んでください。
なお、こちらの手順のデメリットとして、wicファイルではパーティションの構成情報が含まれているため、使用している領域を最大限使用することはできません。rootfs用のパーティションサイズは31MBになっているので大きなファイルを配置することはできないでしょう。

ビルドしたイメージを本格的に使ってみたい場合は、自身でパーティションの設定を行う以降のステップでSDカードのイメージを作成することをお勧めします。

自分でSDカードに必要なファイルを配置していく方法

自分でSDカードにファイルを配置していく場合、大きく以下の3つのステップを行います。

  1. fdisk によるパーティション設定
  2. mkfs によるファイルシステムの作成
  3. パーティションをマウントし必要なファイルをSDカードにコピー

fdisk によるパーティション設定

まずはパーティションの設定からです。ブートローダが使用するBOOTパーティション(FAT32)とrootfsで使用する(ext4)を作成します。
SDカードを開発環境に差し込んで必要なコマンドを実行していきます。

# /dev/sdbは皆さんの環境に合わせて読みかえてください
$ sudo fdisk /dev/sdb

fdsiskは対話的に使用するため、ここでは操作時に入力するコマンドの値の例を記しておきます。

既存パーティションの削除

既に存在するパーティションを d コマンドで削除します。
既存のパーティションが2つある場合コマンド例は以下のようになります。

d
1
d
パーティションの追加

全てのパーティションを削除したら n コマンドでBOOTパーティションとROOTパーテイションを追加します。

コマンド例は

n
p
エンターキー(Partition number デフォルト値:1)
エンターキー(First sector デフォルト値:2048)
+32M

n
p
エンターキー(Partition number デフォルト値:2)
エンターキー(First sector デフォルト値:67584)
エンターキー(Last sector デフォルト値:SDカードの最終セクタ)
BOOTフラグの追加

コマンド例は、

a 
1

のようになります。最初のパーティションにブートフラグが設定されます。

パーティションのタイプの設定

BOOT用のパーティションFAT32にする必要があるため、パーティションのタイプをコマンド例は以下のようになります。

t
1
c 
パーティションの状態確認

上記のようにコマンドを実行し、pコマンドでパーティションの状態を確認すると以下のような状態になっているかと思います。
ちなみにSDカードは16GBのSDカードを使用し、rootfs用のパーティションには残り全ての領域を割り当てた状態です。

Command (m for help): p
Disk /dev/sdb: 14.45 GiB, 15502147584 bytes, 30277632 sectors
Disk model: Storage Device  
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7207759f

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1  *     2048    67583    65536   32M  c W95 FAT32 (LBA)
/dev/sdb2       67584 30277631 30210048 14.4G 83 Linux
設定の書き込み

パーティションの作成が無事完了したら、wコマンドで書き込み内容を反映させてfdiskを終了します。

mkfs によるファイルシステムの作成

パーティション設定が終わったら続いて、mkfsコマンドによりパーティション1をFAT32パーティション2をext4としてファイルシステムを作成します。

# ラベルは BOOT とします
$ sudo mkfs.vfat -n "BOOT" /dev/sdb1

# ラベルは ROOT とします
$ sudo mkfs.ext4 -v -L "ROOT" /dev/sdb2

# 完了後 sync しておく
$ sync

パーティションをマウントし必要なファイルをSDカードにコピー

ファイルシステムが作成出来たら、ビルドしたファイルを各パーティションにコピーしていきます。
パーティション1のBOOT領域にブートローダやデバイスリーファイルなど必要なファイルを配置します。

まずは適当なマウント用ディレクトリを作って/dev/sdb1, /dev/sdb2をマウントします。

$ sudo mkdir -p /media/$USER/BOOT
$ sudo mkdir -p /media/$USER/ROOT
$ sudo mount /dev/sdb1 /media/$USER/BOOT
$ sudo mount /dev/sdb2 /media/$USER/ROOT
必要なファイルをコピー
$ cd ~/yocto/build_bbb/tmp/deploy/images/beaglebone-yocto/
$ sudo cp MLO /media/$USER/BOOT
$ sudo cp u-boot.img /media/$USER/BOOT
$ sudo cp zImage /media/$USER/BOOT
$ sudo cp am335x-bone.dtb /media/$USER/BOOT/
$ sudo cp am335x-boneblack.dtb /media/$USER/BOOT/

ここは2019年当時と変わっていませんね。

extlinux.confの作成

extlinux.confを作成します。ここが重要なポイントになります。
extlinux.confファイルはブートパーテイションのextlinuxというフォルダ以下に配置する必要があります。

まずはフォルダを作ります。

$ mkdir /media/$USER/BOOT/extlinux

続いて extlinux.confというファイルをextlinuxフォルダ内に作成します。
ファイルの内容は以下の通りです。

default Yocto
label Yocto
   kernel /zImage
   fdtdir /
append root=PARTUUID=7207759f-02 rootwait console=ttyS0,115200

こちらのファイルはビルドの成果物のフォルダには存在しませんのでエディタを使うなどして上記内容のファイルを作成してください。
これでBOOTパーテイションへの配置は完了です。

ROOTパーテイションへの配置

yoctoのビルドではtar.bz2形式でrootfs一式が圧縮されていますのでROOTパーティション以下に展開します。

sudo tar -xf core-image-minimal-beaglebone-yocto.tar.bz2 -C /media/$USER/ROOT

これでSDカードへのファイル配置は終わりました。syncした上でSDカードをアンマウントしてください。

$ sync
$ umont  /media/$USER/BOOT
$ umont  /media/$USER/ROOT

実機での起動

SDカードをBeagleBoneBlackに差し込み起動します。
動作確認のためにはUARTのケーブルを実機につないでターミナルソフトで起動ログを確認したり、ターミナルにログインできるようにします。

起動に成功すると以下のようなログが出力されます。

Poky (Yocto Project Reference Distro) 4.0.11 beaglebone-yocto /dev/ttyS0

beaglebone-yocto login:
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 BeagleBone Black
DRAM:  512 MiB
WDT:   Started wdt@44e35000 with servicing (60s timeout)
NAND:  0 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... <ethaddr> not set. Validating first E-fuse MAC
Net:   Could not get PHY for ethernet@4a100000: addr 0
eth2: ethernet@4a100000, eth3: usb_ether
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf
1:      Yocto
Retrieving file: /zImage
append: root=PARTUUID=7207759f-02 rootwait console=ttyS0,115200
Retrieving file: /am335x-boneblack.dtb
Kernel image @ 0x82000000 [ 0x000000 - 0x77b6e8 ]
## Flattened Device Tree blob at 88000000
   Booting using the fdt blob at 0x88000000
   Loading Device Tree to 8ffec000, end 8ffff64e ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 5.15.54-yocto-standard (oe-user@oe-host) (arm-poky-linux-gnueabi-gcc (GCC) 11.3.0, GNU ld (GNU Binutils) 2.38.20220708) #1 PREEMPT Thu Jul 14 18:52:26 UTC 2022
CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
OF: fdt: Machine model: TI AM335x BeagleBone Black
Memory policy: Data cache writeback
cma: Reserved 16 MiB at 0x9e800000
Zone ranges:
  Normal   [mem 0x0000000080000000-0x000000009fefffff]
  HighMem  empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x0000000080000000-0x000000009fefffff]
Initmem setup node 0 [mem 0x0000000080000000-0x000000009fefffff]
CPU: All CPU(s) started in SVC mode.
AM335X ES2.1 (sgx neon)
Built 1 zonelists, mobility grouping on.  Total pages: 129666
Kernel command line: root=PARTUUID=7207759f-02 rootwait console=ttyS0,115200
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
mem auto-init: stack:off, heap alloc:off, heap free:off
Memory: 482236K/523264K available (11264K kernel code, 1552K rwdata, 4080K rodata, 1024K init, 332K bss, 24644K reserved, 16384K cma-reserved, 0K highmem)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
ftrace: allocating 41878 entries in 123 pages
ftrace: allocated 123 pages with 6 groups
trace event string verifier disabled
rcu: Preemptible hierarchical RCU implementation.
rcu:    RCU event tracing is enabled.
        Trampoline variant of Tasks RCU enabled.
        Rude variant of Tasks RCU enabled.
        Tracing variant of Tasks RCU enabled.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
IRQ: Found an INTC at 0x(ptrval) (revision 5.0) with 128 interrupts
TI gptimer clocksource: always-on /ocp/interconnect@44c00000/segment@200000/target-module@31000
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
clocksource: dmtimer: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635851949 ns
TI gptimer clockevent: 24000000 Hz at /ocp/interconnect@48000000/segment@0/target-module@40000
Console: colour dummy device 80x30
Calibrating delay loop... 996.14 BogoMIPS (lpj=4980736)
pid_max: default: 32768 minimum: 301
LSM: Security Framework initializing
landlock: Up and running.
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: using BPIALL workaround
Setting up static identity map for 0x80100000 - 0x80100060
rcu: Hierarchical SRCU implementation.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 3
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: -1, 3072 bytes, linear)
pinctrl core: initialized pinctrl subsystem
NET: Registered PF_NETLINK/PF_ROUTE protocol family
DMA: preallocated 256 KiB pool for atomic coherent allocations
thermal_sys: Registered thermal governor 'step_wise'
cpuidle: using governor ladder
cpuidle: using governor menu
hw-breakpoint: debug architecture 0x4 unsupported.
Serial: AMBA PL011 UART driver
Kprobes globally optimized
raid6: int32x8  gen()   170 MB/s
raid6: int32x8  xor()   105 MB/s
raid6: int32x4  gen()   199 MB/s
raid6: int32x4  xor()   117 MB/s
raid6: int32x2  gen()   367 MB/s
raid6: int32x2  xor()   202 MB/s
raid6: int32x1  gen()   368 MB/s
raid6: int32x1  xor()   173 MB/s
raid6: using algorithm int32x1 gen() 368 MB/s
raid6: .... xor() 173 MB/s, rmw enabled
raid6: using intx1 recovery algorithm
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
clocksource: Switched to clocksource dmtimer
NET: Registered PF_INET protocol family
IP idents hash table entries: 8192 (order: 4, 65536 bytes, linear)
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
TCP established hash table entries: 4096 (order: 2, 16384 bytes, linear)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes, linear)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
NET: Registered PF_UNIX/PF_LOCAL protocol family
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Initialise system trusted keyrings
workingset: timestamp_bits=14 max_order=17 bucket_order=3
NFS: Registering the id_resolver key type
Key type id_resolver registered
Key type id_legacy registered
Key type cifs.idmap registered
xor: measuring software checksum speed
   arm4regs        :  1274 MB/sec
   8regs           :   939 MB/sec
   32regs          :  1273 MB/sec
xor: using function: arm4regs (1274 MB/sec)
Key type asymmetric registered
Asymmetric key parser 'x509' registered
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 248)
io scheduler mq-deadline registered
io scheduler kyber registered
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
brd: module loaded
mtdoops: mtd device (mtddev=name/number) must be supplied
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-omap: OMAP-EHCI Host Controller driver
usbcore: registered new interface driver usb-storage
SPI driver ads7846 has no spi_device_id for ti,tsc2046
SPI driver ads7846 has no spi_device_id for ti,ads7843
SPI driver ads7846 has no spi_device_id for ti,ads7845
SPI driver ads7846 has no spi_device_id for ti,ads7873
i2c_dev: i2c /dev entries driver
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pltfm: SDHCI platform and OF driver helper
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
u32 classifier
    input device check on
    Actions configured
NET: Registered PF_INET6 protocol family
Segment Routing with IPv6
In-situ OAM (IOAM) with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered PF_PACKET protocol family
Bridge firewalling registered
Key type dns_resolver registered
NET: Registered PF_VSOCK protocol family
ThumbEE CPU extension supported.
omap_voltage_late_init: Voltage driver support not added
Loading compiled-in X.509 certificates
Key type ._fscrypt registered
Key type .fscrypt registered
Key type fscrypt-provisioning registered
Btrfs loaded, crc32c=crc32c-generic, zoned=no, fsverity=no
Key type encrypted registered
pinctrl-single 44e10800.pinmux: 142 pins, size 568
ti-sysc: probe of 44e31000.target-module failed with error -16
omap_wdt: OMAP Watchdog Timer Rev 0x01: initial timeout 60 sec
omap_rtc 44e3e000.rtc: registered as rtc0
omap_rtc 44e3e000.rtc: setting system clock to 2000-01-01T00:00:00 UTC (946684800)
ti-sysc: probe of 48040000.target-module failed with error -16
OMAP GPIO hardware version 0.1
omap_i2c 4819c000.i2c: bus 2 rev0.11 at 100 kHz
sdhci-omap 481d8000.mmc: supply vqmmc not found, using dummy regulator
omap_rng 48310000.rng: Random Number Generator ver. 20
random: crng init done
davinci_mdio 4a101000.mdio: davinci mdio revision 1.6, bus freq 1000000
mdio_bus 4a101000.mdio: MDIO device at address 0 is missing.
cpsw-switch 4a100000.switch: initialized cpsw ale version 1.4
cpsw-switch 4a100000.switch: ALE Table size 1024
cpsw-switch 4a100000.switch: Detected MACID = d0:5f:b8:ff:df:4a
cpsw-switch 4a100000.switch: initialized (regs 0x4a100000, pool size 256) hw_ver:0019010C 1.12 (0)
debugfs: Directory '49000000.dma' with parent 'dmaengine' already present!
edma 49000000.dma: TI EDMA DMA engine driver
am335x-phy-driver 47401300.usb-phy: supply vcc not found, using dummy regulator
am335x-phy-driver 47401300.usb-phy: dummy supplies not allowed for exclusive requests
am335x-phy-driver 47401b00.usb-phy: supply vcc not found, using dummy regulator
am335x-phy-driver 47401b00.usb-phy: dummy supplies not allowed for exclusive requests
hw perfevents: enabled with armv7_cortex_a8 PMU driver, 5 counters available
l3-aon-clkctrl:0000:0: failed to disable
printk: console [ttyS0] disabled
44e09000.serial: ttyS0 at MMIO 0x44e09000 (irq = 18, base_baud = 3000000) is a 8250
printk: console [ttyS0] enabled
tps65217-pmic: Failed to locate of_node [id: -1]
tps65217-bl: Failed to locate of_node [id: -1]
tps65217 0-0024: TPS65217 ID 0xe version 1.2
i2c 0-0070: Fixing up cyclic dependency with 4830e000.lcdc
tda998x 0-0070: found TDA19988
omap_i2c 44e0b000.i2c: bus 0 rev0.11 at 400 kHz
omap_gpio 44e07000.gpio: Could not set line 6 debounce to 200000 microseconds (-22)
tilcdc 4830e000.lcdc: bound 0-0070 (ops tda998x_ops)
sdhci-omap 48060000.mmc: Got CD GPIO
[drm] Initialized tilcdc 1.0.0 20121205 for 4830e000.lcdc on minor 0
sdhci-omap 48060000.mmc: supply vqmmc not found, using dummy regulator
tilcdc 4830e000.lcdc: [drm] Cannot find any crtc or sizes
sdhci-omap 481d8000.mmc: supply vqmmc not found, using dummy regulator
musb-hdrc musb-hdrc.1: MUSB HDRC host driver
musb-hdrc musb-hdrc.1: new USB bus registered, assigned bus number 1
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
printk: console [netcon0] enab
                              EXT4-fs (mmcblk0p2): recovery complete
EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null). Quota mode: disabled.
VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
devtmpfs: mounted
Freeing unused kernel image (initmem) memory: 1024K
Run /sbin/init as init process
INIT: version 3.01 booting
Starting udev
udevd[133]: starting version 3.2.10
udevd[134]: starting eudev-3.2.10
EXT4-fs (mmcblk0p2): re-mounted. Opts: (null). Quota mode: disabled.
Fri Mar  9 12:34:56 UTC 2018
INIT: Entering runlevel: 5
Configuring network interfaces... cpsw-switch 4a100000.switch: starting ndev. mode: dual_mac
cpsw-switch 4a100000.switch: phy "/ocp/interconnect@4a000000/segment@0/target-module@100000/switch@0/mdio@1000/ethernet-phy@0" not found on slave 0
udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: broadcasting discover
udhcpc: no lease, forking to background
done.
Starting syslogd/klogd: done

Poky (Yocto Project Reference Distro) 4.0.11 beaglebone-yocto /dev/ttyS0

beaglebone-yocto login: root
root@beaglebone-yocto:~#

まとめ

長くなりましたが kirkstoneでビルドしたイメージをBeagleBoneBlackで動かす手順について書いてみました。
こうして整理してみるとyoctoの変化はあまりないのですが、u-bootの影響を受けているというべきな気がします。
最近のu-bootはUEFIにも対応していて高機能ですね。

yoctoに関する日本語の情報はあまりないのですが、英語だと書籍はいくつか出版されています。

公式サイトの情報はそれなりに充実しているので、使用するPokyのバージョンに合わせてできるだけ読んでいきたいですね。
docs.yoctoproject.org