#uds #diagnostics #adapter #frame #bus #async #can

automotive

Rust 包提供各种与汽车相关的库,例如与CAN接口通信和诊断API

6个版本

0.2.1 2024年5月12日
0.2.0 2024年5月12日
0.1.4 2024年2月24日

#143 in 硬件支持

MIT 许可证

105KB
2K SLoC

汽车包

crates.io docs.rs

欢迎使用 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