Yocto Build for Preempt_Rt

Yocto build for preempt_rt

I was able to get it to build core-image-rt by adding the following to build/conf/local.conf

PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-rt"
COMPATIBLE_MACHINE_beaglebone = "beaglebone"
COMPATIBLE_MACHINE_quilt-native = "beaglebone"

How to setup a pre-emptive real time kernel in Yocto for a evalboard(which has a preset kernel from the manufacturer)?

In general:

in .../source/poky/recipes-kernel/linux you should find a linux-yocto-rt_X.XX.bb recipe to compile a full preemptive RT kernel.

For meta-atmel you should do:

  1. Download the correct RT patch for your kernel version and apply it using a .bbappend file to your current linux kernel recipe. You could find the patch HERE
  2. Add the patch to your bbappend file (stored in your own layer in the one of accepted direcotries). p.e.: SRC_URI += "file://0001-linux-rt.patch"
  3. Activate preemptive kernel. Manually set CONFIG_PREEMPT=y at defconfig at your layer. Alternativly you can use bitbake virtual/kernel -c menuconfig

Pitfalls at meta-atmel:

  1. the linux-at91_4.4.bb recipe does not care about patch and sublevel of the kernel (p.e. 4.4.66 -> ..). if there is a new version at at91-linux it will go after some time to the meta-atmel layer.
  2. the RT branch of the linux kernel is not provided for every new sublevel
  3. this means constant breaks of your own meta-layer

Yocto layer for ADIS16475

So here is the solution I found. We will use the ADIS16475 which is a part of the standard libc since version 5.10. Then we'll get the corresponding device tree overlay from ADIS and add the relevant variables to have it compiled with the other device tree overlays.

Getting the correct versions

For this to work we need libc 5.10 or later since earlier version do not include the adis16475.c source file. However only the latest yocto release, Hardknott, uses the 5.10 version. So simplest thing to do is to switch to the Hardknott branch of Yocto. Keep in mind that if you use other layers, you might also have to change release for compatibility reasons.

Configuring the kernel to compile ADIS16475 drivers as built in

Here we're gonna dab into kernel compilation so there are a few things to know

Short and approximate theory

If you don't know much about kernel compilation don't worry, neither do I. But here is an approximate quick explanation in order for you to understand what we're doing: Kernel makefiles hold list of files the have to compile. For drivers there are 2 important ones. obj-y that holds the files that will be built in and obj-m that holds the files that will be compiled as loadable modules. In order to make these list configurable, they are defined in makefiles with statements such as:

obj-${CONFIG_MYDRIVER} += my_driver.o

The idea is that you can set CONFIG_MYDRIVER in an external file to 'm' or 'y'. If you set it to anything else the line in the makefile will be ignored and your file won't be compiled. So basically all we have to do is to set the right variables to the right values in order for yocto to compile our drivers.

Custom kernel configuration

Basically what we want to do is to create our own configuration fragment file. To do this you will need to set your yocto layer (I'll assume if you're reading this post you know how to do it). In your layer you should add the following folders:

meta-my-layer
|
- recipe-kernel
|
- linux
|
- linux-raspberrypi_5.10.bbappend
|
-linux-raspberrypi
|
-adis16475.cfg

(Note that we are appending linux-raspberrypi_5.10 because it's the one in meta-raspberrypi that is responsible for libc compilation. If you're compiling for another machine look what files are in recipe-kernel/linux. Your BSP might even actually use the ones in poky/meta/recipe-kernel/linux)

Now all that is left to do is to add adis16475.cfg to our sources by adding the following lines in linux-raspberrypi_5.10.bbappend:

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://adis16475.cfg"

And to actually setup your configuration in adis16475.cfg by adding to the file:

CONFIG_SPI_MASTER=y
CONFIG_IIO=y
CONFIG_ADIS16475=y
CONFIG_IIO_KFIFO_BUF=y
CONFIG_SPI_BCM2835=y

To the best of my knowledge and experience, this is the minimal amount of drivers you have to build for it to work.

Once this is done you will have your drivers built in but you won't see any effect on the Pi. That's because we're lacking the correct overlay.

Building adis16475-overlay.dts

To solve this problem I've been widely inspired by this post, so if you're having trouble you might want to check it out.
The issue here is that to my knowledge, the overlay corresponding to the driver is not provided by libc, at least not the 5.10 version. So we will have to be a little crafty. First off get the overlay from adis and copy it into recipe-kernel/linux/linux-raspberrypi.

Once this is done we will source it for yocto to find by modifying recipe-kernel/linux/linux-raspberrypi_5.10.bbappend to look like this:

FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://adis16475.cfg \
file://adis16475-overlay.dts;subdir=git/arch/${ARCH}/boot/dts/overlays"

The last line we added tells yocto where to get our .dts file and where to put it (with the others overlays).

Finally what we have to do is to add our overlay to the list of overlays and device trees to be compiled. To do so we will the machine configuration file raspberrypi4-64.conf. More details about it here.

First in your layer conf folder, create machine/raspberrypi4-64-extra.conf. This file will hold all the additional configuration we want to make for this driver. In it first add:

# Create the device trees and overlay list with necessary drivers
KERNEL_DEVICETREE = " \
${RPI_KERNEL_DEVICETREE} \
${RPI_KERNEL_DEVICETREE_OVERLAYS} \
overlays/adis16475.dtbo \
"

This sets the list of device trees to compile. It add the RPI device trees and overlays necessary for the pi (two first variables) and our adis16475 overlay.

Then we'll take advantage of this file to enable a few necessary raspberrypi spcific configuration options. Add:

# Enable RPI specific options in config.txt
ENABLE_SPI_BUS = "1"
RPI_EXTRA_CONFIG = '\ndtoverlay=adis16475\n'

Finally you need to tell yocto to use this extra config. The most verstile way is to add the following line in your local/local.conf:

# Enables the DIP hardware support
require conf/machine/${MACHINE}-dip-extra.conf

Once this is done, provided you did add your layer to your bblayers.conf file,and your machine is set to raspberrypi4-64 in your local.con file, then everything else should work nicely.

Notes on the machine type

Here I worked with the machine set as raspberrypi4-64 for it was the one I had. There is no reasons for this procedure not to work with any other machine from the meta-raspberrypi layer. Just remember to replace the name of your machine everywhere I put raspberrypi4-64 and you should be fine.

Hope this will help some other people lost in the Yoctoverse

Cheers

Disadvantage(s) of preempt_rt

CONFIG_PREEMPT_VOLUNTARY -

This option introduces checks to the most common causes of long latencies in the kernel code, so that the kernel can voluntarily yield control to a higher priority task waiting to execute. This option is said to be reducing the occurrances of long latencies to a great degree but still it doesn't eliminate them totally.

CONFIG_PREEMPT_RT -

This option causes all kernel code outside of spinlock-protected regions (created by raw_spinlock_t), to be eligible for non-voluntary preemption by higher priority kernel threads. Spinlocks created by spinlock_t and rwlock_t, and the interrupts are also made preemptable with this option enabled. With this option, worst case latency drops to (around) single digit milliseconds.

Disadvantage -

The normal Linux kernel allows preemption of a task by a higher priority task only when the user space code is getting executed.

In order to reduce the latency, the CONFIG_PREEMPT_RT patch forces the kernel to non-voluntarily preempt the task at hand, at the arrival of a higher proiority kernel task. This is bound to cause a reduction in the overall throughput of the system since there will be several context switches and also the lower priority tasks won't be getting much a chance to get through.

Source:
https://rt.wiki.kernel.org/index.php/Frequently_Asked_Questions


Description of technical terms used:

What is latency?

The time elasped between a demand issued on a computer system and the begining of a response to the same demand is called latency or response time.

Kinds of latencies:

  • Interrupt Latency:

    The time elapsed between the generation of an interrupt and the start of the execution of the corresponding interrupt handler.

    Example: When a hardware device performs a task, it generates an interrupt. This interrupt has the information about the task to be performed and about the interrupt handler to be executed. The interrupt handler then performs the particular task.
  • Scheduling Latency:

    It is the time between a wakeup signaling that an event has occurred and the kernel scheduler getting an opportunity to schedule the thread that is waiting for the wakeup to occur (the response). Scheduling latency is also known as dispatch latency.
  • Worst-case Latency:

    The maximum amount of time that can laspe between a demand issued on a computer system and the begining of a response to the same demand.

What is throughput?

Amount of work that a computer can do in a given period of time is called throughput.

What is Context switch?

Context switch is the switching of the CPU from one process/thread to another. Context switches can occur only in kernel mode. This is the process of saving the current execution state of the process (for resuming execution later on), and loading the saved state of the new process/thread for execution.



Related Topics



Leave a reply



Submit