Crate prusst [] [src]

A convenient Rust interface to the UIO kernel module for TI Programmable Real-time Unit coprocessors, with roughly the same functionality as the C prussdrv library but with a safer, rustic API that attempts to mitigate risks related to uninitialized or invalid register states, use of freed memory, memory allocations conflicts etc.

Design rationale

The design of the library exploits the Rust type system to reduce the risk of shooting onself in the foot. Its architecture is meant to offer improved ergonomics compared to its C relative, while operating at a similarly low level of abstraction and providing equivalent functionality.

Data-race safety is warranted by checking that only one Pruss instance (a view of the PRU subsystem) is running at a time. The magic of the Rust borrowing rules will then statically ensure, inter alia:

  • the absence of memory aliasing for local and shared PRU RAM, meaning that a previously allocated RAM segment may not be re-used before the data it contains is released,

  • the impossibility to request code execution on a PRU core before the code has actually been loaded,

  • the impossibility to overwrite PRU code that is already loaded and still in use,

  • the impossibility to concurrently modify the interrupt mapping.

Type safety also avoids many pitfalls associated with interrupt management. Unlike the C prussdrv library, system events, host interrupt, events out and channels are all distinct types: they cannot be misused or inadvertently switched in function calls. A related benefit is that the interrupt management API is very self-explanatory.

Event handling is one of the few places where prusst requires the user to be more explicit than the C prussdrv library. Indeed, the prussdrv_pru_clear_event function of the C driver automatically re-enables an event out after clearing the triggering system event, which may wrongly suggest that the combined clear-enable operation is thread-safe (it isn't). In contrast, prusst mandates that both Intc::clear_sysevt and Intc::enable_host be called if the event out needs to be caught again. This behavior is probably less surprising and is arguably more consistent with the atomicity of other interrupt management functions.

Hello world

extern crate prusst;
use prusst::{Pruss, IntcConfig, Sysevt, Evtout};
use std::fs::File;
fn main() {
    // Configure and get a view of the PRU subsystem.
    let mut pruss = Pruss::new(&IntcConfig::new_populated()).unwrap();
    // Get a handle to an event out before it is triggered.
    let irq = pruss.intc.register_irq(Evtout::E0);
    // Open, load and run a PRU binary.
    let mut file = File::open("hello.bin").unwrap();
    unsafe { pruss.pru0.load_code(&mut file).unwrap().run(); }
    // Wait for the PRU code from hello.bin to trigger an event out.
    // Clear the triggering interrupt.
    // Do nothing: the `pruss` destructor will stop any running code and release ressources.
    println!("We are done...");



Useful objects and functions.



Synchronization primitive that can be used to wait for an event out.


The PRU interrupt controller.


PRU interrupt controller configuration.


View of a contiguous memory segment.


Handle to a binary code loaded in the PRU.


PRU instruction code loader.


Main interface to the PRU subsystem.



A channel to which system interrupts can be mapped.


PRU subsystem error.


An event out.


A host to which channels can be mapped.


A PRU-generated system event.

Type Definitions


Result type for the PRU subsystem.