rppal

repository·master·Indexed 23 days ago

https://github.com/golemparts/rppal

A Raspberry Pi Peripheral Access Library providing a Rust interface to GPIO, I2C, PWM, SPI, and UART peripherals. It supports various Raspberry Pi models including the Raspberry Pi 5, integrates with embedded-hal traits, and supports USB to serial adapters. Version 0.22.1.

Tokens
4.4K
Snippets
4
Records
28
Agent score
80%

What's inside rppal

  1. Hardware Safety Precautions for RPPAL Examples

    master
    Before running any examples that interface with external hardware components (such as LEDs, servos, or sensors), you must read the comments within the source code. Take all necessary precautions to prevent electrical damage to your Raspberry Pi or connected peripherals.
  2. Install RPPAL via Cargo

    master

    To use RPPAL in your Rust project, add it to your Cargo.toml dependencies. You can do this using cargo add rppal or by manually adding the dependency line.

    Note: RPPAL is no longer maintained as of July 1, 2025. It is compatible with all Raspberry Pi models released before that date, including Raspberry Pi 5.

    [dependencies]
    rppal = "0.22.1"
  3. Cross-compile RPPAL for Raspberry Pi

    master

    If you are developing on a non-Raspberry Pi machine, you must cross-compile for the target ARM architecture.

    1. Install the target

    For 32-bit Linux, use armv7-unknown-linux-gnueabihf. For 64-bit, use aarch64-unknown-linux-gnu.

    rustup target install armv7-unknown-linux-gnueabihf

    2. Configure Cargo

    Create a .cargo/config.toml file in your project root to set the default target:

    [build]
    target = "armv7-unknown-linux-gnueabihf"

    3. Configure VS Code

    To ensure rust-analyzer works correctly, create a .vscode/settings.json file in your project root:

    {
        "rust-analyzer.cargo.target": "armv7-unknown-linux-gnueabihf"
    }
  4. Access Raspberry Pi peripherals with RPPAL

    master

    RPPAL provides a user-friendly interface to access Raspberry Pi peripherals including GPIO, I2C, PWM, SPI, and UART. It also supports USB to serial adapters.

    Key integration features:

    • embedded-hal support: RPPAL implements embedded-hal traits, allowing it to be used with a wide variety of platform-agnostic drivers. It supports both embedded-hal v0.2.7 and v1.
    • Platform Support: Compatible with Raspberry Pi A, A+, B, B+, 2B, 3A+, 3B, 3B+, 4B, 5, CM, CM 3, CM 3+, CM 4, CM 5, 400, Zero, Zero W, and Zero 2 W.
    • OS Requirements: Requires a recent release of Raspberry Pi OS. Other Linux distributions are unsupported.
    • Toolchain Support: Supports both gnu and musl libc targets.
  5. Enable embedded-hal trait implementations

    master

    If your project requires embedded-hal trait implementations, you must specify either the hal or hal-unproven feature flag in your Cargo.toml.

    • hal: Enables embedded-hal trait implementations for all supported peripherals (excludes unproven traits).
    • hal-unproven: Enables all embedded-hal trait implementations, including those marked as unproven. Note that unproven traits do not follow semver rules and may introduce breaking changes in patch releases.
    [dependencies]
    rppal = { version = "0.22.1", features = ["hal"] }
  6. How SPI segments work in multi-segment transfers

    master

    When performing a multi-segment transfer via Spi::transfer_segments, each Segment allows you to fine-tune the SPI protocol parameters for that specific chunk of data.

    Key behaviors to keep in mind:

    1. Buffer Lengths: If you provide both a read and write buffer in a single segment, the transfer length is automatically determined by the shortest of the two buffers. You can check this length using segment.len().
    2. Slave Select (SS) Toggling: By setting ss_change to true, you can force the Slave Select line to toggle between segments. This is useful for protocols that require a chip-select pulse between different command/data phases.
    3. Inheritance: If you do not explicitly set a parameter (like clock_speed or bits_per_word) on a segment, it defaults to 0, which instructs the driver to use the global configuration of the Spi instance.
  7. Implement embedded-hal SPI traits with RPPAL

    master

    RPPAL provides implementations for several embedded-hal versions to allow the Spi struct to be used in generic embedded drivers. Depending on which features you enable, Spi implements the following:

    embedded-hal (Modern)

    When the embedded-hal feature is enabled, Spi implements:

    • embedded_hal::spi::ErrorType
    • embedded_hal::spi::Error
    • embedded_hal::spi::SpiBus<u8> (providing read, write, transfer, transfer_in_place, and flush)
    • embedded_hal::spi::SpiDevice<u8> (via SimpleHalSpiDevice)

    embedded-hal-0 (Legacy)

    When the embedded-hal-0 feature is enabled, Spi implements:

    • embedded_hal_0::blocking::spi::Transfer<u8>
    • embedded_hal_0::blocking::spi::Write<u8>
    • embedded_hal_0::spi::FullDuplex<u8>

    embedded-hal-nb (Non-blocking)

    When the embedded-hal-nb feature is enabled, Spi implements:

    • embedded_hal_nb::spi::FullDuplex<u8>
  8. PWM Channel mapping by model

    master

    PWM channel availability depends on the Raspberry Pi model being used:

    Raspberry Pi 5 and later

    Supports 4 hardware PWM channels:

    • Channel::Pwm0 = GPIO12
    • Channel::Pwm1 = GPIO13
    • Channel::Pwm2 = GPIO18
    • Channel::Pwm3 = GPIO19

    Older models (pre-Raspberry Pi 5)

    Supports 2 hardware PWM channels:

    • Channel::Pwm0 = GPIO12 or GPIO18
    • Channel::Pwm1 = GPIO13 or GPIO19

    Note: Using analog audio output consumes both PWM channels on older models, which may cause conflicts if you attempt to access PWM simultaneously.

  9. Use RPPAL with embedded-hal traits

    master

    RPPAL can be used as a hardware abstraction layer for the Rust ecosystem by enabling specific features. This allows you to use RPPAL-compatible hardware with any driver that implements the embedded-hal traits.

    To use these traits, you must enable one of the following features in your Cargo.toml:

    • embedded-hal-0 (for embedded-hal v0.2.7)
    • embedded-hal (for embedded-hal v1)
    • embedded-hal-nb (for non-blocking embedded-hal support)
  10. I2C, SPI, PWM, and UART Usage Patterns

    master

    The following examples demonstrate communication with other peripherals and hardware modules:

    • I2C (Real-Time Clock): i2c_ds3231.rs shows how to set and retrieve time on a Maxim Integrated DS3231 RTC via the I2C bus.
    • Hardware PWM:
      • pwm_blinkled.rs blinks an LED using the Raspberry Pi's dedicated hardware PWM.
      • pwm_servo.rs rotates a servo motor using hardware PWM.
    • SPI (EEPROM): spi_25aa1024.rs demonstrates data transfers to a Microchip 25AA1024 serial EEPROM using the SPI bus.
    • UART (Serial): uart_blocking_read.rs demonstrates how to perform blocking reads while waiting for incoming serial data.
  11. GPIO Usage Patterns and Examples

    master

    The following examples demonstrate various ways to interact with the Raspberry Pi GPIO pins:

    • Basic LED Blinking: gpio_blinkled.rs blinks an LED in a simple loop.
    • Signal Handling: gpio_blinkled_signals.rs blinks an LED while handling SIGINT (Ctrl+C) and SIGTERM signals to ensure the pin state is reset before the application exits.
    • Concurrency with MPSC: gpio_multithreaded_mpsc.rs blinks an LED on a separate thread using a Multi-Producer Single-Consumer (MPSC) channel.
    • Concurrency with Mutex: gpio_multithreaded_mutex.rs demonstrates blinking an LED controlled from multiple threads using a Mutex.
    • Software PWM for Servos: gpio_servo_softpwm.rs rotates a servo motor using software-based Pulse Width Modulation (PWM).
    • Input Interrupts and Shared State: gpio_shared_button_state.rs demonstrates sharing state with an input interrupt and pausing program execution until a specific number of event changes occur.
    • GPIO Status Inspection: gpio_status.rs retrieves and displays the mode and logic level for every pin on the 26-pin or 40-pin GPIO header in an ASCII table.
  12. Blink an LED using GPIO

    master

    This example demonstrates how to control a GPIO pin to blink an LED. This code uses BCM pin numbering (e.g., BCM 23 corresponds to physical pin 16).

    Caution: Always use an appropriate resistor in series with an LED to prevent damage to the GPIO pin or the LED.

    use std::error::Error;
    use std::thread;
    use std::time::Duration;
    
    use rppal::gpio::Gpio;
    use rppal::system::DeviceInfo;
    
    // Gpio uses BCM pin numbering. BCM GPIO 23 is tied to physical pin 16.
    const GPIO_LED: u8 = 23;
    
    fn main() -> Result<(), Box<dyn Error>> {
        println!("Blinking an LED on a {}.", DeviceInfo::new()?.model());
    
        let mut pin = Gpio::new()?.get(GPIO_LED)?.into_output();
    
        // Blink the LED by setting the pin's logic level high for 500 ms.
        pin.set_high();
        thread::sleep(Duration::from_millis(500));
        pin.set_low();
    
        Ok()
    }