I made the following notes while I was compiling a Kernel module (SI7020 Humidity/Temp Sensor) for the Raspberry Pi. The module was not part of the precompiled modules shipped with Raspbian. The steps should be the same if you want to build a different module.
I didn't want to install the Kernel headers or build modules on the Raspberry Pi.
Keep in mind, that a new module has to be build and installed once you update the Kernel!
Get the Kernel Version Tag
apt search raspberrypi-kernel
# raspberrypi-kernel/stable,now 1.20190819~stretch-1 armhf [installed]
The git tag is the info we are looking for. In this example it is 1.20190819. It's not the full tag though. If you browse the github repo for that tag you'll find the following: https://github.com/raspberrypi/linux/tree/raspberrypi-kernel_1.20190819-1
That is the commit we need to clone or checkout if you have the full history repo.
The Kernel version/tag will not match, if you did run a rpi-update before. You should go back to the default Kernel, if you can.
sudo apt update sudo apt install --reinstall raspberrypi-bootloader raspberrypi-kernel
So we will clone as follows
git clone --depth 1 --branch raspberrypi-kernel_1.20190819-1 https://github.com/raspberrypi/linux.git
git clone --depth 1 https://github.com/raspberrypi/tools
- create a script to setup the toolchain when needed:
# setup_toolchain.sh
#!/bin/bash
export PATH=$PATH:$PWD/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
- source it
source ./setup_toolchain.sh
- install needed tools to your build machine
# ubuntu
sudo apt install bison flex libssl-dev
# fedora
sudo dnf install bison flex openssl-devel
- Follow the official guide to setup make for the Kernel you need for your Hardware. For example building for a Pi 3B+:
cd linux
KERNEL=kernel7 make -j $(nproc) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
- Now It's time to make your changes by using the command below. The only thing I added was the driver for the SI7020 I2C humidity temperature sensor.
KERNEL=kernel7 make -j $(nproc) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
- Make the modules
make -j $(nproc) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
- The module will be in:
drivers/iio/humidity/si7020.ko
- Copy the module to your PI
scp drivers/iio/humidity/si7020.ko pi@pi-usa:/tmp/
ssh pi-usa
# now on the pi do:
sudo cp /tmp/si7020.ko /lib/modules/4.19.66-v7+/kernel/drivers/iio/humidity/
- You can check the module info against an already installed one
modinfo /lib/modules/4.19.66-v7+/kernel/drivers/iio/humidity/si7020.ko
# the vermagic should be the same, for me it is
# vermagic: 4.19.66-v7+ SMP mod_unload modversions ARMv7 p2v8
- Register the module
sudo depmod
- Load the module
modprobe si7020
- Check that the module was loaded
lsmod | grep si7020
- To auto load the module, add the name to
/etc/modules
Create a systemd service unit in /etc/systemd/system/si7020.service
# /etc/systemd/system/si7020.service
[Unit]
Description=load si7020 i2c driver
[Service]
Type=oneshot
ExecStart=/bin/echo si7020 0x40 > /sys/bus/i2c/devices/i2c-1/new_device
[Install]
WantedBy=multi-user.target
To enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable si7020
sudo systemctl start si7020
cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_temp_raw
# 6052
cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_temp_offset
# -4368
cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_temp_scale
# 10.725097656
# calc the result
# (raw + offset) * scale
# we can use bc to calc that for us (example in Degree C)
echo "((6053-4368)*10.7251)/1000" | bc -l
# 18.07179350000000000000
# or as a one liner (could be saved as a script)
TEMP=$(cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_temp_raw) && \
OFF=$(cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_temp_offset) && \
SCALE=$(cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_temp_scale) && \
echo "(($TEMP + $OFF)*$SCALE)/1000" | bc -l
See temperature for details.
HUMI=$(cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_humidityrelative_raw) && \
OFF=$(cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_humidityrelative_offset) && \
SCALE=$(cat /sys/module/si7020/drivers/i2c\:si7020/1-0040/iio\:device0/in_humidityrelative_scale) && \
echo "(($HUMI + $OFF)*$SCALE)/1000" | bc -l