6个版本
0.2.1 | 2024年5月12日 |
---|---|
0.2.0 |
|
0.1.4 | 2024年2月24日 |
#143 in 硬件支持
105KB
2K SLoC
汽车包
欢迎使用 automotive
包的文档。该包的目的是帮助您处理所有与汽车相关的事务。最重要的是,它提供了一种完全异步的CAN接口,支持多种适配器。
异步CAN示例
以下适配器打开系统上第一个可用的适配器,然后接收所有帧。请注意,发送的帧被等待,这意味着它将等待消息在CAN总线上被确认。
use automotive::StreamExt;
async fn can_example() -> automotive::Result<()> {
let adapter = automotive::can::get_adapter()?;
let mut stream = adapter.recv();
let frame = automotive::can::Frame::new(0, 0x541.into(), &[0xff; 8])?;
adapter.send(&frame).await;
while let Some(frame) = stream.next().await {
let id: u32 = frame.id.into();
println!("[{}]\t0x{:x}\t{}", frame.bus, id, hex::encode(frame.data));
}
Ok(())
}
UDS示例
该汽车包还提供用于各种诊断协议(如UDS)的接口。首先将适配器包装起来以支持ISO传输层,然后创建UDS客户端。所有方法都是完全异步的,这使得与多个ECU并行通信变得容易。有关支持的SIDs的进展情况,请参阅automotive#21。
async fn uds_example() -> automotive::Result<()> {
let adapter = automotive::can::get_adapter()?;
let isotp = automotive::isotp::IsoTPAdapter::from_id(&adapter, 0x7a1);
let uds = automotive::uds::UDSClient::new(&isotp);
uds.tester_present().await.unwrap();
let response = uds.read_data_by_identifier(automotive::uds::DataIdentifier::ApplicationSoftwareIdentification as u16).await?;
println!("Application Software Identification: {}", hex::encode(response));
Ok(())
}
CAN适配器
以下CAN适配器被支持。
支持的CAN适配器
- SocketCAN(仅限Linux)
- comma.ai panda(所有使用rusb的平台)
已知限制/注意
该库有一些独特功能,可能会在您通常不会注意到的驱动程序中暴露(性能)问题,因此请查看以下已知限制列表。
该库支持等待发送的帧并在CAN总线上等待确认。这需要从适配器接收这些确认,并将它们与适当的发送帧相匹配。这需要一定程度的硬件支持,并非所有适配器/驱动程序都提供。如果驱动程序不支持此功能,则在帧发送后立即模拟确认,但这可能在需要精确时间时引起问题。
- 没有
IFF_ECHO
的SocketCAN驱动程序:此类SocketCAN驱动程序没有硬件支持来通知驱动程序何时确认了帧。相反,这由Linux内核模拟。由于发送的帧立即被接收,如果一次发送476个以上(大多数系统上的默认RX队列大小为476),这可能导致接收队列填满。为了解决这个问题,我们自行实现了模拟确认,而不是依赖于内核的确认。 - comma.ai panda
- 熊猫不会重试未被确认的帧,而是将其丢弃。这可能导致帧被丢弃时库的一些内部部分出现恐慌。关于此问题,请参阅 panda#1922。
- 如果硬件配置为CAN-FD,则忽略帧上的CAN-FD标志,所有帧都将解释为FD,而不管FD帧位(r0位)。
- PCAN-USB:Peak CAN适配器有两个驱动程序
- 内核内置驱动程序(
peak_usb
)。内核驱动程序正确实现了IFF_ECHO
,但TX队列相对较小。这不应该引起任何问题,但可以通过以下命令增加:ifconfig can0 txqueuelen <size>
。 - 树外驱动程序(
pcan
),可以从Peak System的网站上下载。不建议使用树外驱动程序,因为它没有实现IFF_ECHO
。
- 内核内置驱动程序(
- neoVI/ValueCAN:由于SocketCAN驱动程序中的问题,不建议使用Intrepid Control System的设备。如果同时传输许多帧,将导致整个系统/内核挂起。intrepid-socketcan-kernel-module#20 跟踪此问题。
实现新的适配器
实现新的适配器是通过实现CanAdapter
特质来完成的。硬件实现可以是阻塞的,因为AsyncCanAdapter负责向用户提供异步接口。库对发送/接收帧有一些假设。这些假设也通过tests/adapter_tests.rs
中的测试得到验证。
send
函数接受一个&mut VecDequeue
帧队列。要发送的帧从队列的前面取出。如果没有空间在硬件或驱动程序缓冲区中发送所有消息,则在队列完全清空之前返回是正常的。如果发生错误,确保将消息放回队列的起始位置并返回。- 硬件或驱动程序可以自由地优先发送具有较低仲裁ID的帧,以防止优先级反转。但是,具有相同仲裁ID的帧需要在CAN总线上以与它们排队时相同的顺序发送。这个假设是为了将接收到的ACK与正确的帧匹配。
- 一旦帧被确认,就应该将其放入接收队列,并设置
loopback
标志。AsyncCanAdapter
包装器将负责将其与正确的发送帧匹配,并解决Future。如果底层硬件不支持此功能,可以通过立即回环所有发送的帧来模拟。
路线图
我将来想添加的功能。也请查看问题页面。
- CCP/XCP客户端
- 更新文件提取(例如 .frf 和 .odx)
- VIN解码
- Windows上的J2534支持
- 更多设备支持
- WebUSB支持
依赖关系
~5–14MB
~158K SLoC