HI,
I need to configure I2C slave mode in TM4c123GH6PZ controller.
Initially when i am transmitting data from slave board to master board it's working fine there is no any problem. Suppose if i reset only the master board power supply it giving problem. After resetting the power supply in master side, the data which is receiving in master side is interchanged. i mean (LSB and MSB data is interchanged).
I checked with debugger in slave board it showing correct data format only. when i connecting debugger in master board it showing the interchanged data.
could you help any one about this issue?
Below i given the code. I may didn't included some variable declaration. sorry for the inconvenience
#include "fsi_smb.h" #include "common_header.h" #include "GPIO.h" #define MAX_TX_BYTES 2 // Maximum Number of Bytes to be transmitted #define Max_I2C_Tx_Size 2 // Maximum Number of Bytes to be transmitted unsigned char Data_Tx_Buffer[6][MAX_TX_BYTES] = { '0' }; unsigned char Data_Rx_Buffer[MAX_TX_BYTES] = { '0' }; /// SMB related constants #define SMB_BUFFER 32 // max SMB message size #define SMB_TIMEOUT_LENGTH 30 // ms - transaction timeout (any SMB transaction cannot be longer then this) /// Size of SMB word #define SMB_WORD 2 // bytes #define SMB_BYTE 1 /// SMB channel flags #define SMB_FLAG_PEC ( 1 << 0 ) #define SLAVE_ADDRESS 0x0B //Slave Board config #define Bay1_CellA_I2C 1 #define Bay1_CellB_I2C 2 #define Bay2_CellA_I2C 3 #define Bay2_CellB_I2C 4 // I2C0 slave config #define I2C0_SYSCTL_PERIPH_GPIOx SYSCTL_PERIPH_GPIOB #define I2C0_SYSCTL_PERIPH_I2Cx SYSCTL_PERIPH_I2C0 #define I2C0_GPIO_PBx_I2CxSCL GPIO_PB2_I2C0SCL // GPIO_PB2_I2C0SCL - Pin_map.h #define I2C0_GPIO_PBx_I2CxSDA GPIO_PB3_I2C0SDA // GPIO_PB3_I2C0SDA - Pin_map.h #define I2C0_GPIO_PORTx_BASE GPIO_PORTB_BASE #define I2C0_SCL GPIO_PIN_2 #define I2C0_DTA GPIO_PIN_3 #define BASE_I2C0 I2C0_BASE #define INT0_I2C INT_I2C0 // I2C3 slave config #define I2C3_SYSCTL_PERIPH_GPIOx SYSCTL_PERIPH_GPIOG #define I2C3_SYSCTL_PERIPH_I2Cx SYSCTL_PERIPH_I2C3 #define I2C3_GPIO_PGx_I2CxSCL GPIO_PG0_I2C3SCL // GPIO_PG0_I2C3SCL - Pin_map.h #define I2C3_GPIO_PGx_I2CxSDA GPIO_PG1_I2C3SDA // GPIO_PG1_I2C3SDA - Pin_map.h #define I2C3_GPIO_PORTx_BASE GPIO_PORTG_BASE #define I2C3_SCL GPIO_PIN_0 #define I2C3_DTA GPIO_PIN_1 #define BASE_I2C3 I2C3_BASE #define INT3_I2C INT_I2C3 // I2C4 slave config #define I2C4_SYSCTL_PERIPH_GPIOx SYSCTL_PERIPH_GPIOG #define I2C4_SYSCTL_PERIPH_I2Cx SYSCTL_PERIPH_I2C4 #define I2C4_GPIO_PGx_I2CxSCL GPIO_PG2_I2C4SCL // GPIO_PG2_I2C4SCL - Pin_map.h #define I2C4_GPIO_PGx_I2CxSDA GPIO_PG3_I2C4SDA // GPIO_PG3_I2C4SDA - Pin_map.h #define I2C4_GPIO_PORTx_BASE GPIO_PORTG_BASE #define I2C4_SCL GPIO_PIN_2 #define I2C4_DTA GPIO_PIN_3 #define BASE_I2C4 I2C4_BASE #define INT4_I2C INT_I2C4 // I2C5 slave config #define I2C5_SYSCTL_PERIPH_GPIOx SYSCTL_PERIPH_GPIOG #define I2C5_SYSCTL_PERIPH_I2Cx SYSCTL_PERIPH_I2C5 #define I2C5_GPIO_PGx_I2CxSCL GPIO_PG6_I2C5SCL // GPIO_PG6_I2C5SCL - Pin_map.h #define I2C5_GPIO_PGx_I2CxSDA GPIO_PG7_I2C5SDA // GPIO_PG7_I2C5SDA - Pin_map.h #define I2C5_GPIO_PORTx_BASE GPIO_PORTG_BASE #define I2C5_SCL GPIO_PIN_6 #define I2C5_DTA GPIO_PIN_7 #define BASE_I2C5 I2C5_BASE #define INT5_I2C INT_I2C5 /// SMB channels smbState smb[5]; unsigned char Data_Count_var = 0; uint32 temp_data[5], LSB_data, MSB_data; extern uint8 Bay1_Full, Bay1_Calib, Bay2_Full, Bay2_Calib; /************************************************************************************************ * I2C hardware initialization * index - I2C channel index (I2C0 | OUTI2C) * ownAddress - self SMB address *************************************************************************************************/ void initI2C(uint8 index ,uint8 ownAddress) { if(index == Bay1_CellA_I2C) // I2C Zero channel // Bay1 CellA { // SLAVE I2C0 INIT SysCtlPeripheralEnable(I2C0_SYSCTL_PERIPH_I2Cx); //Enables a peripheral . SysCtlPeripheralEnable(I2C0_SYSCTL_PERIPH_GPIOx); //Enables a peripheral. GPIOPinConfigure(I2C0_GPIO_PBx_I2CxSCL); GPIOPinConfigure(I2C0_GPIO_PBx_I2CxSDA); GPIOPinTypeI2CSCL(I2C0_GPIO_PORTx_BASE, I2C0_SCL); // SCL GPIOPinTypeI2C(I2C0_GPIO_PORTx_BASE, I2C0_DTA); I2CSlaveInit(BASE_I2C0, ownAddress); //Initializes the I2C Slave block I2CSlaveEnable(BASE_I2C0); //Enables the I2C Slave block I2CSlaveIntEnable(BASE_I2C0); //Enables the I2C Slave interrupt IntEnable(INT0_I2C); } else if(index == Bay1_CellB_I2C) // I2C Third channel // Bay1 CellB { // SLAVE I2C3 INIT SysCtlPeripheralEnable(I2C3_SYSCTL_PERIPH_I2Cx); //Enables a peripheral . SysCtlPeripheralEnable(I2C3_SYSCTL_PERIPH_GPIOx); //Enables a peripheral. GPIOPinConfigure(I2C3_GPIO_PGx_I2CxSCL); GPIOPinConfigure(I2C3_GPIO_PGx_I2CxSDA); GPIOPinTypeI2CSCL(I2C3_GPIO_PORTx_BASE, I2C3_SCL); // SCL GPIOPinTypeI2C(I2C3_GPIO_PORTx_BASE, I2C3_DTA); I2CSlaveInit(BASE_I2C3, ownAddress); //Initializes the I2C Slave block I2CSlaveEnable(BASE_I2C3); //Enables the I2C Slave block I2CSlaveIntEnable(BASE_I2C3); //Enables the I2C Slave interrupt IntEnable(INT3_I2C); } else if(index == Bay2_CellA_I2C) // I2C Fourth channel // Bay2 CellA { // SLAVE I2C4 INIT SysCtlPeripheralEnable(I2C4_SYSCTL_PERIPH_I2Cx); //Enables a peripheral . SysCtlPeripheralEnable(I2C4_SYSCTL_PERIPH_GPIOx); //Enables a peripheral. GPIOPinConfigure(I2C4_GPIO_PGx_I2CxSCL); GPIOPinConfigure(I2C4_GPIO_PGx_I2CxSDA); GPIOPinTypeI2CSCL(I2C4_GPIO_PORTx_BASE, I2C4_SCL); // SCL GPIOPinTypeI2C(I2C4_GPIO_PORTx_BASE, I2C4_DTA); I2CSlaveInit(BASE_I2C4, ownAddress); //Initializes the I2C Slave block I2CSlaveEnable(BASE_I2C4); //Enables the I2C Slave block I2CSlaveIntEnable(BASE_I2C4); //Enables the I2C Slave interrupt IntEnable(INT4_I2C); } else if(index == Bay2_CellB_I2C) // I2C Fifth channel // Bay2 CellB { // SLAVE I2C5 INIT SysCtlPeripheralEnable(I2C5_SYSCTL_PERIPH_I2Cx); //Enables a peripheral . SysCtlPeripheralEnable(I2C5_SYSCTL_PERIPH_GPIOx); //Enables a peripheral. GPIOPinConfigure(I2C5_GPIO_PGx_I2CxSCL); GPIOPinConfigure(I2C5_GPIO_PGx_I2CxSDA); GPIOPinTypeI2CSCL(I2C5_GPIO_PORTx_BASE, I2C5_SCL); // SCL GPIOPinTypeI2C(I2C5_GPIO_PORTx_BASE, I2C5_DTA); I2CSlaveInit(BASE_I2C5, ownAddress); //Initializes the I2C Slave block I2CSlaveEnable(BASE_I2C5); //Enables the I2C Slave block I2CSlaveIntEnable(BASE_I2C5); //Enables the I2C Slave interrupt IntEnable(INT5_I2C); } #endif } /************************************************************************************************ * Returns corresponding SMBus base value *************************************************************************************************/ uint32 I2CBaseS(uint8 index) { uint32 Slave_base = 0; switch(index) { case Bay1_CellA_I2C: Slave_base = BASE_I2C0; break; case Bay1_CellB_I2C: Slave_base = BASE_I2C3; break; case Bay2_CellA_I2C: Slave_base = BASE_I2C4; break; case Bay2_CellB_I2C: Slave_base = BASE_I2C5; break; } return Slave_base; } /************************************************************************************************ * Returns corresponding SMBus cmd data to buffer *************************************************************************************************/ void smb_slave_tx_data(uint8 index, uint8 command) { switch(command) { case SMB_SPECIFICATION_INFO: temp_data[index] = 0x0003; break; case SMB_CYCLE_COUNT: temp_data[index] = 0x0005; break; case SMB_MAX_ERROR: if(Bay1_Calib == ENABLE) { temp_data[Bay1_CellA_I2C] = 0x0A; temp_data[Bay1_CellB_I2C] = 0x0A; } else { temp_data[Bay1_CellA_I2C] = 0x02; temp_data[Bay1_CellB_I2C] = 0x02; } if(Bay2_Calib == ENABLE) { temp_data[Bay2_CellA_I2C] = 0x0A; temp_data[Bay2_CellB_I2C] = 0x0A; } else { temp_data[Bay2_CellA_I2C] = 0x02; temp_data[Bay2_CellB_I2C] = 0x02; } break; case SMB_BATTERY_MODE: temp_data[index] = 0x0002; break; case SMB_BATTERY_STATUS: if(Bay1_Full == ENABLE) { temp_data[Bay1_CellA_I2C] = 0x00A0; temp_data[Bay1_CellB_I2C] = 0x00A0; } else { temp_data[Bay1_CellA_I2C] = 0x0080; temp_data[Bay1_CellB_I2C] = 0x0080; } if(Bay2_Full == ENABLE) { temp_data[Bay2_CellA_I2C] = 0x00A0; temp_data[Bay2_CellB_I2C] = 0x00A0; } else { temp_data[Bay2_CellA_I2C] = 0x0080; temp_data[Bay2_CellB_I2C] = 0x0080; } break; case SMB_CHARGING_VOLTAGE: temp_data[index] = 0x41A0; // 16800 mV break; case SMB_CHARGING_CURRENT: temp_data[index] = 0x0BB8; // 3000 mA break; case SMB_VOLTAGE: temp_data[index] = 0x3A98; // 15000 mV break; case SMB_CURRENT: temp_data[index] = 0x0B54; // 2900 mA break; case SMB_AT_RATE_TIME_TO_FULL: temp_data[index] = 0x0050; break; case SMB_AT_RATE_TIME_TO_EMPTY: temp_data[index] = 0x0070; break; case SMB_RELATIVE_STATE_OF_CHARGE: temp_data[index] = 0x0041; break; case SMB_ABSOLUTE_STATE_OF_CHARGE: temp_data[index] = 0x003D; break; case SMB_TEMPERATURE: temp_data[index] = 0x0C1C; // 31 * 100 deg cel break; } LSB_data = temp_data[index] & 0x00FF; MSB_data = temp_data[index] & 0xFF00; MSB_data = MSB_data >> 8; Data_Tx_Buffer[index][0] = MSB_data; Data_Tx_Buffer[index][1] = LSB_data; } /************************************************************************************************ * Interrupt handler (index - SMB channel index) *************************************************************************************************/ void I2CHandler(uint8 index) { // uint32 baseM = I2CBaseM (index); // getting master register base uint32 baseS = I2CBaseS(index); // getting slave register base uint8 status; uint8 data; /// SLAVE mode if(I2CSlaveIntStatus(baseS,true)) // I2CSlaveIntStatus() returns true => if I2C slave Interrupt status is active { // Clear the slave interrupt I2CSlaveIntClear(baseS); // Clears I2C Slave interrupt sources. // Get status of the I2C Slave status = I2CSlaveStatus(baseS); // Gets the current I2C Slave interrupt status. data = I2CSlaveDataGet(baseS); // getting the data (This function reads a byte of data from the I2C Slave Data Register.) if(status == I2C_SLAVE_ACT_RREQ_FBR) // Master has sent first byte { // handling that only if BUS is IDLE if(smb[index].state == SMB_IDLE) { smb[index].state = SMB_SLAVE; smb[index].index = 0; smb[index].pecCalculated = 0; smb[index].callback = smb[index].slaveCallback; // if slave mode activated, setting a callback to be slaveCallback smb[index].count = SMB_WORD; // we can only receive WORDs from a slave smb[index].cmd = I2CSlaveDataGet(baseS); // first byte is a command if(smb[index].flags & SMB_FLAG_PEC) { smb[index].count += 1; CRC8_add((uint8 *) &smb[index].pecCalculated,smb[index].cmd); } timerRestart(smb[index].timeoutTimer); } // else // We are in the middle of something, need to drop it first } /// SLAVE Receiver else if(status == I2C_SLAVE_ACT_RREQ) // Master has sent data { data = I2CSlaveDataGet(baseS); // getting the data smb [index].count--; if(smb[index].count == 0) // last byte received { if(smb [index].flags & SMB_FLAG_PEC) // if PEC - last byte is a checksum smb [index].pecReceived = data; smb [index].state = SMB_DONE; // we are done, need to handle the data } // adding byte to a buffer if it isn't last or if no PEC enabled if((smb[index].count > 0) || (!(smb[index].flags & SMB_FLAG_PEC))) { smb[index].que[smb[index].index++] = data; if(smb[index].flags & SMB_FLAG_PEC) CRC8_add((uint8 *) &smb [index].pecCalculated,data); } } /// SLAVE Transmitter if(status == I2C_SLAVE_ACT_TREQ) // Master has requested data(TREQ bit is set) { smb_slave_tx_data(index, smb[index].cmd); if(Data_Count_var < Max_I2C_Tx_Size) // Max_I2C_Tx_Size is the Maximum number of Bytes to be Sent { I2CSlaveDataPut(baseS, Data_Tx_Buffer[index][Data_Count_var]); // Transmits one BYTE Data_Count_var++; // Increments for the next Byte // Check if Tx is complete if (Data_Count_var == Max_I2C_Tx_Size) // Reset the Flags and other Variables { Data_Count_var = 0; smb[index].state = SMB_IDLE; } } } } } /************************************************************************************************ * Real I2C interrupt handlers *************************************************************************************************/ // Slave Board I2C Interrupt void I2C0IntHandler(void) // Bay1 CellA Interrupt { I2CHandler(Bay1_CellA_I2C); } void I2C3IntHandler(void) // Bay1 CellB Interrupt { I2CHandler(Bay1_CellB_I2C); } void I2C4IntHandler(void) // Bay2 CellA Interrupt { I2CHandler(Bay2_CellA_I2C); } void I2C5IntHandler(void) // Bay2 CellB Interrupt { I2CHandler(Bay2_CellB_I2C); } /* * main.c */ int main(void) { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |SYSCTL_XTAL_8MHZ); initI2C(Bay1_CellA_I2C, SLAVE_ADDRESS); // Bay1 CellA initI2C(Bay1_CellB_I2C, SLAVE_ADDRESS); // Bay1 CellB initI2C(Bay2_CellA_I2C, SLAVE_ADDRESS); // Bay2 CellA initI2C(Bay2_CellB_I2C, SLAVE_ADDRESS); // Bay2 CellB while(1) { } }
.