1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
//! [dma_gpio](index.html) is a library for pi's GPIO that uses DMA ([Direct Memory Access](https://en.wikipedia.org/wiki/Direct_memory_access)) and [PWM via DMA](https://stackoverflow.com/questions/50427275/raspberry-how-does-the-pwm-via-dma-work). //! 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](https://github.com/richardghirst/PiBits), [pi-blaster](https://github.com/sarfata/pi-blaster) and [RPIO](https://github.com/metachris/RPIO/tree/master/source); however, this project bypasses L1 cache which the DMA Controller does not recognize, resulting in a slightly faster GPIO Speed. //! //! [pi](pi/index.html) module will have everything you need. //! //! # Getting Started //! First, add the crate to the dependencies. //! ```no_run //! Cargo.toml //! //! ... //! [dependencies] //! dma_gpio = "0.1.6" //! ``` //! //! The easiest way to get started using this library is initializing a [Board](pi/struct.Board.html) using [BoardBuilder](pi/struct.BoardBuilder.html). //! BoardBuilder will configure the default setting for the DMA, but manual configuration is also available (read more on this in [BoardBuiler](pi/struct.BoardBuilder.html#building-with-custom-settings)). //! 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!!! //! //! ```no_run //! 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. //! ```no_run //! Cargo.toml //! //! ... //! [dependencies] //! ... //! //! [dependencies.dma_gpio] //! version = "0.1.6" //! 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](fn.enable_logger.html) function to see the logs in the terminal. //! ```no_run //! 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](pi_core/index.html) module which only has one function [bind_process_to_last](pi_core/fn.bind_process_to_last.html). 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](https://github.com/daschl/hwloc-rs#install-hwloc-on-os-x). Also, enabling debug feature will print out if you have correctly bound process to the last core. //! ```no_run //! 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](https://github.com/japaric/rust-cross) and [this blog](https://piers.rocks/docker/containers/raspberry/pi/rust/cross/compile/compilation/2018/12/16/rust-compilation-for-raspberry-pi.html). 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 #[macro_use] extern crate log; #[cfg(feature = "debug")] use env_logger; pub mod mailbox; pub mod pi; // if you wanna bind the process to core for better performance? #[cfg(feature = "bind_process")] pub mod pi_core; /// use it to see traces when running #[cfg(feature = "debug")] pub fn enable_logger(){ env_logger::Builder::new() .default_format() .default_format_module_path(false) .default_format_timestamp(false) .filter_level(log::LevelFilter::Warn) .filter_module("dma_gpio", log::LevelFilter::Trace) .init(); }