A robust, interrupt-driven Linux Kernel Module for the nRF24L01+ 2.4GHz wireless transceiver, designed for Single Board Computers like the Raspberry Pi.
Unlike user-space Python or C++ libraries, this driver interfaces directly with the Linux Kernel SPI and GPIO subsystems. It exposes a standard Character Device (/dev/nrf24) for reading/writing radio payloads, and a clean Sysfs directory (/sys/nrf24/) for live hardware configuration.
- DMA-Safe SPI Transfers: Dedicated Kernel buffers allocated with
GFP_DMAfor maximum reliability. - Interrupt-Driven (IRQ): Hardware interrupts wake up waiting processes only when new data arrives (zero CPU spinning).
- Native UNIX Stream Interface: Send and receive string/binary payloads directly using standard Unix tools (
cat,echo,tee). - Live Configuration via
/sys/nrf24/: Change RF channels, data rates, transmission power, and Auto-ACK parameters on the fly. - Clone-Friendly: Configurable Auto-ACK toggle to support low-cost or asymmetric nRF24 modules.
Many low-cost nRF24L01+ modules available on the market are unofficial clones or counterfeit chips (often labeled as Si24R1 or generic clones). Due to manufacturing variations or silicon defects, several of these clone modules exhibit hardware-level flaws where they can only function as transmitters (TX) or only as receivers (RX), but fail when switching modes dynamically.
Labeling Recommendation: It is strongly recommended to test your individual modules, identify which ones work strictly for transmitting or receiving, and physically label or tag each module accordingly to avoid troubleshooting non-functional configurations in future setups.
As a result of these hardware limitations, hardware ACK (Acknowledgement) and dynamic bidirectional payload exchanges may fail silently or drop packets consistently. Consequently, the current driver implementation operates as a unidirectional (UDP-style) communication link, where data frames are transmitted without waiting for hardware ACKs.
Important: It is strongly recommended to use the nRF24L01+ Adapter Module (with an on-board AMS1117 3.3V regulator and decoupling capacitors) to ensure power stability. Connect VCC of the adapter module to 5V.
nRF24L01+ Power Adapter Pinout
βββββββββββββββββ
GND ββ€ [1] [2] ββ VCC (5V Input)
CE ββ€ [3] [4] ββ CSN
SCK ββ€ [5] [6] ββ MOSI
MISO ββ€ [7] [8] ββ IRQ (Unused)
βββββββββββββββββ| nRF24L01+ | RPi Physical Pin (40-pin Header) | Function / Signal |
|---|---|---|
| VCC | Pin 2 or Pin 4 | 5V Power |
| GND | Pin 6 | Ground |
| CE | Pin 22 | GPIO 25 |
| CSN | Pin 24 | GPIO 8 (SPI0_CE0) |
| SCK | Pin 23 | GPIO 11 (SPI0_SCLK) |
| MOSI | Pin 19 | GPIO 10 (SPI0_MOSI) |
| MISO | Pin 21 | GPIO 9 (SPI0_MISO) |
| IRQ | Pin 18 | GPIO 24 (Using it for Hardware Interrupt Line) |
Ensure you have the Linux Kernel headers installed on your SBC:
sudo apt update
sudo apt install raspberrypi-kernel-headers build-essential device-tree-compiler linux-headers-$(uname -r)Clone this repository
git clone https://github.com/rbustos567/nrf24_linux_driver.gitcd nrf24_linux_driver/dts
dtc -@ -I dts -O dtb -o nrf24.dtbo nrf24-overlay.dtssudo cp nrf24.dtbo /boot/overlays/
# Enable it by adding the following line to /boot/firmware/config.txt or /boot/config.txt (depending on your OS version):
dtoverlay=nrf24
# Ensure the primary SPI Controller is enabled in /boot/firmware/config.txt or /boot/config.txt (depending on your OS version):
dtparam=spi=on
# Shutdown and restart the system to apply the Device Tree changes
sudo shutdown now
# After rebooting, verify that the SPI interface is active
ls -l /dev/spidev*sudo cp nrf24.dtbo /lib/firmware/
# Enable it in /boot/uEnv.txt:
uboot_overlay_addr0=/lib/firmware/nrf24.dtbo
# Shutdown and restart the system to apply the Device Tree changes
sudo shutdown now
# Check if spidev device is present
ls -l /dev/spidev*
# Verify overlay loading in kernel logs
dmesg | grep -i "spi"cd ../src
makesudo insmod nrf24.ko# View kernel debug output
dmesg | tail -n 30
# device char was created
ls -la /sys/nrf24/
# List module was uploaded
lsmod | grep nrf24Simply read from /dev/nrf24. The process will sleep until a wireless packet arrives via IRQ:
# Continuous string reader
sudo cat /dev/nrf24
# Inspect raw hexadecimal bytes
sudo hexdump -C /dev/nrf24Write any byte sequence (up to 32 bytes per packet) to /dev/nrf24:
# Send a string message
echo -n "Hello World!" | sudo tee /dev/nrf24 > /dev/nullYou can read or update hardware registers at runtime without reloading the module:
Valid range: 0 to 125 (2.400 GHz - 2.525 GHz).
# Check current channel
cat /sys/nrf24/channel
# Set channel to 76 (2.476 GHz)
echo 76 | sudo tee /sys/nrf24/channelSupported options: 250k, 1M, 2M.
# Set air data rate to 250 kbps (Maximum sensitivity/range)
echo "250k" | sudo tee /sys/nrf24/datarateSupported dBm values: -18, -12, -6, 0.
# Set maximum output power (0 dBm)
echo "0" | sudo tee /sys/nrf24/tx_powerEnable (1) or disable (0). Disabling Auto-ACK (Fire-and-Forget mode) is strongly recommended when using low-cost clone modules.
# Disable Auto-ACK
echo 0 | sudo tee /sys/nrf24/auto_ackTo remove the module from memory during testing or driver updates:
sudo rmmod nrf24This project is licensed under the GPL-2.0 License - see the LICENSE file for details.