In this tutorial, we’ll walk you through the process of building a custom Linux kernel tailored specifically for the BeagleBone Black platform. By following these steps, you’ll be able to create a customized embedded Linux distribution optimized for your project’s requirements.
Pre-requisite
Host Machine Environment
$ uname -a
Linux elinlinux 5.4.0-169-generic #187-Ubuntu SMP Thu Nov 23 14:53:38 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux
Target Machine Environment
- Board: BeagleBone Black
- processor: Sitara XAM3359AZCZ100 Cortex A8 ARM
FTDI USB to Serial cable
Which can be found at: http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf
Toolchain
Create workspace
Create a working area to place the tools and components of the system.
cd ~
mkdir beaglebone_workspace
cd beaglebone_workspace
Install require packages
Make sure that your host machine is up to date and install the essential tools, and other tools required for cross compilation.
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential
sudo apt-get install flex bison
sudo apt-get install lzop
sudo apt-get install u-boot-tools
GCC Cross Compiler
sudo apt-get install gcc-arm-linux-gnueabihf
GCC libc source
mkdir arm-toolchain
cd arm-toolchain
wget -c https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
tar xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
Partition Manager
sudo apt-get install gparted
BootLoader (U-boot)
Das U-boot source: https://github.com/u-boot/u-boot
Download u-boot (u-boot-2023.10)
Choose a u-boot version to download.
wget -c https://github.com/u-boot/u-boot/archive/refs/tags/v2023.10.tar.gz
Configure U-Boot
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am335x_boneblack_vboot_defconfig
Compile U-boot
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4
Refer U-Boot: Building with GCC for more information.
MLO
and u-boot.img
After the BootLoader
has been compiled, run the ls
command to make sure that you have the executables MLO
and u-boot.img
. The MLO
file is the first stage BootLoader, and u-boot.img
is the second stage BootLoader also known as the Bootstrap Loader.
Configure Linux Kernel
for BeagleBone Black
Beaglebone Linux Kernel source: https://github.com/beagleboard/linux
Download Linux kernel
Choose a linux kernel version on your demand.
wget -c https://github.com/beagleboard/linux/archive/refs/tags/5.10.168-ti-r76.tar.gz
tar -xvf 5.10.168-ti-r76.tar.gz
Kernel Configuration for BeagleBone Black
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bb.org_defconfig
Build the Kernel
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage dtbs LOADADDR=0x80008000 -j4
Result
Build modules
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4 modules
Refer admin-guide for more information.
Preparing the MicroSD Card
Create two partitions
One partition for booting the kernel, and another one for the
Root File System
.
- Use
gparted
for partitioning. - Create a new partition with 50 MiB for the size. Change the file system type to fat32 and label it boot.
- Add a second partition with 1000 MiB for the size, label it rootfs, and make sure that the file type is ext4.
Root File System
Download Busybox
cd ~/beaglebone_workspace
wget -c https://github.com/mirror/busybox/archive/refs/tags/1_36_0.tar.gz
tar -xvf 1_36_0.tar.gz
Configure BusyBox
cd busybox-1_36_0
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
Enable Build static binary (no shared libs) option
Build BusyBox
Install Busybox into the rootfs partition of your SD card
The build automatically generates a file “busybox.links”, which is used by ‘make install’ to create symlinks to the BusyBox binary for all compiled in commands. This uses the CONFIG_PREFIX environment variable to specify where to install, and installs hardlinks or symlinks depending on the configuration preferences. (You can also manually run the install script at “applets/install.sh”).
Refer busybox: readme for more information.
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- CONFIG_PREFIX=/media/<username>/rootfs/ install
Create required directories and files
create directories and files required by the Linux Kernel
to boot the system
dev/
mkdir dev
sudo mknod dev/console c 5 1
sudo mknod dev/null c 1 3
sudo mknod dev/zero c 1 5
lib/ and usr/lib/
Copy the libraries from the arm toolchain into the root file system lib.
sudo cp -r ~/beaglebone_workspace/arm-toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/* ./lib/
sudo cp -r ~/beaglebone_workspace/arm-toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/* ./lib/
Create additional directories for mounting virtual file systems.
sudo mkdir proc sys root
etc/
sudo mkdir etc etc/init.d
etc/inittab
After the kernel boots, it spawns the first user process, called the init
. init
is a background process that runs unitil the system is shut down. This process requires a configuration file called etc/inittab
, which contains actions the system needs to perform at a given runlevel.
sudo vi etc/inittab
Copy the following into the etc/inittab
file:
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
For more setting options, please refer IBM: inittab File.
etc/fstab
vi etc/fstab
Copy the following into etc/fstab
:
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
For more setting options, please refer man: fstab.
etc/hostname and etc/passwd
Write hostname into it.
sudo vi etc/hostname
sudo vi etc/passwd
Copy root::0:0:root:/root:/bin/sh
into it.
init.d/rcS
Create the file init.d/rcS
to setup the system.
sudo vi etc/init.d/rcS
#!/bin/sh
# ---------------------------------------------
# Common settings
# ---------------------------------------------
# Replace <YOUR_HOSTNAME> with your hostname!
HOSTNAME=<YOUR_HOSTNAME>
VERSION=1.0.0
hostname $HOSTNAME
# ---------------------------------------------
# Prints execution status.
#
# arg1 : Execution status
# arg2 : Continue (0) or Abort (1) on error
# ---------------------------------------------
status ()
{
if [ $1 -eq 0 ] ; then
echo "[SUCCESS]"
else
echo "[FAILED]"
if [ $2 -eq 1 ] ; then
echo "... System init aborted."
exit 1
fi
fi
}
# ---------------------------------------------
# Get verbose
# ---------------------------------------------
echo ""
echo " System initialization..."
echo ""
echo " Hostname : $HOSTNAME"
echo " Filesystem : v$VERSION"
echo ""
echo ""
echo " Kernel release : `uname -s` `uname -r`"
echo " Kernel version : `uname -v`"
echo ""
# ---------------------------------------------
# MDEV Support
# (Requires sysfs support in the kernel)
# ---------------------------------------------
echo -n " Mounting /proc : "
mount -n -t proc /proc /proc
status $? 1
echo -n " Mounting /sys : "
mount -n -t sysfs sysfs /sys
status $? 1
echo -n " Mounting /dev : "
mount -n -t tmpfs mdev /dev
status $? 1
echo -n " Mounting /dev/pts : "
mkdir /dev/pts
mount -t devpts devpts /dev/pts
status $? 1
echo -n " Enabling hot-plug : "
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
status $? 0
echo -n " Populating /dev : "
mkdir /dev/input
mkdir /dev/snd
mdev -s
status $? 0
# ---------------------------------------------
# Mount the default file systems
# ---------------------------------------------
echo -n " Mounting other filesystems : "
mount -a
status $? 0
# ---------------------------------------------
# Set PATH
# ---------------------------------------------
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
# ---------------------------------------------
# Start other daemons
# ---------------------------------------------
echo -n " Starting syslogd : "
/sbin/syslogd
status $? 0
echo -n " Starting telnetd : "
/usr/sbin/telnetd
status $? 0
# ---------------------------------------------
# Done!
# ---------------------------------------------
echo ""
echo "System initialization complete."
Build directory for the kernel
After creating the above files and directories, install the kernel modules into the Root File System
.
cd ~/beaglebone_workspace/linux-5.10.168-ti-r76
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- CONFIG_PREFIX=/media/<username>/rootfs/ modules_install
Refer admin-guide: build-directory-for-the-kernel for more information.
Boot Partition
Create a boot folder in your workspace directory and copy MLO
, u-boot.img
, uImage
, and am335x-boneblack.dbt
.
cd ~/beaglebone_workspace/
mkdir boot
cp u-boot-2023.10/MLO boot/
cp u-boot-2023.10/u-boot.img boot/
cp linux-5.10.168-ti-r76/arch/arm/boot/uImage boot/
cp linux-5.10.168-ti-r76/arch/arm/boot/dts/am335x-boneblack.dtb boot/
uEnv.txt
Go into the boot
folder and create a file called uEnv.txt
. This file will tell the BootLoader
where to load the kernel image and the device binary tree.
vi boot/nEnv.txt
Copy the following into uEnv.txt
:
uenv_addr=0x81000000
load_addr=0x82000000
dtb_addr=0x88000000
mmc_args=setenv bootargs console=ttyO0,115200n8 noinitrd root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait
sdboot=echo Booting from SD Card ...;mmc rescan;fatload mmc 0:1 ${uenv_addr} uEnv.txt;env import -t ${uenv_addr} $filesize;fatload mmc 0:1 ${load_addr} uImage;fatload mmc 0:1 ${dtb_addr} am335x-boneblack.dtb;run mmc_args;bootm ${load_addr} - ${dtb_addr}
uenvcmd=run sdboot
Important: Leave a newline at the end of the uEnv.txt
file.
Finally, copy everything from the ~/beaglebone_workspace/boot
directory to the BOOT
partition of your SD card.
cd ~/beaglebone_workspace/boot/
sudo cp * /media/<username>/BOOT/
sync
Connect FTDI cable with the board
Connect FTDI cable with J1 serial header on the board.
For more information, refer BBB_SRM: 7.5 Serial Header.
Boot result
After you boot up the board, the system should mount the root file system successfully and you should automatically be logged in as root #
.