This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM2434:I2C 时钟卡在低电平

Guru**** 2393725 points
Other Parts Discussed in Thread: AM2434, MSP430FR2355

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1450404/am2434-i2c-clock-stuck-low

器件型号:AM2434
主题中讨论的其他器件: MSP430FR2355

工具与软件:

您好!  

AM2434上的 I2C 时钟信号卡在低电平无法恢复时会遇到问题。 在此 I2C 总线上、AM2434是主器件、而有一个 MSP430FR2355和一个 EEPROM 作为从器件。 当 AM2434在 EFT 噪声干扰期间以引导模式向 MSP430FR2355写入引导数据时、I2C 时钟信号会卡在低电平。

下图显示了 EFT 噪声发生器中断传输后,程序调用 I2C_FreeBus()函数(修改自 SDK 的 I2C_recoverBus ()函数)来尝试恢复 I2C 总线(在标记为"Gen 9 Clocks to Recover bus"的点),然后尝试重新发送数据包。 但是、如图所示、当重新发送达到长度字段的第7位时、SDA 和 SCL 都卡在低电平状态。  

随后,由于连续传输失败,程序再次调用 I2C_FreeBus()函数,但这次 SCL 不会产生预期的9个时钟并保持低电平(如下图所示)。  该情况已重试10次、结果与图中所示相同。 SDA 线转换到两次高电平状态,我们怀疑这是调用 I2C_CtrlInit ()函数的结果。

下面是我们的 I2C_FreeBus()函数、该函数根据 SDK 的 I2C_recoverBus 函数进行了修改。

void I2C_FreeBus( I2C_Handle handle )
{
	I2C_Object *pObject;
	Uint32 SysTest, i;

	pObject = ( I2C_Object* )handle->object;

	/* Acquire the lock for this particular I2C handle */
	( void )SemaphoreP_pend( &pObject->mutex, SystemP_WAIT_FOREVER );

	/* Check if SDA or SCL is stuck low based on the SYSTEST.
	 * If SCL is stuck low we reset the IP.
	 * If SDA is stuck low drive 9 clock pulses on SCL and check if the
	 * target has released the SDA. If not we reset the I2C controller.
	 */
	SysTest = I2CControllerGetSysTest( pObject->baseAddr );

	I2C_CtrlInit( handle );

	/* SDA output high */
	/* generate 9 clk pulses on SCL */
	/* switch to system test mode */
	HW_SET_FIELD32( SysTest, I2C_SYSTEST_ST_EN, I2C_SYSTEST_ST_EN_ENABLE );
	HW_SET_FIELD32( SysTest, I2C_SYSTEST_TMODE, I2C_SYSTEST_TMODE_LOOPBACK );
	// HW_SET_FIELD32( SysTest, I2C_SYSTEST_SDA_O, I2C_SYSTEST_SDA_O_SDAOH );
	I2CControllerSetSysTest( pObject->baseAddr, SysTest );

	for( i = 0; i < 9; i++ ) {
		HW_SET_FIELD32( SysTest, I2C_SYSTEST_SCL_O, I2C_SYSTEST_SCL_O_SCLOH );
		I2CControllerSetSysTest( pObject->baseAddr, SysTest );
		Delay_us( 5 );

		HW_SET_FIELD32( SysTest, I2C_SYSTEST_SCL_O, I2C_SYSTEST_SCL_O_SCLOL );
		I2CControllerSetSysTest( pObject->baseAddr, SysTest );
		Delay_us( 5 );
	}

	/* Switch back to functional mode */
	HW_SET_FIELD32( SysTest, I2C_SYSTEST_ST_EN, I2C_SYSTEST_ST_EN_DISABLE );
	HW_SET_FIELD32( SysTest, I2C_SYSTEST_TMODE, I2C_SYSTEST_TMODE_FUNCTIONAL );
	I2CControllerSetSysTest( pObject->baseAddr, SysTest );

	/* Now check if the SDA is releases. If its still stuck low,
	* There is nothing that can be done. We still try to reset our IP.
	*/
	SysTest = I2CControllerGetSysTest( pObject->baseAddr );
	if ((SysTest & I2C_SYSTEST_SDA_I_FUNC_MASK) == 0U)
	{
	    I2C_CtrlInit( handle );
	}

	/* Release the lock for this particular I2C handle */
	( void )SemaphoreP_post( &pObject->mutex );
}

并且我们还 通过 SDK 修改 I2C_CtrlInit ()、如下所示。

void I2C_CtrlInit( I2C_Handle handle )
{
	I2C_HwAttrs const *pHwAttrs;
	I2C_Object *pObject;
	Uint32 Delay = 50U;
	Uint32 OutputClk;
	Uint32 InternalClk;
	Uint32 RegVal;

	/* Get the pointer to hwAttrs */
	pObject = ( I2C_Object* )handle->object;
	pHwAttrs = ( I2C_HwAttrs const* )handle->hwAttrs;

	/* Put i2c in reset/disabled state */
	I2CControllerDisable( pObject->baseAddr );

	/* Do a software reset */
	I2CSoftReset( pObject->baseAddr );

	/* Enable i2c module */
	I2CControllerEnable( pObject->baseAddr );

	/* Wait for the reset to get complete -- timeout = 50ms */
	while( ( ( HW_RD_REG32( pObject->baseAddr + I2C_SYSS ) & I2C_SYSS_RDONE_MASK ) == 0 ) && ( Delay != 0 ) ) {
		Delay--;
		Delay_us( 1000 );
	}

	/* Put i2c in reset/disabled state */
	I2CControllerDisable( pObject->baseAddr );

	/* Configure i2c bus speed*/
	switch( pObject->i2cParams.bitRate ) {
	case I2C_100KHZ: {
		OutputClk = 100000U;
		InternalClk = I2C_MODULE_INTERNAL_CLK_4MHZ;
		break;
	}

	case I2C_400KHZ: {
		OutputClk = 400000U;
		InternalClk = I2C_MODULE_INTERNAL_CLK_12MHZ;
		break;
	}

	case I2C_1P0MHZ: {
		OutputClk = 3400000U;
		InternalClk = I2C_MODULE_INTERNAL_CLK_12MHZ;
		break;
	}

	default: {
		/* Default case force it to 100 KHZ bit rate */
		OutputClk = 100000U;
		InternalClk = I2C_MODULE_INTERNAL_CLK_4MHZ;
	}
		break;
	}

	/* Set the I2C configuration */
	I2CControllerInitExpClk( pObject->baseAddr, pHwAttrs->funcClk, InternalClk, OutputClk );

	/* Configure I2C_SYSC params
	 * Disable auto idle mode
	 * Both OCP and systen clock cut off
	 * Wake up mechanism disabled
	 * No idle mode selected
	 */
	RegVal = I2C_AUTOIDLE_DISABLE | I2C_CUT_OFF_BOTH_CLK | I2C_ENAWAKEUP_DISABLE | I2C_NO_IDLE_MODE;
	I2CSyscInit( pObject->baseAddr, RegVal );

	/* Configure I2C_CON params */
	RegVal = I2C_OPMODE_FAST_STAND_MODE | I2C_NORMAL_MODE;
	I2CConfig( pObject->baseAddr, RegVal );

	/* Take the I2C module out of reset: */
	I2CControllerEnable( pObject->baseAddr );

	/* Enable free run mode */
	I2CControllerEnableFreeRun( pObject->baseAddr );

	/*Clear status register */
	I2CControllerIntClearEx( pObject->baseAddr, I2C_INT_ALL );
}

我们想问、是否有任何方法可以使 I2C SCL 信号从低电平状态恢复到高电平状态并成功生成时钟信号来解决总线挂起问题。

感谢您的帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    感谢您的提问。

    请留出一些时间来检查上述详细信息并恢复。

    此致、

    Tushar

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好  

    今天、我们会遇到 SCL 引脚卡在低电平状态、而没有由于 EFT 噪声恢复到高电平的情况、如下图所示:

    在这种情况下、我们使用硬件复位来重新启动已配置为 I2C 从设备的 MSP430FR2355。 在复位 MSP430FR2355后、我们观察到 SCL 引脚返回到高电平状态、如下图所示:

    根据此实验、我们怀疑 MSP430FR2355可能处于错误状态、导致在引导模式下拉低 SCL。 是否可以通过任何方式使 MSP430FR2355引导模式程序退出此错误状态?

    此致、

    Yenting

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    您能否告知我们您当前使用的 MCU PLUS SDK 版本?

    此致、

    Vaibhav

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    另请参阅:

    https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1452325/msp430fr2355-handling-i2c-clock-stuck-low-in-msp430fr2355-bsl/5581480

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Yen:

    感谢您的耐心。

    Unknown 说:
    根据此实验、我们怀疑 MSP430FR2355可能处于错误状态、因而导致在引导模式下将 SCL 拉至低电平。 是否可以通过任何方法使 MSP430FR2355引导模式程序退出此错误状态?[/QUOT]

    这似乎是 MSP430器件的问题、而不是 AM243x 上运行的 I2C 驱动程序的问题。

    在您提到的另一个线程中、建议通过主机发送 MSP430的 RESET 命令以使 I2C 线路再次工作。

    此致、

    Tushar