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 中使用
11KB
89 行
device-register
一个用于描述设备寄存器权限的 no_std
库,以简化驱动程序开发。
no_std
支持- 零成本,不使用 dyn
- 没有 dsl,只提供一个 derive 宏和实现一个 trait。
- 错误传递
用法
简单地使用 XXRegister
进行派生,其中 XX 是权限。支持的以下权限有
RORegister
,只读权限WORegister
,只写权限EORegister
,只编辑权限,当一个寄存器需要读取-修改-写入时RERegister
,读取和编辑权限RWRegister
,读取、写入和编辑权限。
要定义一个寄存器,只需使用所需的权限进行派生。
然后使用 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 License, Version 2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
-
麻省理工学院许可证(《LICENSE-MIT》或http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确表示,否则根据Apache-2.0许可证定义的,您有意提交以包含在该作品中的任何贡献,均应按上述方式双许可,不附加任何额外条款或条件。
许可证:MIT或Apache-2.0
依赖项
约2MB
约43K SLoC