Part Number: TM4C1294NCZAD
Hello TI,
I have to make some small updates to a legacy product. Unfortunately, I have no access to the JTAG port on this, and can only update firmware using a Bootloader. No debugging.
This device talks to a whole mess of different I2C based sensors, and mostly works well. The only issue is that if a slave I2C device doesn't respond (missing, broken, etc), the TM4C locks somewhere in the I2CSend routine.
Can someone familiar with the peripheral libraries suggest what I can add to this code to handle a missing/non-responsive I2C Slave device?
Thanks very much!
P.S. I actually posted a similar question about this exact issue years ago and never really came up with a complete fix. Back then, We had development version of this device (with JTAG access), but they've all been discarded over the years, so this is all the more difficult.
uint32_t I2C3Send(uint8_t slave_addr, uint8_t num_of_args, ...)
{
uint8_t i;
// Tell the master module what address it will place on the bus when
// communicating with the slave.
I2CMasterSlaveAddrSet(I2C3_BASE, slave_addr, false);
//stores list of variable number of arguments
va_list vargs;
//specifies the va_list to "open" and the last fixed argument
//so vargs knows where to start looking
va_start(vargs, num_of_args);
//put data to be sent into FIFO
I2CMasterDataPut(I2C3_BASE, va_arg(vargs, uint32_t));
//if there is only one argument, we only need to use the
//single send I2C function
if(num_of_args == 1)
{
//Initiate send of data from the MCU
I2CMasterControl(I2C3_BASE, I2C_MASTER_CMD_SINGLE_SEND);
// Wait until MCU is done transferring.
while(!I2CMasterBusy(I2C3_BASE));
while(I2CMasterBusy(I2C3_BASE));
if(I2CMasterErr(I2C3_BASE)) return 0;
//"close" variable argument list
va_end(vargs);
}
//otherwise, we start transmission of multiple bytes on the
//I2C bus
else
{
//Initiate send of data from the MCU
I2CMasterControl(I2C3_BASE, I2C_MASTER_CMD_BURST_SEND_START);
// Wait until MCU is done transferring.
while(!I2CMasterBusy(I2C3_BASE));
while(I2CMasterBusy(I2C3_BASE));
if(I2CMasterErr(I2C3_BASE)) return 0;
//send num_of_args-2 pieces of data, using the
//BURST_SEND_CONT command of the I2C module
for(i = 1; i < (num_of_args - 1); i++)
{
//put next piece of data into I2C FIFO
I2CMasterDataPut(I2C3_BASE, va_arg(vargs, uint32_t));
//send next data that was just placed into FIFO
I2CMasterControl(I2C3_BASE, I2C_MASTER_CMD_BURST_SEND_CONT);
// Wait until MCU is done transferring.
while(!I2CMasterBusy(I2C3_BASE));
while(I2CMasterBusy(I2C3_BASE));
if(I2CMasterErr(I2C3_BASE)) return 0;
}
//put last piece of data into I2C FIFO
I2CMasterDataPut(I2C3_BASE, va_arg(vargs, uint32_t));
//send next data that was just placed into FIFO
I2CMasterControl(I2C3_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
// Wait until MCU is done transferring.
while(!I2CMasterBusy(I2C3_BASE));
while(I2CMasterBusy(I2C3_BASE));
if(I2CMasterErr(I2C3_BASE)) return 0;
//"close" variable args list
va_end(vargs);
}
return 1;
}
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3); SysCtlPeripheralReset(SYSCTL_PERIPH_I2C3); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR); GPIOPinConfigure(GPIO_PK4_I2C3SCL); GPIOPinConfigure(GPIO_PR5_I2C3SDA); GPIOPinTypeI2CSCL(GPIO_PORTK_BASE, GPIO_PIN_4); GPIOPinTypeI2C(GPIO_PORTR_BASE, GPIO_PIN_5); I2CMasterInitExpClk(I2C3_BASE, SysCtlClockGet(), true); //False = 100kbs, True = 400kbs HWREG(I2C3_BASE + I2C_O_FIFOCTL) = 80008000;

