6 releases
new 0.1.6 | Feb 19, 2025 |
---|---|
0.1.5 | Feb 19, 2025 |
#200 in Embedded development
117 downloads per month
Used in 3 crates
(via sparreal-kernel)
38KB
836 lines
RDrive Rust 动态驱动组件
架构设计
rdif-* 接口
硬件通用操作接口,为支持动态分发,接口均设计为object safe
。
rdrive-macros
便于驱动注册的宏。
rdrive 动态驱动容器
驱动容器,负责驱动注册、遍历、所有权控制。
设备所有权设计为长期借用模式,通过 Device<T>
进行包装,不同于 Mutex<T>
,当一个任务借用了设备后,会获取其所有权,其他任务在尝试借用时会得到 Error
并得到拥有者的任务ID,可用于强制关闭任务。借用者获取所有权后,可进行无锁操作。对 Device<T>
的复制会获取其弱指针,方便其他任务进行快速索引,在中断中可使用弱指针强制获取所有权。
驱动可在不同 crate
进行注册,可实现在一个单独文件中完成所有注册流程,例如:
module_driver!(
name: "GICv3",
probe_kinds: &[
ProbeKind::Fdt {
compatibles: &["arm,gic-v3"],
on_probe: OnProbeKindFdt::Intc(probe_gic)
}
]
);
fn probe_gic(node: Node<'_>) -> Result<FdtProbeInfo, Box<dyn Error>> {
let mut reg = node.reg().ok_or(format!("[{}] has no reg", node.name))?;
let gicd_reg = reg.next().unwrap();
let gicr_reg = reg.next().unwrap();
let gicd = iomap(
(gicd_reg.address as usize).into(),
gicd_reg.size.unwrap_or(0x1000),
);
let gicr = iomap(
(gicr_reg.address as usize).into(),
gicr_reg.size.unwrap_or(0x1000),
);
Ok(FdtProbeInfo {
hardware: Box::new(Gic::new(gicd, gicr, Default::default())),
fdt_parse_config_fn: fdt_parse_irq_config,
})
}
上述代码完成了 Gic
驱动注册,在后续 probe
阶段会调用 probe_gic
函数进行驱动创建。
支持通过设备树遍历设备、静态配置设备。
系统适配
-
LinkerScript
添加:.driver.register : ALIGN(4K) { _sdriver = .; *(.driver.register .driver.register.*) _edriver = .; . = ALIGN(4K); }
-
系统代码中添加:
fn driver_registers() -> &'static [u8] { unsafe extern "C" { fn _sdriver(); fn _edriver(); } unsafe { &*slice_from_raw_parts( _sdriver as *const u8, _edriver as usize - _sdriver as usize) } } fn driver_registers() -> DriverRegisterSlice { DriverRegisterSlice::from_raw(driver_registers()) }
-
初始化(设备树方式):
fn init() { let info = DriverInfoKind::Fdt { addr: // 设备树地址, }; // 库初始化 rdrive::init(info); // 添加驱动注册器 rdrive::register_append(driver_registers().as_slice()); // 其他设备依赖中断控制器,优先初始化 rdrive::probe_intc().unwrap(); irq::init_main_cpu(); // 任务等功能依赖系统时钟,优先初始化 rdrive::probe_timer().unwrap(); time::init_current_cpu(); }
-
遍历设备:
rdrive::probe().unwrap();
-
获取设备:
let mut ls = rdrive::read(|m| m.timer.all()); let (_, timer) = ls.pop()?; let mut timer = timer.upgrade()?.spin_try_borrow_by(0.into()); // 可自由使用 mut timer,此时其他任务尝试借用会返回 Error
可参照样例:
Dependencies
~0.5–1MB
~21K SLoC