RDrive Rust 动态驱动组件
架构设计
rdif-* 接口
硬件通用操作接口,为支持动态分发,接口均设计为 dyn-compatible(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());
可参照样例:
初始化
驱动注册
设备获取