#driver #embedded-hal-driver #embedded-devices #macro-derive #no-std

no-std device-register

一个用于描述设备寄存器权限的 no_std 库,以简化驱动程序开发

7个不稳定版本

0.4.0 2024年1月10日
0.3.1 2023年1月16日
0.3.0 2022年11月29日
0.2.0 2022年10月12日
0.1.1 2022年8月22日

#34 in #嵌入式设备


2 crate 中使用

MIT/Apache

11KB
89

device-register

crates.io documentation

一个用于描述设备寄存器权限的 no_std 库,以简化驱动程序开发。

  • no_std 支持
  • 零成本,不使用 dyn
  • 没有 dsl,只提供一个 derive 宏和实现一个 trait。
  • 错误传递

用法

简单地使用 XXRegister 进行派生,其中 XX 是权限。支持的以下权限有

要定义一个寄存器,只需使用所需的权限进行派生。

然后使用 register 属性来定义其地址、地址类型和错误。

use device_register::*;

#[derive(RWRegister)]
#[register( addr = "42", ty = "u8")]
pub struct Register0(pub u16);

然后,您的驱动程序只需要实现 RegisterInterface 来访问读取/写入/编辑 trait。

完整示例

以下是一个完整示例。有关更多信息,请参阅 tests 文件夹,或查看 tmp117 驱动程序的实际情况。

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

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

// 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")]
struct Register0(pub u16);

impl From<u16> for Register0 {
    fn from(value: u16) -> Self {
        Register0(value)
    }
}

impl From<Register0> for u16 {
    fn from(value: Register0) -> Self {
        value.0
    }
}

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

// Implement a method directly, by passing the trait for specific usecases like async
impl DeviceDriver {
    pub async fn read_async<R>(&self) -> R
    where
        R: ReadableRegister<Address = Address> + From<u16>,
    {
        async {
            let bytes = self.registers.get(&R::ADDRESS.0).unwrap();
            bytes.clone().into()
        }.await
    }
}


// We implement the required interface
impl<R> RegisterInterface<R, Address> for DeviceDriver
where
    R: Register<Address = Address> + Clone + From<u16>,
    u16: From<R>,
{
    // The type of the error, lets have none for now,
    type Error = ();

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

    fn write_register(&mut self, register: &R) -> Result<(), Self::Error> {
        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 type.
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;
}).unwrap();


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

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

MSRV

最低支持的 Rust 版本是 1.75.0,但可能之前的版本也可以与库一起使用

许可证

以下任一许可证下授权

由您选择。

贡献

除非您明确表示,否则根据Apache-2.0许可证定义的,您有意提交以包含在该作品中的任何贡献,均应按上述方式双许可,不附加任何额外条款或条件。

许可证:MIT或Apache-2.0

依赖项

约2MB
约43K SLoC