Hi,
My developing environments:
TM4C1294 custom board, FreeRTOS v7.1.1, LWIP 1.4.1, CCS 6.0.1
I am working on detecting fail bits from I2C expander, and there is only one Master which is MCU.
I thought it worked well since I could read the right values(4 bytes) from the expander. However, it suddenly stops working after running 2~3 hours.(both SDA and SCL go high).
The task,I2CTask in my project, is executed in a regular time basis and read values.
Here is my I2C init funciton:
void i2c_init(void) { // The I2C5 peripheral must be enabled before use. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C5); while(!(ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_I2C5))); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); while(!(ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB))); ROM_GPIOPinConfigure(GPIO_PB0_I2C5SCL); ROM_GPIOPinConfigure(GPIO_PB1_I2C5SDA); // Select the I2C function for these pins. This function will also // configure the GPIO pins for I2C operation, setting them to // open-drain operation with weak pull-ups. ROM_GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_0); ROM_GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_1 ); // Initialize Master and Slave // true: 400kbps I2C clock (false: 100kbps) ROM_I2CMasterInitExpClk(I2C5_BASE, g_ui32SysClock, false); }
Also here is read function:
unsigned long read32_PCA9506() { int err[2]; //used for debugging int i,loopdelay; // delay loop variable unsigned char byte[4]; // 4 byte array for retrieved bytes holding // unsigned char byte1,byte2,byte3,byte4 ; // holders for the 4 retrieved bytes unsigned long return_fails = 0; // 32bit return holder of assembled bytes // Program the SLAVE address into registers, and select a WRITE operation // for I2C bus ROM_I2CMasterSlaveAddrSet(I2C5_BASE, PCA9506_ADDR, I2C_SEND);//PCA9506_ADDR:0x20 // Note: The I^2C bus requires us to transmit the ' START ' condition // from the Micro to the PCA9506. The next byte transfered must be the // address of the slave device. A0,A1,A2 of PCA9506 are tied low (000). // The address is the 7 MSB of a byte, with the LSB being the R/W selection bit. // For our configuration, 0x20 is the address of the PCA9506 // The address is loaded into Slave address register, then the register // address byte is loaded into a write register with the type of 'START' // configuration we want to use.... START toggle is sent, then slave address // goes out automatically, then register to write too is transmitted. // Load Slave address, select type of START transmission, and write // register address to OUTPUT write register for I2C0 ROM_I2CMasterDataPut( I2C5_BASE, COMMAND_REG);//COMMAND_REG: 0x80 // Transmit START, slave address, -- NO STOP sent ROM_I2CMasterControl( I2C5_BASE, I2C_MASTER_CMD_BURST_SEND_START ); while (!(ROM_I2CMasterBusy( I2C5_BASE ))) {} //sometime does not catch flag,so put this code while (ROM_I2CMasterBusy( I2C5_BASE )) {} // wait for transmission to finish err[0] = ROM_I2CMasterErr(I2C5_BASE); // read the error status of last transmission and if ( err[0] != I2C_MASTER_ERR_NONE ) { UARTprintf("error[0] = %x\n",err[0] ); // error detected during START BURST MODE, SEND STOP COMMAND ROM_I2CMasterControl( I2C5_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP ); // ROM_I2CMasterIntClear(I2C5_BASE); I2C5_error_count = (I2C5_error_count + 1); // increment the detected error counter for I2C0 return_fails = 0; return (unsigned long) return_fails; // return from READ function, reporting no // FAIL bit status, but with error count increased } ROM_I2CMasterSlaveAddrSet( I2C5_BASE, PCA9506_ADDR, I2C_RECV ); //repeat start condition followed by receive operation with data negative acknowledge //master goes to Master receive state ROM_I2CMasterControl( I2C5_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START ); for ( i=0; i<4; i++) { while (!ROM_I2CMasterBusy( I2C5_BASE )); while (ROM_I2CMasterBusy( I2C5_BASE )){} // BYTE 1 - IO-O HAS NOW BEEN READ, SO RETRIEVE THE VALUE AND STORE IT IN return byte[i] = ROM_I2CMasterDataGet( I2C5_BASE ); UARTprintf("Data Get: byte[%d] == %x\n", i, byte[i]); ROM_I2CMasterControl(I2C5_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT); err[1] = ROM_I2CMasterErr(I2C5_BASE); if ( err[1] != I2C_MASTER_ERR_NONE ) { UARTprintf("error[1] = %x\n",err[2] ); // error detected during START BURST MODE, SEND STOP COMMAND ROM_I2CMasterControl( I2C5_BASE, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP ); // ROM_I2CMasterIntClear(I2C5_BASE); I2C5_error_count = (I2C5_error_count + 1); // increment the detected error counter for I2C5 return_fails = 0; return (unsigned long) return_fails; // return from READ function, reporting no // FAIL bit status, but with error count increased } for(loopdelay=0; loopdelay<1000; loopdelay++);//8.33 uSec }//end for return_fails = (byte[3] << 24) | (byte[2] << 16) | (byte[1] << 8) | byte[0]; // assemble 32bit FAIL register // all 4 registers have now been read, so transmit the STOP signal to IC2 slave // transmit a receive stop condition - Current State is receive - write 0x04 to I2CMCS register // with NO acknowledge to put I2C bus into IDLE state ROM_I2CMasterControl( I2C5_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH ); // transmit STOP only to free up bus I2C5_error_count = 0; // if we reach this point, we have successfully completed // a read process of 32 bits ( 4 bytes ) from the PCA9506 chip for(loopdelay=0; loopdelay<1000; loopdelay++); return (unsigned long) return_fails; }
I have not found what is wrong with this.
As you see this is the polling mode, so may be better to use interrupt mode? if then can you give a tip to use interrupt mode in my situation like sending and receiving 4 bytes?
Thanks,
Jin