3403|2

190

帖子

10

TA的资源

一粒金砂(中级)

楼主
 

【NXP Rapid IoT评测】触摸按键没有反应——I2C死锁解除方法 [复制链接]

NXP Rapid IoT  上用I2C1上挂了很多外设,
I2C1: Sensors + Touch: FXOS8700, FXAS21002, MPL3115, ENS210, TSL25711, CCS811 (behind I2C switch), SX9500
I2C2: after I2C switch (...NTAG_I2C_EN): NT3H2211, A1006, A71

而且在开发过程中不何避免的复位重启Rapid IoT,造成了I2C时序混乱,同时又由于电池供电,而且I2C上所有设置并不是都全可以进行掉电或者硬件复件。


体现的现象   触摸按键没有反应,传感器没有数据,信号现象 SCL为高,SDA一直为低


死锁产生的原因分析如下:
     在正常情况下,I2C总线协议能够保证总线正常的读写操作。但是,当I2C主设备异常复位时(看门狗动作,板上电源异常导致复位芯片动作,手动按钮复位等等)有可能导致I2C总线死锁产生。下面详细说明一下总线死锁产生的原因。
      在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。而对于I2C主设备来说.复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用会一直等待SCL和SDA信号变为高电平。这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种死锁状态。同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导致I2C总线进入死锁状态。

解锁方法如下:
(1) 尽量选用带复位输人的I2C从器件。
(2) 将所有的从I2C设备的电源连接在一起,通过MOS管连接到主电源,而MOS管的导通关断由I2C主设备来实现。
(3) 在I2C从设备设计看门狗的功能。


(4) 在I2C主设备中增加I2C总线恢复程序。每次I2C主设备复位后,如果检测到SDA数据线被拉低,则控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。

(5) 在I2C总线上增加一个额外的总线恢复设备。
(6) 在I2C上串人一个具有死锁恢复的I2C缓冲器,如Linear公司的LTC4307。

硬件也设置好,而且并非每一个设备都满足上面的条件,只能选择方法(4),具体体现的代码如下:
  1. static void i2c_release_bus_delay(void)
  2. {
  3. #if 0
  4. #define I2C1_RELEASE_BUS_COUNT 200U
  5.     uint32_t i = 0;
  6.     for (i = 0; i < I2C1_RELEASE_BUS_COUNT; i++)
  7.     {
  8.         __NOP();
  9.     }
  10. #else
  11.     App_WaitUsec(100);
  12. #endif
  13. }

  14. void BOARD_I2C1_ConfigurePins(void)
  15. {
  16.     /* Port C Clock Gate Control: Clock enabled */
  17.     CLOCK_EnableClock(kCLOCK_PortC);

  18.     const port_pin_config_t portc10_pinC7_config = {/* Internal pull-up resistor is enabled */
  19.                                                     kPORT_PullUp,
  20.                                                     /* Fast slew rate is configured */
  21.                                                     kPORT_FastSlewRate,
  22.                                                     /* Passive filter is disabled */
  23.                                                     kPORT_PassiveFilterDisable,
  24.                                                     /* Open drain is enabled */
  25.                                                     kPORT_OpenDrainEnable,
  26.                                                     /* Low drive strength is configured */
  27.                                                     kPORT_LowDriveStrength,
  28.                                                     /* Pin is configured as I2C1_SCL */
  29.                                                     kPORT_MuxAlt2,
  30.                                                     /* Pin Control Register fields [15:0] are not locked */
  31.                                                     kPORT_UnlockRegister};
  32.     /* PORTC10 (pin C7) is configured as I2C1_SCL */
  33.     PORT_SetPinConfig(PORTC, 10U, &portc10_pinC7_config);

  34.     const port_pin_config_t portc11_pinB7_config = {/* Internal pull-up resistor is enabled */
  35.                                                     kPORT_PullUp,
  36.                                                     /* Fast slew rate is configured */
  37.                                                     kPORT_FastSlewRate,
  38.                                                     /* Passive filter is disabled */
  39.                                                     kPORT_PassiveFilterDisable,
  40.                                                     /* Open drain is enabled */
  41.                                                     kPORT_OpenDrainEnable,
  42.                                                     /* Low drive strength is configured */
  43.                                                     kPORT_LowDriveStrength,
  44.                                                     /* Pin is configured as I2C1_SDA */
  45.                                                     kPORT_MuxAlt2,
  46.                                                     /* Pin Control Register fields [15:0] are not locked */
  47.                                                     kPORT_UnlockRegister};
  48.     /* PORTC11 (pin B7) is configured as I2C1_SDA */
  49.     PORT_SetPinConfig(PORTC, 11U, &portc11_pinB7_config);
  50. }

  51. void I2C1_ReleaseBus(void)
  52. {
  53.     uint8_t i = 0;
  54.     gpio_pin_config_t pin_config;
  55.     port_pin_config_t i2c_pin_config = {0};

  56.     /* Config pin mux as gpio */
  57.     i2c_pin_config.pullSelect = kPORT_PullUp;
  58.     i2c_pin_config.mux = kPORT_MuxAsGpio;

  59.     pin_config.pinDirection = kGPIO_DigitalOutput;
  60.     pin_config.outputLogic = 1U;
  61.     CLOCK_EnableClock(kCLOCK_PortC);
  62.     PORT_SetPinConfig(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, &i2c_pin_config);
  63.     PORT_SetPinConfig(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, &i2c_pin_config);

  64.     GPIO_PinInit(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, &pin_config);
  65.     GPIO_PinInit(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, &pin_config);

  66.     /* Drive SDA low first to simulate a start */
  67.     GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 0U);
  68.     i2c_release_bus_delay();

  69.     /* Send 9 pulses on SCL and keep SDA high */
  70.     for (i = 0; i < 9; i++)
  71.     {
  72.         GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 0U);
  73.         i2c_release_bus_delay();

  74.         GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 1U);
  75.         i2c_release_bus_delay();

  76.         GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 1U);
  77.         i2c_release_bus_delay();
  78.         i2c_release_bus_delay();
  79.     }

  80.     /* Send stop */
  81.     GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 0U);
  82.     i2c_release_bus_delay();

  83.     GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 0U);
  84.     i2c_release_bus_delay();

  85.     GPIO_PinWrite(BOARD_INITPINS_I2C1_SCL_PORT, BOARD_INITPINS_I2C1_SCL_PIN, 1U);
  86.     i2c_release_bus_delay();

  87.     GPIO_PinWrite(BOARD_INITPINS_I2C1_SDA_PORT, BOARD_INITPINS_I2C1_SDA_PIN, 1U);
  88.     i2c_release_bus_delay();

  89.     BOARD_I2C1_ConfigurePins();
  90. }
复制代码



初始上时钟后,就可以调用上述代码。

完整代码,
board.rar (6.03 KB, 下载次数: 7)
替换  工程文件\RapidIot_Base\board\board.c







此内容由EEWORLD论坛网友dvd1478原创,如需转载或用于商业用途需征得作者同意并注明出处

此帖出自RF/无线论坛

最新回复

嗯,I2C死锁这个问题确实是存在,解决不好,确实很麻烦,谢谢楼主分享!  详情 回复 发表于 2019-3-12 13:33
点赞 关注(1)
 

回复
举报

71

帖子

0

TA的资源

宇宙尘埃

沙发
 
嗯不错!谢谢分享
此帖出自RF/无线论坛
个人签名FTP
 
 

回复

1368

帖子

6

TA的资源

版主

板凳
 
嗯,I2C死锁这个问题确实是存在,解决不好,确实很麻烦,谢谢楼主分享!
此帖出自RF/无线论坛
个人签名专注智能产品的研究与开发,专注于电子电路的生产与制造……QQ:2912615383,电子爱好者群: void
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表