dma_gpio 0.1.3

Interact with pi's GPIO via DMA with PWM
Documentation

dma_gpio

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 very 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.

pi module will have everything you need.

Getting Started

First, add the crate to the dependencies.

Cargo.toml

...
[dependencies]
dma_gpio = "0.1.0"

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.0"
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() {
    dma_gpio::enable_logger();
    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);
    
}

Cross-Compilation

Since compiling a rust project on a pi may take a very long time, it's often a good idea to cross-compile on your computer. Great resources for cross-compilations to Pi that I found helpful are rust-cross and this blog. For pi 2 and 3, use armv7-unknown-linux-gnueabihf, and, for pi 1 and zero, use armv6-unknown-linux-gnueabihf (if you can find one, that is).

Contact

For questions, please email to Jack.Y.L.Dev@gmail.com