3. Software Guide¶
3.1. About this Chapter¶
This Software Guide provides instructions for building and deploying the BSP software: the U-Boot bootloader and the Linux operating system to the µQ7 board.
The section “Compiling Linux Applications” provides guidance for compiling applications for the Pangolin.
3.2. Compiling Kernel and Bootloader¶
3.2.1. Prerequisites¶
You need a recent x86_64 Linux installation to run the cross-compiler on. The cross-compiler requires libc version 2.19. Distributions shipping this version are, among others:
- Ubuntu 14.04 “Trusty”
- Debian 8 “Jessie”
We recommend Debian 8. Please install the following packages to set up the generic build infrastructure:
sudo apt-get install device-tree-compiler u-boot-tools build-essential git bc
3.2.2. Compiler Setup¶
For both the U-Boot bootloader and the Linux kernel, a bare-metal arm cross-compiler is required. Note that a bare-metal compiler is only suitable for compiling kernel and bootloader. It will not generate applications that run under Linux.
You can download precompiled binaries from Linaro: https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-eabi/gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi.tar.xz
Extract the archive in /opt .
Then, set up environment variables to make use of the new compiler:
export ARCH=arm
export CROSS_COMPILE=/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi/bin/arm-eabi-
3.2.3. Building U-Boot¶
U-Boot (Universal Bootloader) is an open source, primary boot loader used in embedded devices to package the instructions to boot the device’s operating system kernel.
The boot loader source code can be cloned from https://git.theobroma-systems.com/pangolin-u-boot.git/:
git clone https://git.theobroma-systems.com/pangolin-u-boot.git
Compile using:
cd pangolin-u-boot
make pangolin_defconfig
make
The resulting u-boot image will be saved as u-boot-sunxi-with-spl.bin
in the pangolin-u-boot
directory.
3.2.4. Building the Boot Script¶
The U-Boot boot sequence is controlled by a file called boot.scr
. This file
is generated from a plain-text file called boot.cmd
.
You can clone this file from https://git.theobroma-systems.com/pangolin-tools.git:
git clone https://git.theobroma-systems.com/pangolin-tools.git
Generate boot.scr
using:
cd pangolin-tools
make
3.2.5. Building the Linux Kernel¶
The kernel source code can be cloned from https://git.theobroma-systems.com/pangolin-linux.git/:
git clone https://git.theobroma-systems.com/pangolin-linux.git
Compile using:
cd pangolin-linux
make pangolin_defconfig
make ARCH=arm uImage sun6i-a31-pangolin.dtb LOADADDR=0x40008000
This will create the two files needed for booting with U-Boot (paths are
relative to the pangolin-linux
directory):
- The device tree:
arch/arm/boot/dts/sun6i-a31-pangolin.dtb
- The u-boot image:
arch/arm/boot/uImage
3.3. Building the root filesystem¶
A filesystem can be created using Debootstrap, specifying armhf as architecture in the command line.
Install support packages on the x86_64 Debian:
sudo apt-get install qemu-user-static debootstrap binfmt-support
Supposing the target dir is called a31-uq7-rootfs
and the chosen distro is
jessie (recommended):
export targetdir=$HOME/a31-uq7-rootfs
export distro=jessie
mkdir -p $targetdir
sudo debootstrap --arch=armhf --foreign $distro $targetdir
Next, copy the qemu-arm-static binary into the right place for the binfmt packages to find it and copy the resolv.conf file from the host system:
sudo cp /usr/bin/qemu-arm-static $targetdir/usr/bin/
sudo cp /etc/resolv.conf $targetdir/etc
This will provide a very basic armhf rootfs in the targetdir. For the next
stages, we chroot
to the target dir and set up the environment again:
cd $targetdir
sudo mount -o bind /dev ./dev
sudo mount -o bind /proc ./proc
sudo mount -o bind /sys ./sys
sudo mount -o bind /run ./run
sudo chroot .
export distro=jessie
export LANG=C
Second stage of debootstrap inside the new root dir:
/debootstrap/debootstrap --second-stage
Setting up apt sources:
cat << EOT > /etc/apt/sources.list
deb http://httpredir.debian.org/debian $distro main contrib non-free
deb-src http://httpredir.debian.org/debian $distro main contrib non-free
deb http://httpredir.debian.org/debian $distro-updates main contrib non-free
deb-src http://httpredir.debian.org/debian $distro-updates main contrib non-free
deb http://security.debian.org/debian-security $distro/updates main contrib non-free
deb-src http://security.debian.org/debian-security $distro/updates main contrib non-free
EOT
We can now pull the latest apt database from the Debian mirrors and install the locales package (in Jessie the dialog package is needed as well):
apt-get update
apt-get install locales dialog
dpkg-reconfigure locales
Now it is a good time to install a good editor of your choice:
apt-get install vim
update-alternatives --config editor #select vim.basic
Install any additional packages inside the chroot. An ssh server and sudo are recommended:
apt-get install openssh-server sudo
Set the root password for logging in via console or ssh:
passwd
root login over ssh is not permitted by default (set to
no
), or permitted only with public key (set to without-password
).
To verify that, run:
cat /etc/ssh/sshd_config | grep "PermitRootLogin"
PermitRootLogin without-password
To allow this open the file /etc/ssh/sshd_config
in your editor of
choice and set PermitRootLogin to yes
.
A better option would be to create a user besides root:
adduser user
Optionally, you can add it to the sudo
list:
adduser user sudo
Set up a basic network configuration file with DHCP via eth0:
cat << EOT >> /etc/systemd/network/eth.network
[Match]
Name=eth0
[Network]
DHCP=yes
EOT
systemctl enable systemd-networkd
systemctl enable systemd-resolved
Set the hostname:
echo a31-uq7 > /etc/hostname
For distros older than jessie (wheezy and earlier), the serial console has to be enabled manually. In jessie, this is handled automatically.:
echo T0:2345:respawn:/sbin/getty -L ttyS1 115200 vt100 >> /etc/inittab
You can optionally also install a Desktop Environment. Xfce is a lightweight desktop environment recommended for use on the A31 µQ7. To install Xfce, do the following:
apt-get install task-xfce-desktop
We can now exit and cleanup the support files:
exit
sudo umount ./run
sudo umount ./sys
sudo umount ./proc
sudo umount ./dev
sudo rm ./etc/resolv.conf
sudo rm ./usr/bin/qemu-arm-static
cd -
We now have a root filesystem which can be deployed to the SD card.
3.4. Deploying on SD Card¶
3.4.1. Partition Setup¶
Both U-Boot and Linux will be located on the same SD card. The layout of the card is as follows:
Offset | Contents |
---|---|
0 | Partition table |
8kiB | U-Boot bootloader |
544kiB | U-Boot environment variables |
1MiB | Partition 1 (ext4 - Linux root fs) |
Partitions can be created using fdisk (assuming the SD card is mapped to
/dev/sdX) and has no partitions (this can be checked using the p
command):
sudo fdisk /dev/sdX
> p
This should show an empty partition table, for example:
Disk /dev/sdX: 3980 MB, 3980394496 bytes
123 heads, 62 sectors/track, 1019 cylinders, total 7774208 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xdbbd45c7
Device Boot Start End Blocks Id System
If there are partitions on the sdcard, they can be deleted with d
.
The required partition can be created with the command n
,
then accepting the defaults:
> n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): <ENTER>
Partition number (1-4, default 1): <ENTER>
First sector (2048-7774207, default 2048): <ENTER>
Last sector, +sectors or +size{K,M,G} (...): <ENTER>
> w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
This will create a primary partition at offset 1MiB.
Now, to format the partition as ext4:
sudo /sbin/mkfs.ext4 -E lazy_itable_init=0 /dev/sdX1
The option lazy_itable_init=0
speeds up the first boot because it
initializes the inode tables in advance.
The SD card is now ready to have the U-Boot bootloader and Linux deployed.
3.4.2. Deploying U-Boot¶
The U-Boot image u-boot-sunxi-with-spl.bin
is written to the SD
card. Assuming the SD card is mapped to /dev/sdX:
sudo dd if=pangolin-u-boot/u-boot-sunxi-with-spl.bin of=/dev/sdX bs=8K seek=1 conv=fsync
3.4.3. Deploying the Linux Kernel and the Root Filesystem¶
Mount the SD card partition and copy the rootfs (assuming that the rootfs is located
at /opt/a31-uq7-rootfs
and the sd card at /dev/sdX1
):
sudo mkdir -p /mnt/sdcard
sudo mount /dev/sdX1 /mnt/sdcard
sudo cp -av /opt/a31-uq7-rootfs/* /mnt/sdcard
Copy kernel image, device tree and boot script into the boot directory:
sudo cp pangolin-linux/arch/arm/boot/dts/sun6i-a31-pangolin.dtb \
pangolin-linux/arch/arm/boot/uImage pangolin-tools/boot.scr \
/mnt/sdcard/boot
Finally, unmount the SD card:
sudo umount /mnt/sdcard
The SD card is ready for booting.
3.4.4. U-Boot Environment¶
The boot sequence is handled by the boot script /boot/boot.scr. Unless you want to customize the sequence, no further action is required.
If you want to step through the sequence manually or customize it, you can execute the following commands on the U-Boot prompt:
setenv bootargs console=tty0 console=ttyS2,115200 root=/dev/mmcblk1p1 rw rootwait
ext4load mmc 0:1 0x40008000 boot/uImage
ext4load mmc 0:1 0x40000000 boot/sun6i-a31-pangolin.dtb
bootm 0x40008000 - 0x40000000
Optionally, these commands can be compiled together in a single command and saved so it is performed on every subsequent boot:
setenv boot_sd "ext4load mmc 0:1 0x40008000 boot/uImage
ext4load mmc 0:1 0x40000000 boot/sun6i-a31-pangolin.dtb
bootm 0x40008000 - 0x40000000"
setenv bootcmd "run boot_sd"
saveenv
To reset the U-Boot settings to default, execute:
env default -f -a
saveenv
3.5. Deploying on On-Board eMMC storage¶
As the eMMC storage is only accessible from the module itself, you must first boot the A31 µQ7 from SD card.
Partion and format the eMMC storage as described in 3.4.1 Partition Setup, but using the
device /dev/mmcblk0
.
Mount the eMMC partition and copy the contents of the SD card to the eMMC storage. The copy process will take about 30 seconds:
sudo mkdir -p /mnt/emmc
sudo mount /dev/mmcblk0p1 /mnt/emmc
sudo cp -ax / /mnt/emmc
sudo umount /mnt/emmc
The final step is copying the bootloader from the SD card to the eMMC:
sudo dd if=/dev/mmcblk1 of=/dev/mmcblk0 bs=8K skip=1 seek=1 count=64 conv=fsync
Shut down the board (poweroff
command) and remove the SD card. Make sure the boot selector switch Boot SW is set to “Normal Boot”.
The next boot will run U-Boot off the internal eMMC storage.
3.6. Compiling Linux Applications¶
The easiest option is to compile your applications directly on a running A31 µQ7 module. Just install the gcc package and related utilities and you are good to go:
sudo apt-get install build-essential
The second option is to cross-compile your applications. That means running a cross-compiler on an x86_64 Linux installation.
You can download precompiled binaries of the cross-compile toolchain from Linaro: http://releases.linaro.org/14.11/components/toolchain/binaries/arm-linux-gnueabihf/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz
Note that this toolchain is only suitable for compiling Linux user-space applications. It will not compile the Linux kernel itself or the bootloader.
3.7. Serial Number¶
Each A31 µQ7 module has a unique serial number that can be read by software.
In U-Boot, the serial number is contained in the environment variable serial#
.
You can print it using the command:
printenv serial#
Under Linux, it is represented by a simple text file in /sys
:
cat /sys/firmware/devicetree/base/serial-number
The serial number is fixed in hardware (derived from the eMMC Product Serial Number) and can not be modified.
3.8. MAC Address¶
By default, the MAC address of each A31 µQ7 module is a random value derived from the serial number. The properties of this default MAC address are:
- It is a Locally Administered Address: The U/L bit of the MAC address is set to 1
- It is not guaranteed to be globally unique
- The address is fixed for each A31 µQ7 module. It stays constant across reboots as it is deterministically derived from the serial number
To set your own Universally Administered Address, you overwrite the U-Boot environment variable ethaddr
.
On the U-Boot prompt, with XX:XX:XX:XX:XX:XX replaced by your MAC address:
setenv ethaddr XX:XX:XX:XX:XX:XX
saveenv
The MAC address can be queried from the U-Boot prompt using:
printenv ethaddr
To reset the MAC address to the default value, run:
env delete ethaddr
saveenv