Table of Contents
Building u-boot, script.bin and linux-kernel
Get a cross toolchain
The toolchain is a set of binaries, system libraries and tools which allow you to build (in our case, cross-compile) u-boot and the kernel for a target platform. This will, to some limited extent, need to match the target rootfs. If you use Ubuntu or Debian, you can get all you need by installing the tools below:
sudo apt-get update sudo apt-get upgrade sudo apt-get install build-essential u-boot-tools uboot-mkimage binutils-arm-linux-gnueabihf gcc-4.7-arm-linux-gnueabihf-base g++-4.7-arm-linux-gnueabihf gcc-arm-linux-gnueabihf cpp-arm-linux-gnueabihf libusb-1.0-0 libusb-1.0-0-dev git wget fakeroot kernel-package zlib1g-dev libncurses5-dev
Note: On Debian (wheezy)/Ubuntu 13.10 (saucy) onwards, the uboot-mkimage package has been removed; the mkimage command is included in the u-boot-tools package. On Ubuntu 12.04, change
gcc-4.7-arm-linux-gnueabihf-base and g++-4.7-arm-linux-gnueabihf
to
gcc-4.6-arm-linux-gnueabihf-base and g++-4.6-arm-linux-gnueabih.
respectively.
You also can use the Linaro tool chain or the Code Sourcery tool chain - they are standalone toolchains with big tarballs which come with everything you need.
Compile Linaro toolchain
Background
What is the differences between “arm-none-eabi-” and “arm-linux-gnueabihf”? Can I use “arm-linux-gnueabihf” tool chain in bare-metal environment? How do you know which toolchain binary to use where?
The general form of compiler/linker prefix is as follows:
A-B-C
Where:
A indicates the target (arm for AArch32 little-endian, aarch64 for AArch64 little-endian). B indicates the vendor (none or unknown for generic) . Note that this is optional (Eg: not present in arm-linux-gnueabihf) C indicates the ABI in use (linux-gnu* for Linux, linux-android* for Android, elf or eabi for ELF based bare-metal).
C has values which seem odd until you understand the history behind it (basically AArch32 used to have a linux-gnu ABI which got changed so needed a new name so we have linux-gnueabi). For AArch32 we have linux-gnueabi and linux-gnueabihf which indicate soft float, and hard float respectively.
The bare-metal ABI will assume a different C library (newlib for example, or even no C library) to the Linux ABI (which assumes glibc). Therefore, the compiler may make different function calls depending on what it believes is available above and beyond the Standard C library.
Also the bare-metal ABI and Linux ABI for the 32-bit Instruction sets make different assumptions about the storage size of enums and wchar_t which you have to be careful of (not a complete list). And the difference between the 32-bit and 64-bit ABIs are also numerous and subtle (the obvious example being pointer sizes).
Does Linaro GCC toolchain support Cortex-A7 along with NEONv2 & VFPv4?
Yes, the linaro-toolchain-binaries projects supports cortex-a7 + vfpv4, but this is not their default configuration. You can override defaults while compiling by giving
arm-linux-gnueabihf -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4
option.
If you choose to rebuild the toolchain so that -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4 become default values, you can choose to do so.
Also, please note that
-mcpu=cortex-a7 -mfpu=vfpv4 -mfloat-abi=softfp|hard: Cortex-A7 with FPv4. -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp|hard: Cortex-A7 with NEONv2 & FPv4.
are the standard ways of configuring gcc to support Cortex-A7.
Below is more information you may find useful for a better perspective: There are four inter-related command-line options here, and below is what each does - and then summarise for Cortex-A7.
-mcpu=CPU: This specifies the integer-side CPU in use. Note that it doesn't specify whether floating point (VFP) or Advanced SIMD (Neon) is available. If both -mcpu & -march appear on the command-line the one furthest to the right on the command line takes precedence. Passing -mcpu=? to GCC will list all valid CPU options.
-march=ARCH: This specifies the base-architecture in use. Note that again this effectively specifies the integer-side CPU in use, and doesn't specify floating point or Advanced SIMD usage. If both -mcpu & -march appear on the command-line the one furthest to the right on the command line takes precedence. Passing -march=? to GCC will list all valid ARCH options. -mfpu=FPASEC: This specifies which Floating Point/SIMD/Crypto Extensions are available to be used. This covers whether VFP version, NEON version, and ARMv8-A Crypto extensions are available. Note that if you use this command-line option you also need to specify -mfloat-abi=softfp or -mfloat-abi=hard otherwise you will not see code using VFP/Neon/Crypto instructions. Passing -mfpu=? to GCC will list all valid FPASEC options. -mfloat-abi=FABI. This specifies how the compiler may use VFP/Neon/Crypto instructions. It has three values:
-mfloat-abi=soft: No VFP/Neon/Crypto instructions are used anywhere even if -mfpu is specified on the command line. -mfloat-abi=softfp: If -mfpu=FPASEC is specified on the command-line as well then use FP/Neon/Crypto instructions within functions, but parameters between functions are still passed using integer registers only. -mfloat-abi=hard: If -mfpu=FPASEC is specified on the command-line as well then use FP/Neon/Crypto instructions within functions, and also use the Floating-point register bank to pass parameters between functions.
So to properly specify a CPU when invoking GCC you should pass three parameters on the command-line:
one of -mcpu & -march -mfpu -mfloat-abi.
GCC's defaults depend on how it has been built. gcc -v will tell you.
(Note the configuration options are named slightly differently. Linaro builds are configured as follows:
arm-none-linux-gnueabi: --with-arch=armv7-a --with-fpu=none --with-float=soft arm-none-linux-gnueabihf: --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard
Now onto Cortex-A7: Cortex-A7 is fully supported by GCC. The command-line options for use are:
-mcpu=cortex-a7 -mfpu=vfpv4 -mfloat-abi=softfp|hard: Cortex-A7 with FPv4. -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=softfp|hard: Cortex-A7 with NEONv2 & FPv4.
More on:
- https://wiki.linaro.org/WorkingGroups/ToolChain/BuildingGNUToolchains?highlight=%28cross%29|%28compile%29|%28toolchain%29
Step by step
Prerequisites
bison, flex, gperf, gawk, libtool, automake, g++
Download
mkdir linaro-toolchain/{build-dir,install-dir}
cd linaro-toolchain
wget http://launchpad.net/gcc-linaro/4.8/4.8-2013.05/+download/gcc-linaro-4.8-2013.05.tar.bz2
tar jxvf gcc-linaro-4.8-2013.05.tar.bz2
Configure
cd build-dir ../gcc-linaro-4.8-2013.05/configure \ --target=arm-linux-gnueabihf \ --with-mode=thumb --with-arch=armv7-a --with-tune=cortex-a7 \ --with-float=hard --with-fpu=vfpv4 \ --prefix=$(pwd)/../install-dir --mcpu=cortex-a7 –mtune=cortex-a7 –mfpu=neon-vfpv4 --enable-languages=c,c++ \ --mcpu=cortex-a7 -mfloat-abi=hard -mfpu=vfpv4 –host=i686-linux-gnu \ –build=i686-linux-gnu \ –enable-gold –program-transform-name=’s&^&arm-linux-gnueabi-&’ \ –disable-option-checking –disable-multilib \ –with-arch=armv5te
Variant
The configure statement above can be broken down into two groups.
Those that are build related:
--disable-bootstrap builds gcc in one pass using the host compiler. This is faster and uses less disk space, but doesn't test the compiler as well as a three stage bootstrap build. --enable-languages=c,c++ builds the C and C++ compilers only, and skips the Fortran, Java, and Objective-C compilers. This is faster, but doesn't test the compiler as well. --prefix=$home/opt/gcc-linaro sets where to install.
Those that set the default type of code generated:
--with-mode=thumb generates Thumb-2 code --with-arch=armv7-a --with-tune=cortex-a9 generates code tuned for the A9 that still works on the A8 --with-fpu=neon generates VFP and NEON instructions for floating point and vectoriser related code --with-float=softfp sets the floating point calling convention to match Ubuntu
To generate code that will work on all Cortex-a8 and above chips, use:
--with-mode=thumb --with-arch=armv7-a --with-fpu=vfpv3-d16
Note that NEON and VFPv3-D32 are optional. The Tegra2 in particular is VFP only. See http://wiki.debian.org/ArmHardFloatPort for more.
To build a compiler for x86_64 or i686, ommit the –with-* options:
Make gcc
make -j4 # in My case 4 is no. of CPUs
Get the Board Specific Package
Get the BSP repository:
git clone https://github.com/LeMaker/bananapro-bsp.git
Build
After getting the BSP, then navigate into the sunxi-bsp directory, and run the build command:
If for Banana Pro:
./configure BananaPro make
If for Banana Pi:
./configure BananaPi make
This will take a long time to build all the things. After it has been built, you can get all you want from the build/Bananapi_hwpack directory, such as the u-boot-sunxi-with-spl.bin, uImage, and scritp.bin, modules. You can tweak your kernel configuration too by running:
make linux-config
This will override the .config file in the bananapro-bsp/build/sun7i_defconfig-linux.
Building u-boot
U-boot is the bootloader commonly used on our Allwinner SoCs. Similar to many others, it provides the basic infrastructure to bring an SBC (single board computer) up to a point where it can load a Linux kernel and start booting your operating system. First you need to clone the repository from Github:
git clone https://github.com/LeMaker/u-boot-sunxi.git
After the repository has been retrieved, you can build the u-boot.
First make the u-boot configure:
If for Banana Pro:
make CROSSCOMPILE=arm-linux-gnueabihf- BananaProconfig
If for Banana Pi:
make CROSSCOMPILE=arm-linux-gnueabihf- BananaPiconfig
And then make the u-boot:
make CROSS_COMPILE=arm-linux-gnueabihf-
After that you may get the u-boot-sunxi-with-spl.bin, u-boot.img, u-boot.bin, spl/sunxi-spl.bin. Here we are only using the u-boot-sunxi-with-spl.bin file.
Building script.bin
First, get the following repositories:
git clone https://github.com/LeMaker/sunxi-tools.git git clone https://github.com/LeMaker/sunxi-boards.git
Go into sunxi-tools and run the command:
make
You will get the tools fex2bin, bin2fex and some others.
Then go into the sunxi-boards tree and find the fex file for the Banana Pi. We can customize some of the configurations in the file, such as [gmacpara], [usbwifi_para], etc.
Create the script.bin file: If for Banana Pro:
${sunxi-tools}/fex2bin BananaPro.fex script.bin
If for Banana Pi:
${sunxi-tools}/fex2bin BananaPi.fex script.bin
The prefix ${sunxi-tools} indicates that you are in your sunxi-tools tree.
You will need this script.bin file later on when finishing the u-boot installation. Building the kernel
First, get the linux kernel repository by following:
git clone https://github.com/LeMaker/linux-sunxi.git
Second, set default kernel configuration:
make ARCH=arm CROSSCOMPILE=arm-linux-gnueabihf- sun7idefconfig
Third, tweak the config. You can open some kind of kernel configuring software or close the useless kernel configuration by editing your kernel configuration:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
Building uImage and modules:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage modules
As a final step, create the full module tree:
make ARCH=arm CROSSCOMPILE=arm-linux-gnueabihf- INSTALLMODPATH=output modulesinstall
The INSTALLMODPATH option specifies the directory where the full module tree will be made available. In this example, it will be the output directory under the kernel build directory itself.
Now you have the following residing in your kernel tree:
arch/arm/boot/uImage output/lib/modules/3.4.XX/
The uImage file needs to be started by u-boot, and the modules directory needs to be copied to the /lib/modules on the target root file system.
Through either “step by step” or “using the bsp”, you will get at least the four files or packages you need, which are:
u-boot-sunxi-with-spl.bin uImage script.bin modules/3.4.XX
We will use these four files to set up the bootable SD card in Part 2. References