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:

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.
    irq.wait();
     
    // Clear the triggering interrupt.
    pruss.intc.clear_sysevt(Sysevt::S19);
 
    // Do nothing: the `pruss` destructor will stop any running code and release ressources.
    println!("We are done...");
}

Modules

util

Useful objects and functions.

Structs

EvtoutIrq

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

Intc

The PRU interrupt controller.

IntcConfig

PRU interrupt controller configuration.

MemSegment

View of a contiguous memory segment.

PruCode

Handle to a binary code loaded in the PRU.

PruLoader

PRU instruction code loader.

Pruss

Main interface to the PRU subsystem.

Enums

Channel

A channel to which system interrupts can be mapped.

Error

PRU subsystem error.

Evtout

An event out.

Host

A host to which channels can be mapped.

Sysevt

A PRU-generated system event.

Type Definitions

Result

Result type for the PRU subsystem.