Issue
Context
Lately I've had trouble including an adis driver in my Yocto build. I've asked the question on the rel="nofollow noreferrer">adis forum but found the solution before anyone answered it. The adis forum not being very user friendly and the answer being quiet long, I've decided to answer my question here and link it in the forum.
The question
I'm building my OS with yocto and I'd like to add a driver for IMU ADIS1607 (anything but the ease of use is a plus) as part of this build.
I'm building a prototype on a raspberryPi4. My application uses an ADIS IMU (ADIS16507). Since the board for the final product is not fixed I'm building my OS with Yocto.
I'm currently trying to add a driver for ADIS16507. Ideally I'd like to add ADIS16475, but I could do with something else provided it works nicely.
First off I have checked that I'm able to build the whole ADIS linux kernel for RaspberryPi as specified in the doc. With that kernel the driver works nicely.
However the ADIS linux kernel is too heavy for what I intend to do. Hence I'm trying to build a lighter OS with yocto (also, as aforementioned, I'll likely need to port my work on different platforms).
I have a few ideas on how to do it, however none of them worked easily and I'm not sure which one to pursue.
I assumed the simplest way would be to compile the ADIS16475 on its own and add it to the Yocto build. However I'm struggling a little with Yocto and haven't been able to compile sucessfully
Alternatively I did find the libiio layer for yocto but it seems to require quiet a lot of code to on top of it to be able to read the IMU values.
I am aware of the python bindings of libiio layer and of Pyadi-iio and it seems easy to use (although I did not try adding it with yocto) but computational speed is an issue for me and I'd rather use C/C++ instead of python.
Finally I also found the meta-adi layer. I think that in my case it is not relevant but the documentation I found is rather sparse and I'm not certain what this layer is supposed to do.
Any pointer on which method I should use (maybe I've missed an obvious easy one) is welcome.
Solution
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 lists. obj-y
that holds the files that will be compiled and built in the kernel 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 use 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 specific 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
Answered By - LNiederha Answer Checked By - Timothy Miller (WPSolving Admin)