device-register

crates.io documentation

A no_std, zero cost toolkit to describe the registers of a device to ease driver development. * no_std support * Zero cost, no use of dyn * No dsl, just a derive macro and impl a trait. * Error passthrough

Usage

Simply derive using XXRegister, where XX is the premission. The following permissions are supported * RORegister, read only permission * WORegister, write only permission * EORegister, edit only permission, when a register need to be read-modify-write * RERegister, Read and edit permission * RWRegister, Read, write and edit permission.

To define a register, simply derive using the desired permission.

Then use the register attribute to define it's address, type for the address and the error.

```rust

[derive(RWRegister)]

[register( addr = "42", ty = "u8", err = "DeviceError" )]

pub struct Register0(pub u16); ``` Then, your driver only need to implement the RegisterInterface to have access to the read/write/edit traits.

Complete example

Here is a complete example. See the tests folder for more, or checkout the tmp117 driver for actual usage.

```rust use std::collections::HashMap; use device_register::*;

// The type of the address used by the driver struct Address(pub u8);

// The type of the error, lets have none for now, type DeviceError = ();

// We define the register with Read/Write permission // Then we pass the address type, value and error type of the driveer

[derive(Debug, Copy, PartialEq, Eq, Clone, RWRegister)]

[register( addr = "Address(1)", ty = "Address", err = "DeviceError" )]

struct Register0(pub u16);

// Mock of the device driver struct DeviceDriver { // Simulate reading from the device pub registers: HashMap, }

// Implement a method directly, by passing the trait for specific usecases like async impl DeviceDriver { pub async fn read_async(&self) -> R where R: ReadableRegister

+ From, { async { let bytes = self.registers.get(&R::ADDRESS.0).unwrap(); bytes.clone().into() }.await } }

// We implement the required interface impl RegisterInterface for DeviceDriver where R: Register

+ Clone + From, u16: From, { fn read_register(&mut self) -> Result { let bytes = self.registers.get(&R::ADDRESS.0).unwrap(); Ok(bytes.clone().into()) }

fn write_register(&mut self, register: &R) -> Result<(), DeviceError> {
    self.registers.insert(R::ADDRESS.0, register.clone().into());
    Ok(())
}

}

let mut device = DeviceDriver{ registers: HashMap::new(), }; // We can the Read/Write/Edit the registers that uses the Address and DeviceError types. let write = Register0(42); device.write(write).unwrap();

let read: Register0 = device.read().unwrap();

assert_eq!(read, write);

device.edit(|r: &mut Register0| { r.0 = 43; r }).unwrap();

let read: Register0 = device.read().unwrap(); assert_eq!(read, Register0(43));

// Custom implementation, async is an example of usecase for custom implements tokiotest::blockon( async { let readasync: Register0 = device.readasync().await; assert_eq!(read, Register0(43)); } );

```

License

Licensed under either of - Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

License: MIT OR Apache-2.0