BeagleBone Black

The official Mender documentation explains how Mender works. This is simply a board-specific complement to the official documentation.

Board description

BeagleBone Black is a low-cost, community-supported development platform for developers and hobbyists based on AM335x 1GHz ARM® Cortex-A8

URL: https://beagleboard.org/black
Wiki: https://elinux.org/Beagleboard:BeagleBoneBlack

Test results

BeagleBone Black is one of the official reference devices of Mender and is easy to get started with. This device is continuously tested as part of Mender testing pipelines which assures high quality of the integration.

The Yocto Project releases in the table below have been tested by the Mender community. Please update it if you have tested this integration on other Yocto Project releases:

Yocto Project Build Runtime
zeus (3.0) :test_works: :test_works:
warrior (2.7) :test_works: :test_works:
thud (2.6) :test_works: :test_works:
sumo (2.5) :test_works: :test_works:

Build Means that the Yocto Project build using this Mender integration completes without errors and outputs images.
Runtime Means that Mender has been verified to work on the board. For U-Boot-based boards, the integration checklist has been verified.

Getting started

Prerequisites

  • A supported Linux distribution and dependencies installed on your workstation/laptop as described in the Yocto Mega Manual
    • NOTE. Instructions depend on which Yocto version you intend to use.
  • Google repo tool installed and in your PATH .

Configuring the build

Set the Yocto Project branch you are building for:

# set to your branch, make sure it is supported (see table above)
BRANCH="warrior" 

Create a directory for your mender-beaglebone setup to live in and clone the meta information.

mkdir mender-beaglebone && cd mender-beaglebone

Initialize repo manifest:

repo init -u https://github.com/mendersoftware/meta-mender-community \
           -m meta-mender-beaglebone/scripts/manifest-beaglebone.xml \
           -b ${BRANCH}

Fetch layers from manifest:

repo sync

Next, initialize the build environment:

source setup-environment beaglebone

Building the image

Build your image by running:

bitbake core-image-base

Replace core-image-base with your desired image target.

Using the build output

After a successful build, the images and build artifacts are placed in tmp/deploy/images/beaglebone-yocto,

  • tmp/deploy/images/beaglebone-yocto/core-image-base-beaglebone-yocto.sdimg
  • tmp/deploy/images/beaglebone-yocto/core-image-base-beaglebone-yocto.mender

The disk image (with .sdimg suffix) is used to provision the device storage for devices without Mender running already. Please proceed to the official documentation on provisioning a new device for steps to do this.

Hint: You may need to hold the Boot Button (S2) (near the SD card slot, but on the other side of the PCB) and, while holding this button, insert the USB/power lead to connect the power in order to force booting from SD card.

On the other hand, if you already have Mender running on your device and want to deploy a rootfs update using this build, you should use the Mender Artifact files, which have .mender suffix. You can either deploy this Artifact in managed mode with the Mender server (upload it under Releases in the server UI) or by using the Mender client standalone mode.


If this post was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!

2 Likes

10 posts were split to a new topic: Typo in BeagleBone Black integration post (Yocto)

5 posts were split to a new topic: Can not find sdimg after successful Yocto build

8 posts were split to a new topic: Issue building Beaglebone Black image in Yocto

2 posts were split to a new topic: Qemu-native build failure in Yocto

Has anyone attempted to use Grub with the BeagleBone?

Mender docs state:

By default, Mender uses GRUB to boot, and this is the recommended bootloader to use, even on platforms that ordinarily use U-Boot. However, U-Boot can be used in cases where using GRUB is not possible or unsuccessful.

So I thought it might be a good idea to try to use Grub with Mender on the BeagleBone but I am trying to figure out how to get started with that.

Hi @pdp7, the default configuration of the Mender integration on the Beaglebone Black is to use Grub as an EFI application to boot. As far as I know, using the steps documented here that should be the default. Have you tried it? I’ve not booted by BBB recently but in the past it used to work.

Drew

I think I making a minor mistake somewhere but I get the error ERROR: Layer 'mender-demo' depends on layer 'openembedded-layer', but this layer is not enabled in your configuration

Here is my transcript running the above instructions:

pdp7@x1:~/dev$ BRANCH="warrior" 
pdp7@x1:~/dev$ mkdir mender-beaglebone && cd mender-beaglebone
pdp7@x1:~/dev/mender-beaglebone$ repo init -u https://github.com/mendersoftware/meta-mender-community \
>            -m meta-mender-beaglebone/scripts/manifest-beaglebone.xml \
>            -b ${BRANCH}
Downloading Repo source from https://gerrit.googlesource.com/git-repo
remote: Counting objects: 1, done
remote: Finding sources: 100% (38/38)
remote: Total 38 (delta 20), reused 38 (delta 20)
Unpacking objects: 100% (38/38), 28.37 KiB | 1.18 MiB/s, done.
Downloading manifest from https://github.com/mendersoftware/meta-mender-community
remote: Enumerating objects: 4217, done.
remote: Counting objects: 100% (491/491), done.
remote: Compressing objects: 100% (321/321), done.
remote: Total 4217 (delta 195), reused 380 (delta 146), pack-reused 3726
Receiving objects: 100% (4217/4217), 1.03 MiB | 21.46 MiB/s, done.
Resolving deltas: 100% (1928/1928), done.

Your identity is: Drew Fustini <drew@pdp7.com>
If you want to change this, please re-run 'repo init' with --config-name

repo has been initialized in /home/pdp7/dev/mender-beaglebone
pdp7@x1:~/dev/mender-beaglebone$ repo sync
Fetching: 100% (3/3), done in 15.404s
Garbage collecting: 100% (3/3), done in 0.005s
repo sync has finished successfully.
pdp7@x1:~/dev/mender-beaglebone$ source setup-environment beaglebone
You had no conf/local.conf file. This configuration file has therefore been
created for you with some default values. You may wish to edit it to, for
example, select a different MACHINE (target hardware). See conf/local.conf
for more information as common configuration options are commented.

You had no conf/bblayers.conf file. This configuration file has therefore been
created for you with some default values. To add additional metadata layers
into your configuration please add entries to conf/bblayers.conf.

The Yocto Project has extensive documentation about OE including a reference
manual which can be found at:
    http://yoctoproject.org/documentation

For more information about OpenEmbedded see their website:
    http://www.openembedded.org/


### Shell environment set up for builds. ###

You can now run 'bitbake <target>'

Common targets are:
    core-image-minimal
    core-image-sato
    meta-toolchain
    meta-ide-support

You can also run generated qemu images with a command like 'runqemu qemux86'
pdp7@x1:~/dev/mender-beaglebone/build$ bitbake core-image-minimal
/home/pdp7/dev/mender-beaglebone/sources/poky/bitbake/lib/bb/fetch2/clearcase.py:148: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if command is 'mkview':
/home/pdp7/dev/mender-beaglebone/sources/poky/bitbake/lib/bb/fetch2/clearcase.py:155: SyntaxWarning: "is" with a literal. Did you mean "=="?
  elif command is 'rmview':
/home/pdp7/dev/mender-beaglebone/sources/poky/bitbake/lib/bb/fetch2/clearcase.py:159: SyntaxWarning: "is" with a literal. Did you mean "=="?
  elif command is 'setcs':
ERROR: Layer 'mender-demo' depends on layer 'openembedded-layer', but this layer is not enabled in your configuration

Summary: There was 1 ERROR message shown, returning a non-zero exit code.
pdp7@x1:~/dev/mender-beaglebone/build$ 

It looks like there was a dependency added on meta-oe to get the jq package but the manifests may not have been updated. You can probably just manually checkout meta-oe on the warrior branch and add it to your bblayers.conf, or temporarily revert that patch. It may then fail to build due to the missing jq dependency though.

@Alan you made that patch. Can you take a look at updating the manifests?

Drew

Maybe it was because of warrior?

I just tried this which uses dunfell in a fresh directory and it did complete ok:

mkdir mender-beaglebone && cd mender-beaglebone
repo init -u https://github.com/mendersoftware/meta-mender-community -m meta-mender-beaglebone/scripts/manifest-beaglebone.xml -b dunfell
repo sync
source setup-environment beaglebone
bitbake core-image-base

It looks like image created ok:

pdp7@x1:/tmp/mender-beaglebone/build/tmp/deploy/images/beaglebone-yocto$ ls *sdimg
core-image-base-beaglebone-yocto-grub-20210809212818.sdimg  core-image-base-beaglebone-yocto-grub.sdimg

Thanks, yes, indeed GRUB is working. I was able to build mender image with dunfell and boot it OK on the BBB.

However, there was some odd error messages about error: can't find command. It doesn’t seem to cause a problem but do you know what would cause that?

U-Boot SPL 2020.01 (Jan 06 2020 - 20:56:31 +0000)
Trying to boot from MMC1


U-Boot 2020.01 (Jan 06 2020 - 20:56:31 +0000)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB
WDT:   Started with servicing (60s timeout)
NAND:  0 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from FAT... *** Warning - bad CRC, using default environment

<ethaddr> not set. Validating first E-fuse MAC
Net:   eth0: ethernet@4a100000
Warning: usb_ether MAC addresses don't match:
Address in ROM is          de:ad:be:ef:00:01
Address in environment is  1c:ba:8c:9b:be:b6
, eth1: usb_ether
Hit any key to stop autoboot:  2  1  0 
switch to partitions #0, OK
mmc0 is current device
SD/MMC found on device 0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
58300 bytes read in 7 ms (7.9 MiB/s)
58300 bytes read in 8 ms (6.9 MiB/s)
Found EFI removable media binary efi/boot/bootarm.efi
e7e[re[999;999He[6ne8Scanning disk mmc@48060000.blk...
Scanning disk mmc@481d8000.blk...
Found 10 disks
BootOrder not defined
EFI boot manager: Cannot load any image
385024 bytes read in 30 ms (12.2 MiB/s)
e[?25he[0;30;47mWelcome to GRUB!



e[0;37;40me[0;37;40me[0;37;40merror: $.

error: syntax error.

error: Incorrect command.

error: syntax error.

error: can't find command `boot/'.

error: can't find command `boot/EFI'.

error: can't find command `boot/EFI/BOOT'.

error: can't find command `boot/EFI/BOOT/bootar'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/grub.c'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/EFI/BOOT/mender'.

error: can't find command `boot/MLO'.

error: can't find command `boot/am335x-bone.dtb'.

error: can't find command `boot/am335x-boneblac'.

error: can't find command `boot/am335x-bonegree'.

error: can't find command `boot/dtb'.

error: can't find command `boot/dtb/am335x-bone'.

error: can't find command `boot/dtb/am335x-bone'.

error: can't find command `boot/dtb/am335x-bone'.

error: can't find command `boot/u-boot.img'.

error: can't find command `boot/zImage'.

lock: OK

lock: OK





EFI stub: Booting Linux Kernel...

EFI stub: Using DTB from configuration table

EFI stub: Exiting boot services and installing virtual address map...

Booting Linux on physical CPU 0x0
Linux version 5.4.58-yocto-standard (oe-user@oe-host) (gcc version 9.3.0 (GCC)) #1 PREEMPT Sun Aug 16 22:40:50 UTC 2020

Full log here:

That’s definitely not right. There seems to be a variable undefined or something in the grub.cfg file. Perhaps @kacf has a clue.

It turns out it was my mistake. I had accidentally written those paths to the ./EFI/BOOT/grub.cfg instead of a file I was trying to paste notes in.

It is now working normally:

U-Boot SPL 2020.01 (Jan 06 2020 - 20:56:31 +0000)
Trying to boot from MMC1


U-Boot 2020.01 (Jan 06 2020 - 20:56:31 +0000)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB
WDT:   Started with servicing (60s timeout)
NAND:  0 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from FAT... *** Warning - bad CRC, using default environment

<ethaddr> not set. Validating first E-fuse MAC
Net:   eth0: ethernet@4a100000
Warning: usb_ether MAC addresses don't match:
Address in ROM is          de:ad:be:ef:00:01
Address in environment is  1c:ba:8c:9b:be:b6
, eth1: usb_ether
Hit any key to stop autoboot:  2  1  0 
switch to partitions #0, OK
mmc0 is current device
SD/MMC found on device 0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
58300 bytes read in 7 ms (7.9 MiB/s)
58300 bytes read in 9 ms (6.2 MiB/s)
Found EFI removable media binary efi/boot/bootarm.efi
e7e[re[999;999He[6ne8Scanning disk mmc@48060000.blk...
Scanning disk mmc@481d8000.blk...
Found 10 disks
BootOrder not defined
EFI boot manager: Cannot load any image
385024 bytes read in 29 ms (12.7 MiB/s)
e[?25he[0;30;47mWelcome to GRUB!



e[0;37;40me[0;37;40me[0;37;40mlock: OK

lock: OK





EFI stub: Booting Linux Kernel...

EFI stub: Using DTB from configuration table

EFI stub: Exiting boot services and installing virtual address map...

Booting Linux on physical CPU 0x0
Linux version 5.4.58-yocto-standard (oe-user@oe-host) (gcc version 9.3.0 (GCC)) #1 PREEMPT Sun Aug 16 22:40:50 UTC 2020

grub.cfg

# Start of ---------- 00_mender_grubenv_defines_grub.cfg ----------
mender_rootfsa_part=2
mender_rootfsb_part=3
mender_kernel_root_base=/dev/mmcblk0p
kernel_imagetype=zImage
# End of ---------- 00_mender_grubenv_defines_grub.cfg ----------
# Start of ---------- 01_console_bootargs_grub.cfg ----------
set console_bootargs="console=tty0,115200n8 console=ttyS0,115200n8 console=ttyO0,115200n8 console=ttyAMA0,115200n8"
# End of ---------- 01_console_bootargs_grub.cfg ----------
# Start of ---------- 02_root_bootargs_grub.cfg ----------
set rootargs="rootwait"
# End of ---------- 02_root_bootargs_grub.cfg ----------
# Start of ---------- 05_mender_setup_grub.cfg ----------
# See the fw_printenv script for how this works.

function maybe_pause {
    # By default we do nothing. debug-pause PACKAGECONFIG replaces this so we
    # can pause at strategic places.
    echo
}

drop_to_grub_prompt="no"
function maybe_drop_to_grub_prompt {
    # By default we do nothing. force-grub-prompt PACKAGECONFIG replaces this so we
    # can bypass boot and stop at the grub prompt.
    echo
}

# Load environment.

MENDER_ENV1=${prefix}/mender_grubenv1/env
MENDER_ENVPREFIX1=${prefix}/mender_grubenv1/
MENDER_LOCK1=${prefix}/mender_grubenv1/lock
MENDER_LOCKSUM1=${prefix}/mender_grubenv1/lock.sha256sum
MENDER_ENV2=${prefix}/mender_grubenv2/env
MENDER_ENVPREFIX2=${prefix}/mender_grubenv2/
MENDER_LOCK2=${prefix}/mender_grubenv2/lock
MENDER_LOCKSUM2=${prefix}/mender_grubenv2/lock.sha256sum

function mender_check_and_restore_env {
    if ! hashsum --hash sha256 --prefix ${MENDER_ENVPREFIX2} --check ${MENDER_LOCKSUM2}; then
        load_env --skip-sig --file ${MENDER_ENV1} bootcount mender_boot_part upgrade_available mender_systemd_machine_id
        save_env --file ${MENDER_ENV2} bootcount mender_boot_part upgrade_available mender_systemd_machine_id
        editing=0
        save_env --file ${MENDER_LOCK2} editing
        if ! hashsum --hash sha256 --prefix ${MENDER_ENVPREFIX2} --check ${MENDER_LOCKSUM2}; then
            echo "Environment 2 still corrupt after attempted restore. Halting."
            halt
        fi
    elif ! hashsum --hash sha256 --prefix ${MENDER_ENVPREFIX1} --check ${MENDER_LOCKSUM1}; then
        load_env --skip-sig --file ${MENDER_ENV2} bootcount mender_boot_part upgrade_available mender_systemd_machine_id
        save_env --file ${MENDER_ENV1} bootcount mender_boot_part upgrade_available mender_systemd_machine_id
        editing=0
        save_env --file ${MENDER_LOCK1} editing
        if ! hashsum --hash sha256 --prefix ${MENDER_ENVPREFIX1} --check ${MENDER_LOCKSUM1}; then
            echo "Environment 1 still corrupt after attempted restore. Halting."
            halt
        fi
    fi
}

function mender_save_env {
    # Save redundant environment.
    editing=1
    save_env --file ${MENDER_LOCK2} editing
    save_env --file ${MENDER_ENV2} bootcount mender_boot_part upgrade_available mender_systemd_machine_id
    editing=0
    save_env --file ${MENDER_LOCK2} editing

    editing=1
    save_env --file ${MENDER_LOCK1} editing
    save_env --file ${MENDER_ENV1} bootcount mender_boot_part upgrade_available mender_systemd_machine_id
    editing=0
    save_env --file ${MENDER_LOCK1} editing
}

function mender_check_grubenv_valid {
    if [ "${mender_boot_part}" != "${mender_rootfsa_part}" -a "${mender_boot_part}" != "${mender_rootfsb_part}" ]; then
        return 1
    fi

    if [ "${bootcount}" != "0" -a "${bootcount}" != "1" ]; then
        return 1
    fi

    if [ "${upgrade_available}" != "0" -a "${upgrade_available}" != "1" ]; then
        return 1
    fi

    return 0
}

mender_check_and_restore_env

# Now load environment.

# Skipping signatures?? Yes, because these values will change over time, so they
# cannot be signed. There is also no checksum facility that will work for
# changing values. Instead we check their content for validity.
load_env --skip-sig --file ${MENDER_ENV1} bootcount mender_boot_part upgrade_available mender_systemd_machine_id

if ! mender_check_grubenv_valid; then
    if [ "${check_signatures}" == "enforce" ]; then
        echo "Unverified environment and signatures enabled. Halting."
        halt
    fi
fi

if [ "${upgrade_available}" = "1" ]; then
    if [ "${bootcount}" != "0" ]; then
        echo "Rolling back..."
        if [ "${mender_boot_part}" = "${mender_rootfsa_part}" ]; then
            mender_boot_part="${mender_rootfsb_part}"
        else
            mender_boot_part="${mender_rootfsa_part}"
        fi
        upgrade_available=0
        bootcount=0
    else
        echo "Booting new update..."
        bootcount=1
    fi

    mender_save_env
fi

regexp (.*),(.*) $root -s mender_grub_storage_device
# End of ---------- 05_mender_setup_grub.cfg ----------
# Start of ---------- 06_systemd_machine_id_grub.cfg ----------
if test -n "${mender_systemd_machine_id}"; then
   systemd_bootargs="systemd.machine_id=${mender_systemd_machine_id}"
fi
# End of ---------- 06_systemd_machine_id_grub.cfg ----------
# Start of ---------- 10_bootargs_grub.cfg ----------
set bootargs="${bootargs} ${console_bootargs} ${rootargs} ${systemd_bootargs}"
# End of ---------- 10_bootargs_grub.cfg ----------
# Start of ---------- 90_mender_boot_grub.cfg ----------
maybe_drop_to_grub_prompt

if [ "${mender_boot_part}" = "${mender_rootfsa_part}" -a test -n "${mender_kernela_part}" ]; then
    mender_ptable_part=${mender_kernela_part}
    mender_kernel_path="(${mender_grub_storage_device},${ptable_type}${mender_kernela_part})"
elif [ "${mender_boot_part}" = "${mender_rootfsb_part}" -a test -n "${mender_kernelb_part}" ]; then
    mender_ptable_part=${mender_kernelb_part}
    mender_kernel_path="(${mender_grub_storage_device},${ptable_type}${mender_kernelb_part})"
else
    mender_ptable_part=${mender_boot_part}
    mender_kernel_path="(${mender_grub_storage_device},${ptable_type}${mender_boot_part})/boot"
fi

if test -e (${mender_grub_storage_device},gpt${mender_ptable_part})/; then
    ptable_type=gpt
else
    ptable_type=msdos
fi

if test -n "${mender_rootfsa_uuid}" -a test -n  "${mender_rootfsb_uuid}"; then
    if [ "${mender_boot_part}" = "${mender_rootfsa_part}" ]; then
        mender_root="PARTUUID=${mender_rootfsa_uuid}"
    elif [ "${mender_boot_part}" = "${mender_rootfsb_part}" ]; then
        mender_root="PARTUUID=${mender_rootfsb_uuid}"
    fi
else
    mender_root="${mender_kernel_root_base}${mender_boot_part}"
fi

if [ "${drop_to_grub_prompt}" = "no" ]; then
    if linux ${mender_kernel_path}/${kernel_imagetype} root=${mender_root} ${bootargs}; then
        if test -n "${initrd_imagetype}" -a test -e ${mender_kernel_path}/${initrd_imagetype}; then
            initrd ${mender_kernel_path}/${initrd_imagetype}
        fi
        maybe_pause "Pausing before booting."
        boot
    fi
    maybe_pause "Pausing after failed boot."
fi
# End of ---------- 90_mender_boot_grub.cfg ----------
# Start of ---------- 95_mender_try_to_recover_grub.cfg ----------
if [ "${drop_to_grub_prompt}" = "no" ]; then
    if [ "${upgrade_available}" == "1" ]; then
        reboot
    fi
fi
# End of ---------- 95_mender_try_to_recover_grub.cfg ----------
# Start of ---------- 99_mender_end_of_grub.cfg ----------
if [ "${drop_to_grub_prompt}" = "yes" ]; then
    echo "Dropping to grub prompt intentionally."
    sleep --interruptible 10 --verbose
else
    echo "Dropping to grub prompt for unknown reason. Should never get here."
    sleep --interruptible 10 --verbose
fi
menuentry 'Dummy Entry for Debug.' 'Wait' {
   echo Menu Entry for debug/command prompt access
}
# End of ---------- 99_mender_end_of_grub.cfg ----------
1 Like