Porting Barebox to the Digi CC-IMX6UL SBC Pro
One of our projects required the addition of board support for the Digi ConnectCore 6UL SBC Pro to the Barebox bootloader. This article outlines the used development setup and required additions to the bootloader to support a board with a well supported processor. Development of the board support was done live during the monthly talks at Stratum 0, the hackerspace in Braunschweig. The video (in German) is embedded at the end of the article.
For the development setup several items are required:
- The evaluation board in question
- Support for console access to the board
- A way to load the bootloader onto the board
- Optionally: a switchable power source
While the first and second item are self-explanatory, the third requires some context. Processors of the i.MX family support a boot mode where they wait for the upload of a binary to the bootloader, which is then loaded into RAM and executed. For the Digi board, this mode is enabled at boot time by shorting the BOOT pin header on the board. Thereafter the board does not boot from internal NAND flash and instead waits for the bootloader upload. The upload is done by using the imx-usb-loader tool which can be enabled in the barebox menu configuration. The switchable power source during development of the board support was a switchable externally powered USB hub. To connect USB power to the barrel connector of the board, an adapter cable was used. The board was shipped with a console adapter cable, and a standard Micro-USB cable was used to connect to the Micro-USB port on the board.
Porting barebox to the new board requires several distinct steps:
- First a new board folder is created and added to the board directory's Makefile. This new Makefile already uses the new Kconfig symbol for the board.
- The Kconfig symbol is added to the correct Kconfig file for the board's architecture.
- Next we enable the device tree support for the board and create a Makefile entry for it as well.
- The used i.MX architecture requires the DCD table entries for the initialization done during the boot ROM. We acquire these from the downstream U-Boot Digi repository.
- Finally, the new image is added to the appropriate image Makefile.
The port is started by copying the board files from a similar board which is already supported by barebox. The PICO Hobbit with a PICO-IMX6UL SoM in arch/arm/boards/technexion-pico-hobbit provides a good starting point for the Digi board. That board folder is copied to a new folder named digi-ccimx6ulsbcpro. The folder itself contains several files:
- flash-header.imxcfg files which contain the DCD table entries
- C files for board and lowlevel support
- a Makefile describing the different objects for prebootloader and barebox
The flash header files can safely be deleted and the Makefile can remain untouched. The files board.c and lowlevel.c require changes for the new board. The PICO Hobbit SoM has multiple memory variants, but our first port for the Digi board will only support one variant. Furthermore, the new Digi board uses a different UART as the main console, this needs to be adjusted in the lowlevel file. The new board folder also needs to be added to arch/arm/boards/Makefile.
Since the Digi board uses an i.MX6UL, the board needs to be added to the mach-imx architecture Kconfig file:
bool "Digi International CC-IMX6UL SBC Pro"
Device Tree Support
Barebox already periodically synchronizes the upstream device trees from the Linux kernel. All which has to be done is to add the barebox specific device nodes to the device tree which will be compiled into our barebox binary. In case of the Digi board, the barebox specific entry is the chosen node for the stdout of barebox:
/* include the upstream device tree from /dts/src/arm/ */
stdout-path = &uart5;
DCD table entries
The DCD tables entries are important for the initialization of the DDR memory controller. The downstream U-Boot of Digi International provides the values for the CC-IMX6UL SoM here. The important parts for the barebox flash header begin with the DATA 4 entries. These entries are copied from the U-Boot configuration file. Then the DATA 4 directives are replaced with wm 32 directives, since the barebox DCD interpreter uses different directives than U-Boot. Additionally, a barebox specific header has to be added:
The loadaddr describes the address where the bootloader will be loaded to on the SoC, on the i.MX6ul 0x80000000 corresponds to the beginning of RAM. Next, the SoC is described and the DCD table offset within the image is defined.
The required entries for the images Makefile are listed here:
pblb-$(CONFIG_MACH_DIGI_CCIMX6ULSBCPRO) += start_imx6ul_ccimx6ulsbcpro
CFG_start_imx6ul_ccimx6ulsbcpro.pblb.imximg = $(board)/digi-ccimx6ulsbcpro/flash-header-imx6ul-ccimx6ulsbcpro.imxcfg
FILE_barebox-imx6ul-ccimx6ulsbcpro.img = start_imx6ul_ccimx6ulsbcpro.pblb.imximg
image-$(CONFIG_MACH_DIGI_CCIMX6ULSBCPRO) += barebox-imx6ul-ccimx6ulsbcpro.img
The first line describes the entry function of the pre-bootloader. This function was created in the lowlevel.c file. The second line describes the flash header to be used for the image, which is compiled into an imximg file. The third line adds the prebootloader image to the barebox image. Finally, the image creation is enabled if the corresponding Kconfig variable is enabled in the configuration.
This concludes the port of barebox to the Digi board. Barebox can now be loaded onto the board with imx-usb-loader and returns a usable prompt. What remains to be tested and added are the following points:
- Support for the OCOTP node to read the persistent MAC address from the device
- Addition of NAND partition nodes to use barebox_update
- Test of the persistent barebox flashed to NAND
- Test of the Ethernet PHYs to verify that network works
After these points have been addressed, the resulting patch can be sent to the mailing list and this blog post will be updated with a link to the patch.
Update: Version 2 of the upstream barebox patch can be found here: http://lists.infradead.org/pipermail/barebox/2019-May/038026.html
The video recorded during the Stratum 0 talks (in german) is embedded here:
The Arria10 SoCFPGA can boot from multiple sources: SD Card, NAND flash, QSPI flash and eMMC, that can be selected via the BSEL pins. If the bootrom can not find a valid bootloader on that medium, it will fall back to JTAG. So for developing and testing, the BSEL pins can just be set to a medium that is non-existent. In case of bootstrapping, the bootrom falls back to JTAG anyway, as there is no valid bootloader, yet.