Yocto: using U-Boot as bootloader with a RaspberryPi Zero
This is a guide about building and configuring a Yocto build for a raspberry pi zero with u-boot.
Yocto and Repo
You can obtain an out-of-the-box configured Yocto tree using a manifest in the following way
$ mkdir rpi-yocto && cd rpi-yocto $ repo init -u https://github.com/gipi/rpi0-repo -b sumo $ repo sync $ source sources/oe-init-build-env build/ $ bitbake rpi-basic-image $ sudo dd if=tmp/deploy/images/raspberrypi0/rpi-basic-image-raspberrypi0.rpi-sdimg of=/dev/sdd $ bitbake rpi-basic-image -c populate_sdk
This way of configuring a project composed of multiple git repositories is inspired of the
way Android works: there is manifest (i.e. a simple XML
file) containing the description
of the repository with the specific revision and path that is needed to checkout in order
to have a correctly configured project. In my case I created a manifest with the minimal
layers in order to boot up a raspberry pi zero with U-Boot
and configured to enable
the debugging via JTAG
.
In the rest of the post I try to summarize how this is done.
U-Boot
U-Boot
is a bootloader, i.e. a program that is used to setup the essential peripherals
(like RAM and flash) and to load the intended kernel with the correct parameters.
In order to use it with meta-raspberry
you need only to set in local.conf
the following
RPI_USE_U_BOOT = "1"
Since I want to save the manual procedure for future use, what follows is the explanation for the configuration, if you use the layer indicated above all this is unecessary.
Boot sequence
The raspberry pi, in particular the Broadcom chip, follows this sequence to bootup
- stage 1: is the on-chip ROM, loads stage2 in the L2 cache
-
stage 2: is
bootcode.bin
. Enable SDRAM and loads stage 3 -
stage 3: is
loader.bin
. It loadsstart.elf
-
start.elf
loadskernel.img
kernel.img
is usually the linux kernel, we want to substitute it with u-boot
.
This is achievable renaming accordingly the file or changing the right variable (named kernel
)
in the config.txt
file. cmdline.txt
instead contains the arguments for the kernel.
cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait console=tty0
The complicated thing that happens with this device is that the start.elf
prepare
already the fdt
(flat device tree) at a specific address and doesn't need to be loaded from the
SD card. The address is passed as environment variable in u-boot
.
Take in mind that some document uses fdt_addr_r
instead of the mainline's fdt_addr
.
Configuration
If you don't have already u-boot
compiled you can use Yocto via these variables
PREFERRED_PROVIDER_virtual/bootloader = "u-boot" KERNEL_IMAGETYPE = "zImage" KERNEL_BOOTCMD = "bootz"
The command to boot are indicated in
boot.cmd
that is obtained compiling boot.scr
fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs fatload mmc 0:1 ${kernel_addr_r} zImage bootz ${kernel_addr_r} - ${fdt_addr}
GPIOs
For future use I want to set the pins needed to use JTAG
with the board.
The chip of the raspberry pi has 54 pins configurable via 41 32-bit registers; the start
address is different between board models, for a pi zero is 0x7e200000
but to use
it directly to modify the registers is a pain in the ass.
There are several options to go with to set the desired pins, each one needs (but the first one)
a recent version of the firmware (you can see the version of your system using vcgencmd version
)
- create a device driver and move the pins using it
dt-blob.bin
-
config.txt
and itsgpio
variable
The simplest way (with a modern firmware) is to use the last option: in my case I can
add directly in the config.txt
the following lines
gpio=22-27=a4
or using the layer meta-raspberrypi
you can set it via the RPI_EXTRA_CONFIG
variable in your local.conf
.
In order to check if all is ok you can use the wiringpi
library and in particular
the gpio
program in the running system:
root@raspberrypi0:~# gpio readall +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5v | | | | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | | 27 | 2 | GPIO. 2 | ALT4 | 0 | 13 || 14 | | | 0v | | | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | ALT4 | GPIO. 5 | 5 | 24 | | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | ALT4 | GPIO. 6 | 6 | 25 | | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | | | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 | | 26 | 25 | GPIO.25 | ALT4 | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+-Pi Zero--+---+------+---------+-----+-----+
How you can see the configuration is correct.
Links
- RPi Boot flow
- DEVICE TREES, OVERLAYS, AND PARAMETERS
- Zero Client: Boot kernel and root filesystem from network with a Raspberry Pi2 or Pi3
- https://www.denx.de/wiki/view/DULG/UBootEnvVariables
- https://www.denx.de/wiki/DULG/UBootCmdFDT
- https://elinux.org/RPi_U-Boot#Test_U-Boot
- https://dius.com.au/2015/08/19/raspberry-pi-uboot/
- https://bootlin.com/blog/dt-overlay-uboot-libfdt/
- https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md
- https://www.raspberrypi.org/documentation/configuration/pin-configuration.md
- https://www.mjoldfield.com/atelier/2017/03/rpi-devicetree.html
- https://pinout.xyz/pinout/jtag
- https://www.suse.com/c/debugging-raspberry-pi-3-with-jtag/
- https://sysprogs.com/VisualKernel/tutorials/raspberry/jtagsetup/
- https://media.readthedocs.org/pdf/meta-raspberrypi/latest/meta-raspberrypi.pdf
- https://github.com/FrankBau/raspi-repo-manifest/wiki
- https://www.yoctoproject.org/docs/2.4.2/dev-manual/dev-manual.html#creating-partitioned-images-using-wic
- https://www.yoctoproject.org/docs/2.4.2/dev-manual/dev-manual.html#flashing-images-using-bmaptool
- https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_Zero_1p3_reduced.pdf
- https://cdn.sparkfun.com/assets/learn_tutorials/6/7/6/PiZero_1.pdf
- https://elinux.org/RPI_vcgencmd_usage
- https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
- http://www.pieter-jan.com/node/15
post if you want to use Yocto to build all from scratch.
Comments
Comments powered by Disqus