Skip to content

Commit

Permalink
refactor: set /dev/gpiochip0 as default (#1018)
Browse files Browse the repository at this point in the history
resolves #1017

This also adds some info to the docs that was requested in #1017

* remove unnecessary members
* make cached chip FD static
  • Loading branch information
2bndy5 authored Feb 1, 2025
1 parent 6f3da43 commit 929a5aa
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 44 deletions.
6 changes: 4 additions & 2 deletions RF24.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ class RF24
*
* See [Related Pages](pages.html) for device specific information
*
* @param _cepin The pin attached to Chip Enable on the RF module
* @param _cepin The pin attached to Chip Enable on the RF module.
* Review our [Linux general](rpi_general.md) doc for details about selecting pin numbers on Linux systems.
* @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module.
* - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI)
* is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for
Expand Down Expand Up @@ -290,7 +291,8 @@ class RF24
* @param spiBus A pointer or reference to an instantiated SPI bus object.
* The `_SPI` datatype is a "wrapped" definition that will represent
* various SPI implementations based on the specified platform.
* @param _cepin The pin attached to Chip Enable on the RF module
* @param _cepin The pin attached to Chip Enable on the RF module.
* Review our [Linux general](rpi_general.md) doc for details about selecting pin numbers on Linux systems.
* @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module.
* - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI)
* is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin.
Expand Down
2 changes: 2 additions & 0 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ words:
- iomanip
- ITSYBITSY
- Jannis
- Jetson
- jscrane
- KBPS
- Konde
Expand All @@ -142,6 +143,7 @@ words:
- ldiaz
- libboost
- libc
- libgpiod
- libmaple
- libncurses
- librf
Expand Down
6 changes: 6 additions & 0 deletions docs/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ SHOW_FILES = YES

SHOW_NAMESPACES = NO

# Don't display the ugly/complicated "tree view" side menu.
# And, restore the top (simpler) navigation bar.
# As of doxygen v1.13.0, these default values changed from NO to YES
GENERATE_TREEVIEW = NO
DISABLE_INDEX = NO

#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
Expand Down
8 changes: 4 additions & 4 deletions docs/linux_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ Using CMake: (See the [instructions using CMake](using_cmake.md) for more inform
./install.sh
```

@warning
@warning
`SPIDEV` is now always selected as the default driver because
all other Linux drivers are being removed in the future.
See [RF24 issue #971](https://github.com/nRF24/RF24/issues/971) for rationale.

It will also ask to install a python package named [pyRF24](https://github.com/nRF24/pyRF24).
This is not the same as the traditionally provided python wrappers as the pyRF24 package can be
This is not the same as the traditionally provided python wrappers because the pyRF24 package can be
used independent of the C++ installed libraries. For more information on this newer python
package, please check out [the pyRF24 documentation](https://nrf24.github.io/pyRF24/).
4. Try an example from one of the libraries
Expand Down Expand Up @@ -76,7 +76,7 @@ See the [instructions using CMake](using_cmake.md) for more information and opti
./install.sh
```

@warning
@warning
`SPIDEV` is now always selected as the default driver because
all other Linux drivers are being removed in the future.
See [RF24 issue #971](https://github.com/nRF24/RF24/issues/971) for rationale.
Expand Down Expand Up @@ -115,7 +115,7 @@ See the [instructions using CMake](using_cmake.md) for more information and opti
```
It automatically detects device and build environment.

@warning
@warning
`SPIDEV` is now always selected as the default driver because
all other Linux drivers are being removed in the future.
See [RF24 issue #971](https://github.com/nRF24/RF24/issues/971) for rationale.
Expand Down
31 changes: 29 additions & 2 deletions docs/rpi_general.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,43 @@ for proper constructor to address the correct spi device at /dev/spidev\<a\>.\<b
Choose any GPIO output pin for radio CE pin.
> [!WARNING]
> The pin numbers may be different for certain systems.
> In this library's examples, we use the BCM pin numbers for BroadCom chips such as
> those used on all Raspberry Pi models.
>
> For Raspberry Pi clones, such as Orange Pi or Banana Pi, defer to the pin numbers described
> in their corresponding documentation/manual.
>
> Hint: If libgpiod is installed (not required for this library),
> then you can use the included
> [CLI tools shipped with libgpiod](https://libgpiod.readthedocs.io/en/latest/gpio_tools.html)
> to gleam system-specific details.
### Linux kernel (SPIDEV driver) and the GPIO chip number
This RF24 library, as of v1.4.9, uses the Linux kernel's Character Device API to interface
with GPIO pins (AKA "lines" in kernel docs). Previous versions used the deprecated "sys fs" interface.
By default, this library attempts to use pins exposed via `/dev/gpiochip0`.
Some systems have multiple public-facing GPIO chips integrated (ie nVidia Jetson series).
If your system exposes the desired GPIO pins via a different chip (ie `/dev/gpiochip4`), then the
`RF24_LINUX_GPIO_CHIP` can be set to the correct value when compiling the library.
```shell
cmake .. -DRF24_LINUX_GPIO_CHIP="/dev/gpiochip4"
```

### General

```cpp
RF24 radio(22,0);
RF24 radio(22, 0);
```
### MRAA Constructor
```cpp
RF24 radio(15,0);
RF24 radio(15, 0);
```

See [the MRAA documentation for Raspberry Pi support](http://iotdk.intel.com/docs/master/mraa/rasppi.html)
Expand Down
7 changes: 4 additions & 3 deletions utility/RPi/RF24_arch_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ typedef uint8_t rf24_gpio_pin_t;

#ifndef RF24_LINUX_GPIO_CHIP
/**
* The default GPIO chip to use. Defaults to `/dev/gpiochip4` (for RPi5).
* Falls back to `/dev/gpiochip0` if this value is somehow incorrect.
* The default GPIO chip to use.
* Defaults to `/dev/gpiochip0`.
* Define this when compiling if this value is somehow incorrect.
*/
#define RF24_LINUX_GPIO_CHIP "/dev/gpiochip4"
#define RF24_LINUX_GPIO_CHIP "/dev/gpiochip0"
#endif

#define PSTR(x) (x)
Expand Down
24 changes: 8 additions & 16 deletions utility/SPIDEV/gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,22 @@ std::map<rf24_gpio_pin_t, gpio_fd> cachedPins;
struct gpio_v2_line_request request;
struct gpio_v2_line_values data;

// initialize static member.
int GPIOChipCache::fd = -1;

void GPIOChipCache::openDevice()
{
if (fd < 0) {
fd = open(chip, O_RDONLY);
fd = open(RF24_LINUX_GPIO_CHIP, O_RDONLY);
if (fd < 0) {
std::string msg = "Can't open device ";
msg += chip;
msg += RF24_LINUX_GPIO_CHIP;
msg += "; ";
msg += strerror(errno);
throw GPIOException(msg);
return;
}
}
chipInitialized = true;
}

void GPIOChipCache::closeDevice()
Expand Down Expand Up @@ -75,31 +77,21 @@ GPIO::~GPIO()

void GPIO::open(rf24_gpio_pin_t port, int DDR)
{
try {
gpioCache.openDevice();
}
catch (GPIOException& exc) {
if (gpioCache.chipInitialized) {
throw exc;
return;
}
gpioCache.chip = "/dev/gpiochip0";
gpioCache.openDevice();
}
gpioCache.openDevice();

// get chip info
gpiochip_info info;
memset(&info, 0, sizeof(info));
int ret = ioctl(gpioCache.fd, GPIO_GET_CHIPINFO_IOCTL, &info);
if (ret < 0) {
std::string msg = "Could not gather info about ";
msg += gpioCache.chip;
msg += RF24_LINUX_GPIO_CHIP;
throw GPIOException(msg);
return;
}

if (port > info.lines) {
std::string msg = "pin number " + std::to_string(port) + " not available for " + gpioCache.chip;
std::string msg = "pin number " + std::to_string(port) + " not available for " + RF24_LINUX_GPIO_CHIP;
throw GPIOException(msg);
return;
}
Expand Down
13 changes: 9 additions & 4 deletions utility/SPIDEV/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ typedef uint16_t rf24_gpio_pin_t;
* The default GPIO chip to use. Defaults to `/dev/gpiochip4` (for RPi5).
* Falls back to `/dev/gpiochip0` if this value is somehow incorrect.
*/
#define RF24_LINUX_GPIO_CHIP "/dev/gpiochip4"
#define RF24_LINUX_GPIO_CHIP "/dev/gpiochip0"
#endif

/** Specific exception for GPIO errors */
Expand All @@ -42,9 +42,14 @@ class GPIOException : public std::runtime_error
/// This struct's destructor should close any cached GPIO pin requests' file descriptors.
struct GPIOChipCache
{
const char* chip = RF24_LINUX_GPIO_CHIP;
int fd = -1;
bool chipInitialized = false;
/// @brief The file descriptor used to access the GPIO chip.
///
/// This is used to open/close pins exposed by the GPIO chip specified via
/// `RF24_LINUX_GPIO_CHIP`.
///
/// Because this member is static, all instances (& derivative instances) of this
/// struct use the same file descriptor.
static int fd;

/// Open the File Descriptor for the GPIO chip
void openDevice();
Expand Down
16 changes: 3 additions & 13 deletions utility/SPIDEV/interrupt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,31 +65,21 @@ int attachInterrupt(rf24_gpio_pin_t pin, int mode, void (*function)(void))
detachInterrupt(pin);
GPIO::close(pin);

try {
irqChipCache.openDevice();
}
catch (GPIOException& exc) {
if (irqChipCache.chipInitialized) {
throw exc;
return 0;
}
irqChipCache.chip = "/dev/gpiochip0";
irqChipCache.openDevice();
}
irqChipCache.openDevice();

// get chip info
gpiochip_info info;
memset(&info, 0, sizeof(info));
int ret = ioctl(irqChipCache.fd, GPIO_GET_CHIPINFO_IOCTL, &info);
if (ret < 0) {
std::string msg = "[attachInterrupt] Could not gather info about ";
msg += irqChipCache.chip;
msg += RF24_LINUX_GPIO_CHIP;
throw IRQException(msg);
return 0;
}

if (pin > info.lines) {
std::string msg = "[attachInterrupt] pin " + std::to_string(pin) + " is not available on " + irqChipCache.chip;
std::string msg = "[attachInterrupt] pin " + std::to_string(pin) + " is not available on " + RF24_LINUX_GPIO_CHIP;
throw IRQException(msg);
return 0;
}
Expand Down

0 comments on commit 929a5aa

Please sign in to comment.