#i2c-bus #i2c #embedded-hal-i2c #embedded-hal #io

no-std i2c_hung_fix

尝试使用 embedded-hal 的特性,在非正常重置后解除 I2C 总线的挂起状态。

1 个不稳定版本

0.1.0 2020年1月27日

#1170 in 嵌入式开发

MIT/Apache

14KB
68

i2c_hung_fix

尝试使用 embedded-hal 的特性,在非正常重置后解除 I2C 总线的挂起状态。

Crate Documentation

I2C 标准的一个缺点是,如果主设备在从设备读取数据的过程中断电或崩溃,从设备会保持数据线处于低电平,因为它正在等待完成向主设备发送数据。

如果数据线保持低电平,初始化主设备上的 I2C 将会失败,因为从设备不会响应启动程序。这通常被称为挂起总线。

我实现了这个功能,因为在我的设备开发与调试过程中,设备重编程时 I2C 总线经常挂起,但这是一个在生产硬件中人们需要缓解的已知问题。

模拟器件(Analog Devices)有一篇应用笔记描述了这个问题和两种解决方案:[实现 I2C 重置](https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf)

如果硬件设计可以添加硬件,允许主设备给从设备断电是最佳方案;但在许多情况下,软件解决方案也有效。

这个 crate 实现了挂起总线的软件解决方案。它简单地给 SCL 时钟线计时,直到从设备释放 SDA 数据线。

在每次启动时运行挂起修复是合理的;如果总线没有挂起,它将在单个 I2C 时钟周期后退出。

示例

本示例使用 stm32f1xx-hal

let mut rcc = device.RCC.constrain();
let mut flash = device.FLASH.constrain();
let mut gpiob = device.GPIOB.split(&mut rcc.apb2);
let mut scl = gpiob.pb10.into_push_pull_ouput();
let sda = gpiob.pb11;

let clocks = rcc.cfgr.freeze(&mut flash.acr);
let mut delay = Delay::new(core.SYST, clocks);

try_unhang_i2c(&mut scl, &sda, &mut delay, 4_000_000, RECOMMENDED_MAX_CLOCK_CYCLES)
    .expect("I2C bus is still hung after try_unhang_i2c");

许可证

免费开源软件,根据 MIT 许可证和 Apache 许可证 2.0 的条款分发。

依赖项

~71KB