Hi everyone,
First off I would like to thank those who have taken the time to read this post.
My environment Windows XP uVision 3 Keil MCB2300 with NXP LPC2386
Goal Read a temperature sensor
Physical Setup I have pins 24 and 25 exposed on my Dev board ( just some male headers ) which is I2C Bus 0. Also the appropriate pins are connected to a device with some I2C devices on it.
I am going to display code in the order in which it is executed for simplicity. There is also some defines which I will display too.
Even though documentation and startup code state that all registers are initialized to 0, I do it also.
There are other PINSEL and FIO0DIR registers set, but I believe it is irrelevant.
PINSEL0 &= 0x00000000; PINSEL1 &= 0x00000000; FIO0DIR |= 0x407E8B00; //pins [9:8], 11, 15, [22:17], 30 are ouputs
This function is used to setup I2C. I am showing it all just in case I have overlooked something.
uint8 I2CInit( ) { PCONP |= (1 << 7); /*Enable PCI2C0 interface 0 power/clock control bit */ PINSEL1 |= 0x01400000; /* set P0.27 and P0.28 to I2C0 SDA and SCK */ PCONP |= (1 << 19); /*Enable PCI2C1 interface 1 power/clock control bit */ PINSEL0 |= 0x0000000F; /* set P0.00 and P0.01 to I2C1 SDA and SCK */ PCONP |= (1 << 26); /*Enable PCI2C2 interface 2 power/clock control bit */ PINSEL0 &= ~0x00F00000; PINSEL0 |= 0x00A00000; /* set P0.10 and P0.11 to I2C2 SDA and SCK */ /*--- Clear flags ---*/ I20CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC; I21CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC; //I22CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC; /*--- Reset registers ---*/ I20SCLL = I2SCLL_SCLL; I20SCLH = I2SCLH_SCLH; I21SCLL = I2SCLL_SCLL; I21SCLH = I2SCLH_SCLH; if ( install_irq( I2C0_INT, (void *)I2C0MasterHandler, HIGHEST_PRIORITY ) == FALSE ) { return FAIL; } if ( install_irq( I2C1_INT, (void *)I2C1MasterHandler, HIGHEST_PRIORITY ) == FALSE ) { return FAIL; } I20CONSET = I2CONSET_I2EN; I21CONSET = I2CONSET_I2EN; return SUCCESS; }
At this point everything should be initiated and ready to go
The function below gets called when we want to read an I2C device that requires a write first.
addr = Address of I2C device sz = Size of response offset = The register inside of the device I want to read buff = The buffer that gets passed here contains storage for the response of the read bus = Specify which bus the I2C device is connected to
int write_readI2C(uint8 addr, uint8 sz, uint8 offset, uint8 *buff, uint8 bus) { uint8 i; uint16 stat; /* shift address to bits 7-1; bit 0 is R/W */ I2CMasterBuffer[0] = addr<<1; /* write 2 size: I2C address + offset to read */ I2CWrLength = 2; I2CMasterBuffer[1] = offset; /* now load read command */ I2CMasterBuffer[2] = addr<<1 | RD_BIT; I2CRdLength = sz; stat = I2CEngine(bus); if (stat) return stat; if (RdIndex == 0) //no data was read return FAIL; //(I2C_ERR_MASK | RD_ERR); for ( i = 0; i < sz; i++ ) buff[i] = I2CMasterBuffer[i+3]; return stat; }
The line stat = I2CEngine(bus); above is the function stated below
uint8 I2CEngine( BYTE bus ) { DWORD timeout = 0; I2CMasterState = I2C_IDLE; RdIndex = 0; WrIndex = 0; I2CStop(bus); if (I2CStart(bus) != SUCCESS) { I2CStop(bus); return FAIL; } while ( 1 ) { if ( I2CMasterState == I2C_STOP) //DATA_NACK { I2CStop(bus); break; } if ( timeout >= MAX_TIMEOUT ) return FAIL; timeout++; } return SUCCESS; }
The statement if (I2CStart(bus) != SUCCESS) above is where the error occurs
#define MAX_TIMEOUT 0x00008FFF uint8 I2CStart( uint8 bus ) { uint32 timeout = 0; uint8 returnValue = FAIL; if (bus == 1) I21CONSET = I2CONSET_STA; /* Set Start flag */ else if (bus == 0) I20CONSET = I2CONSET_STA; /* Set Start flag */ /*--- Wait until START transmitted ---*/ while( 1 ) { if (I2CMasterState == I2C_STARTED) { returnValue = SUCCESS; break; } if ( timeout >= MAX_TIMEOUT ) { returnValue = FAIL; break; } timeout++; } return( returnValue ); }
The statement if ( timeout >= MAX_TIMEOUT ) above is where the program takes me if I set a breakpoint inside the IF statement.
I was going to post my I2C0MasterHandler IRQ but this post is getting long.