Compiling the Kernel¶
In this tutorial, we will compile the Linux kernel for our SoC's ARM using the toolchain we already have configured.
Kernel 4.4¶
Clone the Linux kernel:
$ git clone https://github.com/torvalds/linux
$ cd linux
This might take a while, the kernel is a large project.
Tip
The official repository of the Linus kernel is: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git however cloning from it is usually much slower than from GitHub (which is just a mirror of the official repository).
We will work with version 4.4
of the kernel which is a version with: Long Time Support
(LTS), i.e., it will be maintained for much longer than other versions. Version 4.4 was released on January 10 and will be officially maintained until 2021, it is also a version called Super LTS, with extended support until 2036. Think that a developer of an embedded system, who is going to create a whole dedicated infrastructure, doesn't want to have to adjust and validate everything again just to have the newest version of the kernel. The idea of using a version with more support is to minimize efforts with new resources.
The kernel uses the tag
system of git:
$ git tag
...
v2.6.11
v2.6.11-tree
v2.6.12
v2.6.12-rc2
v2.6.12-rc3
v2.6.12-rc4
v2.6.12-rc5
v2.6.12-rc6
v2.6.13-rc2
v2.6.14-rc2
v2.6.14-rc3
...
Note that odd revisions are for Kernel in development stage, and even numbers for production version, example:
- Linux 2.4.x - Production
- Linux 2.5.x - Development
- Linux 2.6.x - Production
- ....
Exercise
Configuring the Kernel¶
Once in the 4.4-SoC
branch we need to configure the kernel for our processor (ARM) and make the necessary configurations in the kernel. First, we will generate a standard configuration file .config
for Altera ARM SoCs.
Exercise
Exercise
This command will open the Linux Kernel configuration interface (there are other options: make xconfig
; make config
; make gconfig
, ...). This interface allows us to select various Kernel configurations. Now we will follow the script proposed in the following tutorial, translated in a reduced way here.
Configuring¶
Now lets configure the kernel:
Exclude/ Include
To Disable use the letter N
on the keyboard, to include the letter Y
Doubts?
Most parameters have an explanation, just press ?
to read about it.
Automatically append version information to the version string¶
- Go to general Setup
- Disable: Automatically append version information to the version string
Automatically append version information to the version string
Go into the “General Setup” menu. Uncheck “Automatically append version information to the version string”. This will prevent the kernel from adding extra “version” information to the kernel. Whenever we try to dynamically load a driver (also called kernel modules, as discussed in a later section) the kernel will check to see if the driver was built with the same version of the source code as itself. If it isn’t, it will reject to load that driver. For development, it’s useful to disable these options to make it easier to test out different versions of drivers. In a production system however, it’s recommend to keep this option enabled and only use drivers that were compiled with the correct version of the kernel. I encourage you to peruse the options in the General Setup menu and see what’s available to you (hitting “?” to view the help info for the highlighted option). Of particular importance to us is the “Embedded System” option (turns on advanced features) and the type of SLAB allocator used (determines how memory will be dynamically allocated in the kernel). If you want to use an initial ram disk or ram filesystem that would be enabled here as well (these will be explained in the next section). (text extracted from the reference)
Enable loadable module support¶
- Go back to the main menu (
<ESC>
<ESC>
)- Note that Enable loadable module support is enabled.
This allows the kernel to be modified (by loading drivers) after its execution. This will be useful when we develop our own device driver, without the need to recompile the kernel every time we want to test a modification in the code. This is the configuration that allows us to use USBs, SSDs, network cards via the possibility of dynamically loading drivers by the operating system.
Support for large (2TB+) block devices and files¶
- In the main menu Enable the block layer
- Enable: `Support for large (2TB+) block devices and files
`
This option will allow the use of EXT4 type partitions. If you forget this option and the kernel is on an EXT4 partition, it will be mounted as READ-ONLY.
The Extended 4 (ext4) filesystem¶
- Main menu File systems
- Note that it is already selected:
The Extended 4 (ext4) filesystem
- Note that it is already selected:
This option will enable the kernel to mount devices formatted in EXT4. We intend to use this on the SDCARD.
Altera SOCFPGA family¶
- Main menu System Type
- Note that it is already selected:
Altera SOCFGPA family
- Note that it is already selected:
This indicates to the kernel which will be the device that it will be executed on, note that this option has a new menu where we can enable or not the suspension to RAM.
Symmetric Multi-Processing¶
- Main menu Kernel Features
- Note that it is already selected:
Symmmetric Multi-Processing
- Note that it is already selected:
This option indicates to the kernel that it should use the two cores present in the ARM HPS of the FPGA.
Device Drivers¶
- Main menu Device Drivers
- Analyze the available drivers...
Indicates which drivers will be compiled along with the kernel, note that we already have configured network drivers (Network device support); GPIO (GPIO Support); RTC; DMA; ... . Remember that we already initialized the .config
with a default configuration for Altera SoCs.
Saving¶
Saving
.config¶
Note
Take a look at the generated .config
file! Sometimes it's easier to edit directly in it, than having to open the configuration menu and find the place to activate a module.
Compiling¶
The makefile uses the CROSS_COMPILE
variable to define the toolchain that will compile the kernel, let's define it as the Linaro GCC recently downloaded and than compile the Linux kernel.
Exercise
Tip
Add the export CROSS_COMPILE=....
to your .bashrc
so you don't have to keep typing it every time you have to compile the kernel.
Warning
If you get the error:
"/usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x10): multiple definition of 'yylloc'; scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here".
It's because there is an incompatibility of the version we are compiling 4.5 with the GCC (from version 9 onwards). There are two solutions:
- Use gcc9: https://www.soughttech.com/front/article/17085/viewArticle
- Apply a patch to the linux kernel that removes the multiple declaration of the variable
yylloc
, in the root of the kernel:
$ wget https://github.com/Tomoms/android_kernel_oppo_msm8974/commit/11647f99b4de6bc460e106e876f72fc7af3e54a6.patch
$ git am 11647f99b4de6bc460e106e876f72fc7af3e54a6.patch
Fail
If a build error occurs, you should check the path of CROSS_COMPILE
or if there is a dependency that has not been met.
This command causes the Linux kernel to be compiled into a compressed version that is self-extracting. Other options would be:
- Image: Kernel binary
- zImage: compressed version that has self-extracting
- uImage: a version that already has the uboot bootloader
1^: https://stackoverflow.com/questions/22322304/image-vs-zimage-vs-uimage
Compiled Kernel
The zImage is saved in:
arch/arm/boot/zImage
zImage
This file is the binary that contains the Linux kernel and will be executed on the embedded system.
Testing¶
Now we need to update the kernel that is on the SDCard so we can test if it is working.
Updating the SDCARD
To verify that everything is set up correctly, simply insert the memory card into the kit and check the version of the running kernel. Please note that your kernel version and compilation time may differ from mine.
$ uname -a
Linux buildroot 4.4 #1 SMP Mon Jul 16 21:22:58 -03 2018 armv7l GNU/Linux
Mouse/ Keyboard?¶
Do mouse and keyboard work right away? Try plugging a USB mouse into the board, is it recognized by Linux? It shouldn't be. To work you should go back to the Linux kernel settings and insert the drivers that manage USB and HID. Compile, replace the zImage on the sdcard and test again.
How to check if the mouse is working?
- Type 'lsusb', it should show that it recognized a mouse
- After connecting the mouse, type
tail dmesg
, it should show that it recognized a new USB device and associated it with a mouse - The mouse in linux is mounted on
/dev/input/mice
, to see if it is working you can execute:cat /dev/input/mice
, move the mouse to see if anything appears on the screen
Human Interface Devices (HID)
HID is a type of device recognized by the Linux Kernel as a user interface device, this type of device is usually automatically recognized by the kernels, as they implement a communication standard.
USB also has a classification of HID type devices, which facilitates their use by the kernel: