本帖最后由 香水城 于 2017-8-17 10:11 编辑
时钟延展导致 I2C 通信不可靠
问题:
该问题由某客户提出,发生在 STM32F103R8T6 器件上。据其工程师讲述:其产品中设计中,STM32 与一颗 MPEG 解码芯片通过I2C接口通信。其中,STM32 为 SLAVE节点,而 MPEG 解码芯片为 MASTER 节点。在产品调试过程中,发现该通信不可靠。在系统运行一段时间后,该通信会出现故障而导致整个系统死机。使用示波器测量,发现这时I2C总线的 SCL 信号持续为低电平。
调研:
检查硬件设计,VDD、VDDA、VBAT、VSS、VSSA、NRST、BOOT0 等管脚相关的外部电路设计无异常。测量I2C通信数据帧结构,如图(一)所示,未见异常。重复长时间运行测试,故障重现,如其工程师所述。使用 IAR Embedded Workbech+Jlink 调试工具连接到STM32 中正在运行的程序,将程序暂停后通过寄存器窗口修改 SCL 信号对应的 GPIO 寄存器,将 I/O 的模式切换到 GPIO 浮空输入模式。使用示波器测量 SCL 信号,发现此时SCL 信号为高电平。再将 I/O 切换回 AF 开路输出模式,然后测量 SCL 信号,发现 SCL又跳变到低电平。由此可以判定 SCL 信号上的低电平是由 STM32 驱动造成的。通过调试工具的观查窗口查看I2C接口的状态寄存器,发现 SR1 中的 RxNE 置‘1’,说明有数据在DR寄存器中未被读出。再查看I2C接口的控制寄存器,发现CR1寄存器中的NO STRETCH位为‘0’,说明 I2C 接允许时钟延展。于是,可以判定,此时 I2C 接口由于接收缓冲区满而对外送出的时钟延展信号,从而拉低了 SCL 信号。进一步通过其工程师了解到,MPEG解码芯片的I2C接口是一个软件模拟的接口,不支持时钟延展功能。于是猜测,有可能是 MPEG 忽略的 STM32 送出的时钟延展信号,继续对外传送数据而造成冲突而导致数据丢失。如果其软件设计中存在某些缺陷,在通信数据丢失时进入死锁状态而不能退出,则会有类似的现象发生。进一步检查其软件设计,发现其对I2C接口接收到的数据的处理方式是边接收边处理,而且要待前一个数据处理完以后再去读取下一个数据,对某些数据的处理较为烦琐。修改其软件,在内存中建立一个 32 字节的循环缓冲区。通过中断的方式接收I2C接口收到的数据,保证数据传入后能够立该转移到循环缓冲区中。而数据的处部分的程序分改从循环缓冲区取数据。重新进行测试,长时间观测,未见先前现象发生,从而印证了前面的猜测。
结论:
由于 MASTER 节点不支持时钟延展,造成 I2C 信号冲突,从而有数据丢失。而其软件在某个数据丢失后,对后续的数据做出了错误的处理,最终进入了逻辑混乱状态。
处理:
加入循环缓冲区以避免数据丢失,加强其软件对数据的合法性的判断以避免造成错误处理,增加自恢复功能以增强系统的可靠性。
建议:
在 I2C 的规范中定义了时钟延展协议。通过这一协议,SLAVE 设备在没有条件接收或发送下一个数据时,可以拉低 SCL 信号,通知 MASTER 设备暂停数据的传输,直到 SLAVE设备释放 SCL 信号。对于 STM32 的I2C接口来说,如果 CR1 寄存器中的 NO STRETCH 位为‘0’则开启时钟延展协议,而该位为‘1’时关闭时钟延展协议。在开启了时钟延展协议的情况下,STM32 的I2C接口作为 SLAVE 设备接收数据时,如果 SR1 中的 RxNE 不为‘0’,也就是接收缓冲区不空,则会送出时钟延展信号,将 SCL 信号拉低。同样情况下,作为 SLAVE 设备发送数据时,如果发送缓冲区为空,即 SR1 中的 TxE 为‘1’时,也会送出时钟延展信号。在关闭了该协议的情况下,STM32 的I2C接口不会向外发送时钟延展信号。而此时,软件必须检测 SR1 寄存器中的 OVR 位,来判断是不发生了接收数据覆盖或重复发送问题。
对应的PDF:时钟延展导致 I2C 通信不可靠
更多实战经验请看:【ST MCU实战经验汇总贴】
|