【 以下文字转载自 Circuit 讨论区 】
发信人: lvsoft (Lv(The Last Guardian)), 信区: Circuit
标 题: Re: 小新不懂就问:自己设计的开发板固件怎么搞定的?
发信站: 水木社区 (Fri Jan 5 23:37:04 2024), 站内
我又忍不住又要来安利rust了...
我最近通过一个项目已经基本完全迁移到rust上开发了。
目前在手撸一个运控。
我是感觉到rust的抽象能力实在是太爽了,比如我是先定义mm,um,丝,inch等公制,英制单位,(注意丝这个单位英文里没有对应的单词,于是我直接用了中文...)
比如驱动频率有hz,khz,mhz。旋转运动有rpm,feedrate有mm/min,ipm等单位...
写死之后基本上不可能出错。因为整个系统不允许任何出现无量纲的数字...
比如设定电机转速得写成set_rotary_speed(3000.rpm()),不能直接写个3000进去。
比如pwm频率得写成10.khz(),不能直接写10000。
然后位置也有量纲的区分,比如move_to如果传的是Position(100.mm())表示绝对定位100mm,如果没有做过homing就会报错。
但如果没有做过homing,可以传Displacement(100.mm()),表示从当前位置开始算的相对位移,
然后不仅传入的数字不允许出现无量纲,这些单位的内部是否可以计算,计算的结果也被我定义了的单位,比如Position-Position得到Distance等等,这样不管是外部使用还是内部写逻辑,都不太可能写错。
最后回到rtos的问题。rust有个框架叫RTIC,用async/await的形式直接就提供了异步支持,直接拿来用就行了:
#[task(
priority = 2,
shared = [led],
local = [tog: bool = true],
)]
async fn heartbeat(mut c: heartbeat::Context) {
loop {
info!("heartbeat, tog = {}", *c.local.tog);
if *c.local.tog {
c.shared.led.lock(|l| l.set_high().unwrap());
} else {
c.shared.led.lock(|l| l.set_low().unwrap());
}
*c.local.tog = !*c.local.tog;
rtic_monotonics::systick::Systick::delay(500.millis()).await;
}
}
#[task(
priority = 1,
shared = [timer, cap_displacement_sensor],
)]
async fn displacement_update(mut c: displacement_update::Context) {
loop {
let now = c.shared.timer.lock(|timer| timer.get_counter());
info!("now = {}", now.ticks());
c.shared.cap_displacement_sensor.lock(|cds| {
info!("{:?}", cds.read_spi_and_feed(now));
});
// Period to read the displacement.
rtic_monotonics::systick::Systick::delay(10.millis()).await;
}
}
总的来说,这个就叫降维打击,实在是太爽了。rust会逼着你去思考,逼着你只能写出正确的逻辑,逼着你只能写出正确的代码。
比如上面的代码有很多unwrap,看着很丑。这种丑就是rust在逼你把代码写成带错误处理的模式。
因为我目前故障处理这块还没做完,所以先unwrap跑起来再说。但等把所有的故障都规划好设计好,并把代码都改成带故障处理的模式之后,这些unwrap就不会再存在了。
最主要的是,我前几年尝试切rust,每次都被它陡峭的学习曲线打击了,导致半途而废。但现在有chatgpt,有啥不懂得直接请教ai就行了。学rust难度降低了一个数量级,现在转真心不是什么问题了。
【 在 dismoon 的大作中提到: 】
: 我都底层C重写了一遍类RTOS,写固件是个问题?
:
--
修改:lvsoft FROM 121.225.189.*
FROM 121.225.189.*