I have set one processor up a a slave using the following code (from an example in the 52259 manual):
//
// I2C slave routines
//
static __interrupt__ void _IIC_InterruptSlave(void) // I2C0 interrupt
{
char junk;
I2SR&=~IIC_IIF; // clear the interrupt flag
if(I2SR&IIC_IAL) {
I2SR&=~IIC_IAL; // If IAL (arbitration lost) set, clear it
if(I2SR&IIC_IAAS) {
buffOffset=1; // Ignore space for the address
} else return;
}
if(I2SR&IIC_IAAS) { // IAAS is set, received our slave address
ParamBackBoard=1;
BackTimer=1000;
if(I2SR&IIC_SRW) { // if SRW set, tx mode
I2CR|=IIC_MTX; // Set hardware to tx mode
buffOffset=1; // Init buffer address
DEBUG_LED_ON; // KAF
I2DR=output_i2c.data.buf[buffOffset++]; // Send the first character
} else { // rx mode
I2CR&=~IIC_MTX; // Set hardware to rx mode
buffOffset=1; // Init buffer address
junk=I2DR; // Do a dummy read
}
} else { // IAAS not set, in the middle of communication
if(I2CR&IIC_MTX){ // If in tx mode
if(I2SR&IIC_RXACK){ // Received an ACK so ready for next byte
I2DR=output_i2c.data.buf[buffOffset++]; // Send the next character
}else { // Done transmitting data
I2CR&=~IIC_MTX; // Set hardware to rx mode
junk=I2DR; // Do a dummy read
}
}else { // If in rx mode
input_i2c.data.buf[buffOffset++]=I2DR; // Read the next character
}
}
}
//
// Configure the IIC hardware
//
void fnConfigIICSlave(IICTABLE *pars)
{
unsigned char ucSpeed;
POWER_UP(POWER_I2C); // enable clock to module {46}
PASPAR |= (AS_I2C_SCL_0_FUNCTION | AS_I2C_SDA_0_FUNCTION); // configure the SDA and SCL pins on AS
// The calculation of the correct divider ratio doesn't follow a formular but is best taken from a table.
// The required divider value is ((BUS_CLOCK/1000)/pars->usSpeed). Various typical speeds are supported here.
switch (pars->usSpeed) { // {31}
case 400: // high speed IIC
#if BUS_CLOCK > 60000000 // 80MHz
ucSpeed = 0x32; // set about 400k with 80MHz bus frequency
#elif BUS_CLOCK > 50000000 // 60MHz
ucSpeed = 0x0d; // set about 400k with 60MHz bus frequency
#elif BUS_CLOCK > 40000000 // 50MHz
ucSpeed = 0x0b; // set about 400k with 50MHz bus frequency
#else // assume 40MHz
ucSpeed = 0x0a; // set about 400k with 40MHz bus frequency
#endif
break;
case 100:
default: // default to 100kHz
#if BUS_CLOCK > 60000000 // 80MHz
ucSpeed = 0x3a; // set about 100k with 80MHz bus frequency
#elif BUS_CLOCK > 50000000 // 60MHz
ucSpeed = 0x15; // set about 100k with 60MHz bus frequency
#elif BUS_CLOCK > 40000000 // 50MHz
ucSpeed = 0x37; // set about 100k with 50MHz bus frequency
#else // assume 40MHz
ucSpeed = 0x36; // set about 100k with 40MHz bus frequency
#endif
break;
case 50:
#if BUS_CLOCK > 60000000 // 80MHz
ucSpeed = 0x3e; // set about 50k with 80MHz bus frequency
#elif BUS_CLOCK > 50000000 // 60MHz
ucSpeed = 0x19; // set about 50k with 60MHz bus frequency
#elif BUS_CLOCK > 40000000 // 50MHz
ucSpeed = 0x3b; // set about 50k with 50MHz bus frequency
#else // assume 40MHz
ucSpeed = 0x3a; // set about 50k with 40MHz bus frequency
#endif
break;
}
I2FDR = ucSpeed;
I2CR = (IIC_IEN); // enable IIC controller and set slave mode
IC_ICR_0_17 = IIC_INTERRUPT_PRIORITY; // define interrupts level and priority
fnSetIntHandler(IIC_VECTOR, (unsigned char *)_IIC_InterruptSlave); // enter the handler routine
IC_IMRL_0 &= ~(IIC_PIF_INT_L | MASK_ALL_INT);
I2CR|=IIC_IIEN; // Enable interrupts
I write and read from the master with the following code:
static const unsigned char ucReadI2C[] = {17, 1, OWN_TASK};
retval=fnWrite(IICPortID, (unsigned char *)&(output_i2c.zero), SIZEOFCOMSTRUCT+2);
sprintf(buf,"W=%d\n\r",retval);
fnDebugMsg(buf);
retval=fnRead(IICPortID, (unsigned char *)ucReadI2C, 0);
sprintf(buf,"R=%d\n\r",retval);
fnDebugMsg(buf);
At the end of the main look I added the following code to input the read message data:
//
// I2C read code
//
if (fnMsgs(IICPortID) != 0) { // if IIC message waiting
DEBUG_LED2_ON; //KAF
sprintf(DebugStr,"M=%d ",fnMsgs(IICPortID));
fnDebugMsg(DebugStr);
while ((Length = fnRead(IICPortID, ucInputMessage, MEDIUM_MESSAGE)) != 0) {
sprintf(DebugStr,"L=%d\r\n",Length);
fnDebugMsg(DebugStr);
memcpy(&input_i2c.count,ucInputMessage,Length);
}
}
The writes work OK, if I comment out the reads it runs forever.
If I try to read I get this debug output:
Hello, world... Coldfire V2 MCU
BoardNum=1
I2C Init 15
W=18
R=3
W=1
In the middle of writing the second write string the system hangs.
The debug led never turns on (DEBUG_LED2 from the I2C read code) so
it never gets there.
Anyone see anything wrong?
Keith Flick
kaflick@sev.org