Other Parts Discussed in Thread: MOTORWARE
I have written a simple I2C slave interface for the F28027F and it seems to be working as expected, but there is one remaining problem. When I add the I2C stuff into motorware lab1 it runs for a while then hangs (seems to be holding scl low). This locks up the bus until there is a reset. When I reduce the overhead of mainISR the problem goes away.
This is is what I have found causes the problem:
I get the I2C_IntSrc_Slave_Addr (7) interrupt, if it is a read command I also immediately get the I2C_IntSrc_Tx_Rdy (5). Normally this isn't a problem. If mainISR is executing at this time it seems that one of the interrupts is missed and the I2C module locks up. I have verified this behavior by timing the ISRs with a logic analyzer.
I am not using FIFOs, which I imagine could mitigate the problem. I use the I2C_IntSrc_Slave_Addr interrupt to setup to clear some array indices and set I2CDXR to the first value (if I do this on the I2C_IntSrc_Tx_Rdy interrupt the first byte sent uses the previous value of I2CDXR), I could probably do this on a stop interrupt just as well. I could also implement some sort of timeout check as well. I mainly just want to understand what the problem is in this case.
Init Code:
void HAL_setupI2C(HAL_Handle handle)
{
HAL_Obj *obj = (HAL_Obj *)handle;
//I2C_Obj *I2CARegs=(I2C_Obj *)obj->I2CaHandle;
// Initialize I2C
/* I2CARegs->I2CSAR = 0x0050; // Slave address - EEPROM control code
I2CARegs->I2COAR =1;
// I2CCLK = SYSCLK/(I2CPSC+1)
I2CARegs->I2CPSC = 6; // Prescaler - need 7-12 Mhz on module clk
I2CARegs->I2CCLKL = 20; // NOTE: must be non zero
I2CARegs->I2CCLKH = 20; // NOTE: must be non zero
I2CARegs->I2CIER = (1<<6)|(1<<4)|(1<<3); // Enable SCD & ARDY interrupts
I2CARegs->I2CMDR = 0x0020; // Take I2C out of reset*/
// Stop I2C when suspended
//PIE_enableInt(PIE_Handle pieHandle, const PIE_GroupNumber_e group, const PIE_InterruptSource_e intSource)*/
I2C_setSlaveAddress(obj->I2CaHandle, 0x0001);
I2C_setupClock(obj->I2CaHandle, 6, 20,20);
I2C_enableInt(obj->I2CaHandle,I2C_IntEn_Rx_Rdy|I2C_IntEn_Tx_Rdy|I2C_IntEn_Slave_Addr);
I2C_setSlave(obj->I2CaHandle);
I2C_enable(obj->I2CaHandle);
}
void HAL_enableI2CInt(HAL_Handle handle)
{
HAL_Obj *obj = (HAL_Obj *)handle;
PIE_enableInt(obj->pieHandle,PIE_GroupNumber_8,PIE_InterruptSource_I2CA1 );
CPU_enableInt(obj->cpuHandle,CPU_IntNumber_8);
}
Isr code:
interrupt void i2c_int1a_isr(void) // I2C-A
{
// Read interrupt source
halHandle->gpioHandle->AIOTOGGLE=(1<<2);
int IntSource;
IntSource = (int)I2C_getIntSource(halHandle->I2CaHandle);
//GPIO_toggle(myGpio, GPIO_Number_1);
// Interrupt source = stop condition detected
/*if(IntSource == I2C_SCD_ISRC)
{
} // end of stop condition detected
*/
if(IntSource==I2C_IntSrc_Slave_Addr)
{
RxPointer=0;
TxPointer=0;
//GPIO_toggle(myGpio, GPIO_Number_2);
//I2caRegs.I2CDXR=StatusPacket[0];
}
if(IntSource==I2C_IntSrc_Rx_Rdy)
{
if(RxPointer<sizeof(RxPacket))
RxPacket[RxPointer]=I2C_getData(halHandle->I2CaHandle);
if(RxPointer==1)
RxLength=RxPacket[RxPointer];
if(RxPointer==(RxLength+3))
{
memcpy((void*)DecodeBuffer,(void*)RxPacket,sizeof(DecodeBuffer));
DecodePacket=1;
}
RxPointer++;
}
if(IntSource==I2C_IntSrc_Tx_Rdy)
{
if(TxPointer<(sizeof(StatusPacket)-1))
TxPointer++;
/*if(TxPointer==0)
GPIO_setLow(myGpio, GPIO_Number_3);
else
GPIO_setHigh(myGpio,GPIO_Number_3);*/
I2C_putData(halHandle->I2CaHandle,StatusPacket[TxPointer]);
}
// Enable future I2C (PIE Group 8) interrupts
//PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
PIE_clearInt(halHandle->pieHandle,PIE_GroupNumber_8);
//halHandle->gpioHandle->AIOCLEAR=(1<<2);
}