[My] Embedded Workshop

Running current Linux on an “old” ARM board from scratch

Overview and Goal
Here’s my final project for the course “EECS_X497.10: Fundamentals of Embedded Linux”.
The project consists in bringing up an ‘old’ ARM board and getting it to boot a modern version of Linux. The board chosen for this project is the ‘Cosmic Board+’ developed by Phytec in 2013. It’s based around a NXP Vybrid SoC, VF6xx family. This Soc features 2 cores, one ARM Cortex A5 running at 500MHz, and a Cortex M4 running at 167MHz, 256MB DRAM and 512MB Flash. It features board support for several peripherals , such as 2xUSB 2.0, 1x RS-232 UART, 10/100 Ethernet, micro HDMI, and a high count header(2x60pin expansion connectors) with several SPIs, I2Cs, ADCs, and GPIOs.

The board

What makes this project interesting to me is the educational side of it. This board came with almost no upstream support at the time, and not much documentation from the vendor. It was shipped originally with Linux 3.10, with a forked version of u-boot, all ready on a microSD card. It’s been a long time since then, and I’ve lost the card and the board needs some love. The goal of this project is to build a modern system, using latest u-boot,Linux 4.15 kernel, and a rootfs compiled with a current toolchain (GCC 7.X), small enough to work around the device limitations(small RAM).

== Questions: ==
– [X] How to boot the board?
– The board can boot from NAND flash and from the micro SD, depending on the boot pins configuration.
* Apparently, the board can boot from other devices(SPI-flash,UART/USB0), but it’s limited by the ‘Carrier board’ to just the two.
– [X] How to use u-boot with this board?
– Because one of the main goals is to boot everything with up-to-date software. I downloaded the u-boot git repository from https://github.com/u-boot/u-boot.git .
– The old sourcecode apparently had a u-boot fork, because it wasn’t supported in mainline at the time. Fortunately, now it is.
– After grepping for anything in the u-boot source with the word ‘vybrid'(the processor family), I came out with several mentions of ‘pcm052’,
which is the name of the main board product number. Grepping for that, I found a config file!!!
– The I run the appropiate commands:

$ export CROSS_COMPILE=arm-none-eabi-
$ make pcm052_defconfig
$ make u-boot.imx

– To test if this worked with the board. I used a clean microSD, and copied the u-boot.imx file at 0x400.

# dd if=u-boot.imx of=/dev/<sd-card> bs=1k seek=1

– I connected the board’s Serial port to my usb2serial adapter, accessed picocom and presto.

U-Boot 2018.03-00090-g735f397c14 (Mar 16 2018 - 14:01:46 -0500)

CPU: Freescale Vybrid VF610 at 396 MHz
Reset cause: EXTERNAL RESET
Model: Phytec phyCORE-Vybrid
Board: PCM-052
I2C: ready
DRAM: 256 MiB
NAND: 512 MiB
MMC: FSL_SDHC: 0
Loading Environment from NAND... *** Warning - bad CRC, using default environment

Failed (-5)
In: serial@40028000
Out: serial@40028000
Err: serial@40028000
Net: CPU Net Initialization Failed
No ethernet found.
Hit any key to stop autoboot: 0
=>

– Apparently there are some issues with NAND, and ethernet.., but everything else is just fine.
– The CPU information matches the info of my board. I dont know if this info is all hardcoded, or at least the amount of memory and peripherals is polled at runtime. I’ll need to take a look at that.
– [ ] What’s the difference between u-boot.imx and u-boot.bin?

UPDATE #1:
– [X] Why is the following warning showing during boot? “Loading Environment from NAND… *** Warning – bad CRC, using default environment”
The previous u-boot output is clear about two things: one, it is configured to try to load the kernel from NAND flash by default. And two, it is NOT finding the kernel there. Because I dont want to recompile u-boot and change the default configuration, at least for now, I will stop autoboot by ‘Hitting any key’ and, after looking for an alternative, I found all the environment variables of the current u-boot build(printenv command). One of which is ‘bootcmd_sd’, which expands to the following commands:

fatload mmc 0:1 ${kernel_addr} ${kernel_file}
fatload mmc 0:1 ${fdt_addr} ${fdt_file}
bootz ${kernel_addr} - ${fdt_addr}

This searches for files named(in this case) zImage, and zImage.dtb in the first partition of the mmc0(SD card) and copies them to RAM, and then bootz executes the kernel with the device tree blob. *This partition needs to be a FAT partition for the command to work apparently. Haven’t tried it with another filesystem.
This means that, to continue with the boot process, I need to give this command everything it needs. So now I need to compile the Linux kernel for my board.

– [X] How to compile Linux for my particular board?
– Originally I planned to compile the kernel along the with rootfs using buildroot, but there were some issues so I decided to compile it by myself. The process was relatively easy, after finding the right config file for the processor:

$ export CROSS_COMPILE=arm-none-eabi-
$ export ARCH=arm
$ make imx_v6_v7_defconfig

*this config file was found after grepping for any config file that had the words ‘vybrid’ and/or ‘vf6’ in their git history.

$ make zImage

– Then, I had to compile the device tree files(.dts):

$ make dtbs

– This last command compiles ALL device tree files, which is probably the wrong way of doing it, since I only need 2 files for testing right now: vf610m4-cosmic.dts and vf610-cosmic.dts. This files as well were found by grepping in the linux git repository for keywords related to the chosen processor and board.

*miniupdate: the correct syntax for building single .dtb files is:

make ARCH=arm CROSS_COMPILE=arm-none-eabi- vf610-cosmic.dtb vf610m4-cosmic.dtb

– Now, with this two files. I just need to copy them to the recently created FAT partition (partition1).
– Now let’s test if u-boot actually reads this two files, when I changed their names to the ones u-boot expects and copied them to the boot partition.

(...)
=> run bootcmd_sd
7167200 bytes read in 368 ms (18.6 MiB/s)
14520 bytes read in 15 ms (945.3 KiB/s)
Kernel image @ 0x82000000 [ 0x000000 - 0x6d5ce0 ]
## Flattened Device Tree blob at 81000000
   Booting using the fdt blob at 0x81000000
   Using Device Tree in place at 81000000, end 810068b7

Starting kernel ...

Now u-boot is receiving the files it needs and is copying them to RAM, writing this message and trying to boot the kernel, I dont know if the kernel is actually booting correctly though, because it just stays there. Also, there is no root filesystem yet.

UPDATE #2:
– [X] How to create a root filesystem for this board? and, is the lack of a rootFS the reason why the kernel is apparently not running?
For some time I really thought that I needed to load the rootFS so that the kernel didn’t stop there, and I think I was half-right. It’s true that the kernel would stop if it did not find a root filesystem to load, but it’s also true that there would be output of some sort before that. So, no, this situation is probably due to some sort of driver incompatibility with the board peripherals, and this can only be caused by the device tree blobs. Is it that they are not the ones suited for this board, or maybe the kernel is not reading them because I did not configured the kernel for that(there are some CONFIG_ options which are needed for the kernel to be “DTS-enabled”. (I need to find which ones are). First, I’ll start building the rootFS with buildroot, because this will take a while and even on my machine, I imagine it will take at least 20min per try.

I had to configure buildroot so that it worked with the CPU architecture, and also had to select the tools to be compiled in. I didn’t have an external one ready, so I build both, the host toolchain for building the target tools, and the target tools themselves. I didn’t spend time selecting programs, I went with default busybox, and a SSH server tool called Dropbear, just in case. Here are some screenshots of my setup:
Buildroot - Target options
The board has two cores, but it’s the A5 which will load Linux. As most commercial implementations of ARM processors, this one has a little endian configuration. The Cortex-A5 has a Vector Floating-Point so I enabled it, instead of going with a software-based floating point support. (something worth talking about is that, while researching this project I found out that someone did some hacking with a Vybrid board and successfully loaded a MMU-less version of Linux on the Cortex M4!, so basically he loaded the two Cores with their respective version of Linux, very cool!. All his work has been upstreamed already, so I think I’ll try to do that in the future).
Buildroot - Build options
I read that it’s useful to set the Download directory outside of the buildroot directory, to avoid the risk of everything being deleted after an accidental ‘make clean’. I dont know if that’s true, havent test it, but just to be sure.
Buildroot - Toolchain(1)
Buildroot - Toolchain(2)
I ended up going with glib. Although it’s bigger, I had some issues compiling uClibc-ng. I dont know if it was because of the library of because I hadnt set the VFP support yet and it was confused by the Target Optimizations. Anyway, the difference in size can’t be that huge (as a matter of fact, I know there’s a big difference in size between them, but I’m planning to use an microSD card, so ‘extremely small’ is not really my goal just yet). As with the kernel itself, I chose Linux headers v4.15 for the toolchain and also the latest GCC 7.x (actually there’s already a GCC 8 which just came out, but nevermind).
Buildroot - System Configuration
Finally, the system configuration. Most of the options here are mainly just for appearance’s sake. things like the System’s hostname which I changed to the name of the board, as well as the System banner. Leaving Busybox’s own init system and shell was OK I guess, most of the other options I dont have a preference, nor are things that may ruin the build. I changed the TTY port from the default name(console) to tty1.

The generated filesystem was built and compressed with gzip. I extracted it as SU on the root partition, which is EXT4.

sudo tar -C /media/root_partition -xf rootfs.tar.gz

I dont remember if the current build of the kernel has support for EXT4, but that’s not a priority right now. After trying to boot this board with the new filesystem, it behaved like before. No progress for now.

Categories: Uncategorized

Having Fun Kernel Debugging on my old Netbook » « USB: First Steps

1 Comment

  1. Noticed your message on my blog 🙂

    “Starting kernel …” is the last message printed by U-Boot. It looks like Linux is crashing during unpacking or very early boot. It is quite likely that the kerne is overwriting the device tree which is rather low at 0x81000000. Try adjusting variables (e.g. move device tree from 0x81000000 higher up e.g. to 0x84000000). Otherwise, try using CONFIG_EARLY_PRINTK for Vybrid (under Kernel Hacking) and pass the earlyprintk parameter. With that you should see more than “Starting kernel …”.

Leave a Reply

Your email address will not be published.

*

Copyright © 2019 [My] Embedded Workshop

Theme by Anders NorenUp ↑