Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

MSP430FR2355: Handling I2C Clock Stuck Low in MSP430FR2355 BSL

Part Number: MSP430FR2355
Other Parts Discussed in Thread: AM2434,

Tool/software:

Hi, 

We are encountering an issue where the I2C clock signal stuck low and cannot recover. On this I2C bus, the AM2434 is the master, and there is one MSP430FR2355 as slaves. The I2C clock signal gets stuck low when the AM2434 is writing program data to the MSP430FR2355 in boot mode during EFT noise interference.

The diagram below shows that after the EFT noise generator interrupts the transmission, AM2434 calls the I2C_FreeBus() function (modified from the SDK's I2C_recoverBus() function) to try to recover the I2C bus (at the point labeled "Gen 9 clocks to recover bus"), and then attempts to resend the packet. However, as shown in the diagram, when resending reaches the 7th bit of the first byte of Length field, both SDA and SCL get stuck in a low state. 

Subsequently, due to continuous transmission failures, the program calls the I2C_FreeBus() function again, but this time SCL does not generate the expected 9 clocks and remains low (as shown in the diagram below). This situation was retried 10 times, and the results were the same as shown in the diagram. The SDA line transitions to a high state twice, which we suspect is the result of calling the I2C_CtrlInit() function.

Below is our I2C_FreeBus() function in AM2434, which is modified from the SDK's I2C_recoverBus function.

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 );
}

And we also modify I2C_CtrlInit() of AM2434 from SDK as below.

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 );
}

In further testing, when the I2C clock (SCL) is stuck low, We attempted to reset the MSP430FR2355 using a hardware method. This approach manually triggers a hardware reset to recover the device and restore normal I2C communication.

After resetting the MSP430FR2355, we observed that the SCL pin returned to the high state, as shown in the image below:

Next, we tested the scenario where the MSP430FR2355 enters APP mode, and EFT noise is introduced to force the I2C clock (SCL) line to remain stuck low. However, in our MSP430FR2355 application, we configured UCB0CTLW1 = 0x03 to enable the Clock Low Timeout feature. When the UCCLTOIFG flag is detected, we reset the I2C module.
As a result, the I2C clock line successfully recovers to a high state after approximately 44 ms, as shown in the following figure.

I would like to ask if there is a way to configure the MSP430FR2355 BSL to automatically reset the I2C module when the clock (SCL) is detected to be stuck low for a certain period of time. This is to prevent programming failures caused by noise interference during the programming process.

Any guidance would be greatly appreciated!

Regards,

YenTing

  • Hi Yen Ting,

    First want to confirm with you, you are using the ROM based BSL, right?

    If so, have you connect the reset pin on the device from the host? If yes, I think you can just use the reset pin to reset the device. 

  • Hi Gary

    Yes, we are using the ROM-based BSL.
    Unfortunately, the reset pin of the MSP430 is not connected to the host. Is there any solution other than using a hardware reset to recover the device?

    Additionally, does the MSP430FR2355 BSL have the USCI30 issue?
    We observed waveforms that match the behavior described in USCI30, where the issue occurs on the 7th bit of the first byte of the Length field.

    Regards,

    YenTing

  • Have you try to enable the a watch dog that make the timeout like 10s that is enough for normal firmware update? If you use the software trigger it seems will not reset the registers that mean the watch dog maybe can work.

    FR2355 seems not have USCI30 issue, all the issues in the errata https://www.ti.com/lit/er/slaz695j/slaz695j.pdf 

  • Hi Gary,

    Is it possible to enable and use the watchdog timer (WDT) in BSL mode on the MSP430FR2355 before programming any firmware?
    If so, could you provide guidance on how to configure the WDT in this situation to recover the device when the I²C bus gets stuck or communication fails?

    If the issue is not related to the USCI30 erratum, what other mechanisms or conditions in the MSP430FR2355 BSL mode could cause the SCL line to remain stuck low and unable to release?

    We are trying to identify potential root causes and would appreciate any insights or suggestions for further investigation.

    Thank you for your help!

    Best regards,
    YenTing

  • Is it possible to enable and use the watchdog timer (WDT) in BSL mode on the MSP430FR2355 before programming any firmware?

    No, you need to enable it in your application code

    If the issue is not related to the USCI30 erratum, what other mechanisms or conditions in the MSP430FR2355 BSL mode could cause the SCL line to remain stuck low and unable to release?

    Add more delay between packages that make sure the MSP430 to deal with pre-package. 

  • Hi Gary

    Add more delay between packages that make sure the MSP430 to deal with pre-package. 

    Thank you for the suggestion! Could you please elaborate on the reasoning behind adding more delay between packages?

    How much delay would be considered appropriate?

    Also, is there any relevant information or guidance about this in the MSP430 documentation?

    Best regards,
    YenTing

  • 30ms should be enough.

    By the way have you try to measure the SCl and SDA signal by oscilloscope to see the signal quality is good? What's the frequency of the SCL do you used now? Have you try to slow down it?

    By the way, do you mean the issue will happen even with a blank device?

  • Hi Gary

    30ms should be enough.

    We have tried increasing the interval between each packet to 30ms, but the SCL line is still being pulled low by the MSP430 ROM BSL.

    By the way have you try to measure the SCl and SDA signal by oscilloscope to see the signal quality is good?

    Currently, we have some products where the internal circuitry generates significant noise, and we can observe noise on the I2C lines, as shown in the image below. These devices fail during the first attempt to program the MSP430 at the factory.

    What's the frequency of the SCL do you used now? Have you try to slow down it?

    The current I2C frequency is set to 100kHz, which is already the lowest speed available.

    By the way, do you mean the issue will happen even with a blank device?

    Yes, this issue occurs during the first programming attempt on blank devices.
    (Devices with successfully programmed applications also encounter communication failures, but the issue can be mitigated in the application mode using the clock timeout mechanism.)

    Best regards,

    YenTing

  • Could you share me the whole wave form of the I2C? If you have a saleae that will be better, if not and it can be opened from myside that also works to me.

  • Hi Gary

    This is the complete waveform captured using a logic analyzer with 30ms delay between packages.
    20241219_30msBetweenPackage.zip

    There are four markers (A0 to A3) indicating the periods where SCL is stuck low.

    The software I used is ZP-Logic V1.02.08 (model: LAP-C Pro(16064M)). You can download it from the following link:
    https://www.zeroplus.com.tw/logic-analyzer_en/download_re.php?id=7849&name=https%3A%2F%2Fbd.zeroplus.com.tw%2Fwww%2FZP-Logic_10208_all.zip

    Best regards,

    YenTing

  • I seems the software can't be used without the hardware. 

    So this issue just happen when you add the EFT noise right? If no EFT noise, dose this issue will happen?

  • Hi Gary

    I seems the software can't be used without the hardware. 

    Choose Demo

    Choose LAP-C Pro(16CH 64M) and press Demo, then you can use the software to open the waveform file.

    So this issue just happen when you add the EFT noise right? If no EFT noise, dose this issue will happen?

    Yes, if there is no noise, the SCL line will not get stuck low.
    We use EFT to introduce noise because we want to simulate the operating conditions of a batch of products with poor power supply design that generate noise. This batch of products also experiences SCL being stuck low during programming due to the power supply noise.

    We are currently hoping to use a software-based solution to enable successful programming of the MSP430 in that batch of products.

    Best regards,

    YenTing

  • For the production I think you should use the JTAG to download the firmware at first time, right? If so, the timeout configuration will be implemented on the device. In the application failed case, the time out should can be used.

  • Hi Gary

    Although JTAG can be used for programming during production, there is still a need for software upgrades at the customer side after shipment. These upgrades require writing updated software to the MSP430's BSL via the AM24. Therefore, a software-based solution is still necessary.

    Best regards,

    YenTing

  • I know that, what I mean is after the device been programed with application firmware the you can the timeout feature will be enabled it can work when it failed when you try to do firmware update.

  • The I2C bus is highly susceptible to noise, due (primarily) to the passive high. Noise can result in protocol errors, bus hangs, and (undetected) incorrect data. This can be mitigated using shielding, stronger pullups, slower bus, checksums, and multiple reads (voting).

    If SDA is held low, the 9-clock trick usually works. If SCL is held low, you need to (hardware) reset the slave via RST/NMI/SBWTDIO and start over. [Ref UM10204 (r6) Sec 3.1.16]. The RST/NMI/SBWTDIO pin is part of the BSL protocol [Ref FRAM BSL UG (SLAU550AB) Sec 3.3.2], so there has to be a connection from the host.

    From what Gary says, the ROM BSL doesn't use either the WDT nor the UCCLTO timeout, so the master has to manage it. You can write your own BSL, though I suspect that's more than you had in mind.

    Is it too late in the design to switch to the UART BSL? A UART drives both high and low, and so is (slightly) less susceptible to noise.

**Attention** This is a public forum