I2C loss of arbitration on LPC5512

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

I2C loss of arbitration on LPC5512

2,029件の閲覧回数
randylee
Contributor V

I'm using SDK 2.11 on an LPC5512 using MCUexpresso 11.5.1.  I've got an I2C bus (400KHz) and am using an I2S amplifier.  The LPC is bus master and there are a couple of slaves on it. I2C driver version is 2.3.0

Every so often (random) I see an loss of arbitration error on the I2C using a write/read.  Code:

i2c_master_transfer_t masterXfer;
memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = Device;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = reg_addr;
masterXfer.subaddressSize = 1;
masterXfer.data = rxBuff;
masterXfer.dataSize = rxSize;
masterXfer.flags = kI2C_TransferDefaultFlag;

/* direction=write : start+device_write;cmdbuff;xBuff; */
/* direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */

RetVal = I2C_MasterTransferBlocking(ACCEL_I2C_PERIPHERAL, &masterXfer);

This will go like this:

randylee_0-1662067185397.png

This appears to be something connected to power somehow BUT I'd like to recover from it.  If I just restart the transfer I get something more interesting:

randylee_1-1662067245833.png

and the transfer hangs forever waiting for some status to happen that never does in fsl_i2c.c around line 425

Interestingly enough, I've got the I2C channel supposedly configured in the peripherals tool to timeout in like 35mS but it never does.

randylee_2-1662067485682.png

How do I get this thing reset and running again?

I don't find any reference to the timeout code being enabled.  Is the tool not putting out the right stuff there? Or does it just not do that?

 

ラベル(1)
4 返答(返信)

986件の閲覧回数
danielholala
Senior Contributor II

How did you finally resolve this issue?

I'm asking as I think I see a similar behavior when I force SCL low for even a very short amount of time during times when the I2C bus is idle (for example manually with a push button). That is enough to stop the I2C system in my LPC5526 from working as expected.

0 件の賞賛
返信

1,983件の閲覧回数
frank_m
Senior Contributor III

> How do I get this thing reset and running again?

Many I2C devices, especially older and less complex one's, seem to be simple state machines. If some impulse gets lost or an additional one interspersed by e.g. EMI, synchonisation is lost. Often, not even a stop event helps. While an amplifier seems not "simple", it might have inherited simpler I2C-IP from older devices ...

One commonly used method is to manually drive CLK pulse (perhaps reconfigure the I2C pins), until the slave releases the bus.

I would try a lower clock frequency as well. Not that I think it is the bus speed per se, assuming the slave has clock stretching implemented.

0 件の賞賛
返信

2,012件の閲覧回数
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi

Pls try to use non blocking mode, in other words, use the interrupt mechanism to transfer data.

i2c_master_transfer_t masterXfer;
memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = Device;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = reg_addr;
masterXfer.subaddressSize = 1;
masterXfer.data = rxBuff;
masterXfer.dataSize = rxSize;
masterXfer.flags = kI2C_TransferDefaultFlag;

/* direction=write : start+device_write;cmdbuff;xBuff; */
/* direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */

RetVal = I2C_MasterTransferNonBlocking(ACCEL_I2C_PERIPHERAL, &g_m_handle,&masterXfer);

You can refer to the example code like:

xiangjun_rong_0-1662357805663.png

 

Because I use the example based on LPC55S69-EVK, I do not know if there is similar example based on LPC5512-EVK.

static bool I2C_ReadAccelRegs(I2C_Type *base, uint8_t device_addr, uint8_t reg_addr, uint8_t *rxBuff, uint32_t rxSize)
{
i2c_master_transfer_t masterXfer;
memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = device_addr;
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = reg_addr;
masterXfer.subaddressSize = 1;
masterXfer.data = rxBuff;
masterXfer.dataSize = rxSize;
masterXfer.flags = kI2C_TransferDefaultFlag;

/* direction=write : start+device_write;cmdbuff;xBuff; */
/* direction=recive : start+device_write;cmdbuff;repeatStart+device_read;xBuff; */

I2C_MasterTransferNonBlocking(BOARD_ACCEL_I2C_BASEADDR, &g_m_handle, &masterXfer);

/* wait for transfer completed. */
while ((!nakFlag) && (!completionFlag))
{
}

nakFlag = false;

if (completionFlag == true)
{
completionFlag = false;
return true;
}
else
{
return false;
}
}

Hope it can help you

BR

XiangJun Rong

0 件の賞賛
返信

1,987件の閲覧回数
randylee
Contributor V

actually, I had that exact code in there to begin with and changed to blocking to see if that helped (it didn't).