dma_gpio 0.1.8

Interact with pi's GPIO via DMA with PWM
Documentation

dma_gpio

If you're looking for a performant and intuitive library to interact with your pi's GPIO with PWM, this is the library for you! (low CPU usage is a plus!)

dma_gpio is a library for pi's GPIO that uses DMA (Direct Memory Access) and PWM via DMA. By using DMA and interacting directly with hardware memory, it manages to be fast (Max Raw Speed ≈ 1.6 MHz on Pi3) while having almost no CPU usage ( ~2%). This project was inspired by its predecessor projects in C, such as PiBits, pi-blaster and RPIO; however, this project bypasses L1 cache which the DMA Controller does not recognize, resulting in a slightly faster GPIO Speed.

Be sure to run your binary file in sudo.

Cross-Compilation

Note that this library will only compile on a 32-bit machine a.k.a. a raspberry pi. So, if you try to compile this on your personal computer, it will most likely fail. So, if you want to test and compile your project with this library on your PC, you should do so by cross-compiling for a specific target such as armv7-unknown-linux-gnueabihf.

Great resource for cross-compilations to Pi that I found helpful is rust-cross. For pi 2 and 3, use armv7-unknown-linux-gnueabihf, and, for pi 1 and zero, use armv6-unknown-linux-gnueabihf.

Getting Started

First, add the crate to the dependencies.

Cargo.toml

...
[dependencies]
dma_gpio = "0.1.8"

pi module will have everything you need.

The easiest way to get started using this library is initializing a Board using BoardBuilder.

BoardBuilder will configure the default setting for the DMA, but manual configuration is also available (read more on this in BoardBuiler). When the Board is initialized, it recognizes which Pi-version it is running on, and interacts with the hardware memory accordingly.

Example

Below example initializes the board using BoardBuilder with default configurations, set the PWM of gpio pins 21 and 22 to 25%, 50%, 75%, then 100% for 1 second each.

Make sure to run the binary file in sudo!

use std::thread::sleep;
use std::time::Duration;
use dma_gpio::pi::BoardBuilder;

fn main() {
    let mut board = BoardBuilder::new()
        .build_with_pins(vec![21, 22]).unwrap();
    board.print_info();
    
    board.set_all_pwm(0.25).unwrap();
    let sec = Duration::from_millis(1000);
    sleep(millis);
    
    board.set_all_pwm(0.5).unwrap();
    sleep(millis);
    
    board.set_all_pwm(0.75).unwrap();
    sleep(millis);
    
    board.set_all_pwm(1.0).unwrap();
    sleep(millis);
    
}

Features

There are two features you can enable in this crate: 'debug' and 'bind_process'. To enable these features, write the dependency for this crate as shown below.

Cargo.toml

...
[dependencies]
...

[dependencies.dma_gpio]
version = "0.1.8"
features = ["debug", "bind_process"]

'debug' feature

By enabling this feature, the library will print out the process every step of the way. This feature will be useful when debugging. Also, after enabling this feature in Cargo.toml, you have to call enable_logger function to see the logs in the terminal.

use std::thread::sleep;
use std::time::Duration;
use dma_gpio::pi::BoardBuilder;

fn main() {
    dma_gpio::enable_logger();
    let mut board = BoardBuilder::new()
        .build_with_pins(vec![21, 22]).unwrap();
    
    board.set_all_pwm(0.5).unwrap();
    let sec = Duration::from_millis(2000);
    sleep(millis);
    
}

'bind_process' feature

This feature lets you access the pi_core module which only has one function bind_process_to_last. This function binds the process to the last core of the Pi. However, to use this function, you have to first install a C library called hwloc. Also, enabling debug feature will print out if you have correctly bound process to the last core.

use std::thread::sleep;
use std::time::Duration;
use dma_gpio::{pi::BoardBuilder, pi_core};

fn main() {
    pi_core::bind_process_to_last();
    let mut board = BoardBuilder::new()
        .build_with_pins(vec![21, 22]).unwrap();
    
    board.set_all_pwm(0.5).unwrap();
    let sec = Duration::from_millis(2000);
    sleep(millis);
    
}

Contact

If you have any questions or recommendations for the betterment of this project, please email me at Jack.Y.L.Dev@gmail.com