Build kernel and bootloader for your embedded board (PART 1)
This is the first part of series, Libretech tritium Board Bringup.
There can be times when you wonder, what is the actual sequence of commands which initiates the boot-up process of a board, starting from bootloader till the filesystem once the board is powered on.
Well, after spending quiet a time searching and googling, I somewhat got an idea of that stuff. So, let’s see what I found.
So, here we’ll build bootloader and kernel(bare minimum) from source and boot the board using them.
The following commands and code-snippets have been tested on Ubuntu 18.04.
Following is the checklist before continuing
- An embedded board, (in my case, libretech all-h3-cc h2+)
- Serial to USB connector (with 3 volts output), with jumper cables, which will be used for debugging and executing commands on board.
- A formatted sdcard, to flash bootloader
- A USB, to power the board (pretty obvious, right?)
So, to run commands on board, we would need a serial terminal emulator (such as minicom), which can be installed as follows
sudo apt install minicom
If you don’t have git install, then run this
sudo apt install git
Install cross compiler toolchain and other dependencies
sudo apt install bison flex swig gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
So, let’s start with bootloader(u-boot)
Cloning and building u-boot
git clone git://git.denx.de/u-boot.git u-boot
Now, lets build it. Move into cloned u-boot directory and continue.
Create build configuration
Configuration files for almost all the boards is found in u-boot/configs/, find corresponding defconfig file for your board and replace libretech_all_h3_cc_h2_plus_defconfig in following command.
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- libretech_all_h3_cc_h2_plus_defconfig
Change .config file generated for partition number
This one is something I had to do because, u-boot was unable to find kernel image on sdcard. You might or might not need it, but if you have same board as mine, you definitely should do this.
sed -i ‘s/CONFIG_ENV_FAT_DEVICE_AND_PART=.*/CONFIG_ENV_FAT_DEVICE_AND_PART=”0:auto”/g’ .config
Finally, build the bootloader
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
Flashing u-boot to sdcard
After the build is complete, you will see some new files in u-boot directory. But we need to focus on just 1 or maybe 2, depending on how you proceed to flash.
Connect sdcard to host computer/ laptop and flash u-boot
Depending upon how your sdcard is connected, your device name will change in following commands. If you have an sdcard slot in laptop, it’ll be something like `/dev/mmcblkX` (X can be 0, 1, 2…), and if you use sdcard reader, it’ll be `/dev/sdX` (X can be b, c, d…). So modify following command accordingly.
Run any of the following 2 command blocks
Flash SPL and u-boot together
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8 status=progress
Flash SPL and u-boot separately
sudo dd if=spl/sunxi-spl.bin of=/dev/sdX bs=1024 seek=8 status=progress
sudo dd if=u-boot.img of=/dev/sdX bs=1024 seek=40 status=progress
Checking u-boot
Plug in sdcard in board’s sdcard slot.
Connect UART pins on board to Serial to USB connector. In following manner
GND — GNDRX — TXTX — RX
Configure minicom for ttyUSB0 port with baudrate 115200 and hardware flow control to NO. Plug in and start minicom.
Power up the board and you should get something like this in console
If there’s nothing on console, try swapping RT-TX on either of the ends.
Hit enter or any key to enter u-boot console. Here you can try all the commands u-boot supports. We will use this console to boot the board once we have the kernel image ready.
Now, lets head towards kernel
Cloning and building linux-kernel 4.18 and device-tree
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git -b linux-4.18.y linux
Now, lets build it. We will build the bare minimum linux kernel with default configuration for now. Move into cloned linux directory and continue.
Create build configuration
Since we are building for an ARM device, required defconfig file can be found in arch/arm/configs/. Replace the one corresponding with your board in following command
make ARCH=arm sunxi_defconfig
Build kernel zImage
Based on the number of cpus in your computer, change the number after -j in following command
make -j 8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage
Now sit back and wait, this is gonna take some time…
Build device tree
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
Copy kernel image and device tree to sdcard
Considering you are following this guide from beginning, your sdcard should be having u-boot already flashed. Otherwise, flash u-boot before continuing
Mount sdcard, change your sdcard device accordingly
sudo mount /dev/sdX1 /mnt
Copy kernel Image
sudo cp arch/arm/boot/zImage /mnt/zImage
Copy device tree blob
Change the sun8i-h2-plus-libretech-all-h3-cc.dtb file, in case you have another board
sudo cp arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dtb /mnt/device_tree.dtb
Unmount sdcard
sudo umount /mnt
Testing kernel image
- Plug sdcard into the board
- Start minicom after connecting USB to serial connector
- Power up the board and hit any key to enter u-boot console as before
- Load kernel image and device tree into memory.
Finding memory addresses for kernel and device tree
Before loading kernel and device tree into memory, you need to find out the memory addresses allocated for kernel image and device tree for your board configuration.
Run following commands in u-boot terminal, to find expected memory addresses.
printenv
Now look for a key like kernel_addr_r in terminal output, that is the memory address for kernel image.
And look for a key like fdt_addr_r in output, that is the memory address for device tree.
Now load kernel and device tree into corresponding memory address as follows, you can change variables $kernel_addr_r and $fdt_addr_r to memory addresses found above.
mmc rescan
load mmc 0:1 $kernel_addr_r zImage
load mmc 0:1 $fdt_addr_r device_tree.dtb
Now finally boot with following command
bootz $kernel_addr_r — $fdt_addr_r
Now you will start seeing logs for Starting kernel, which will eventually get stuck at a kernel panic.
But it’s fine, as we haven’t build a filesystem for the kernel to continue.
So now you have build u-boot and kernel which are capable of booting up your board.
So, in the next one, we’ll build a filesystem image and use the bootloader and kernel build above to properly boot up the board.
Part 2 is available here
Cheers.