I2C experience

Hi all,

I’ve been trying for past few days to make I2C work on a SL6087. I’m writing this in the hopes that you’ll find it when you need it. I’m only using synchronous access (no interrupts etc.)

Just like everyone else, I’ve been getting ADL_RET_ERR_PARAM on both adl_busRead and adl_busWrite. It seems that this error code is returned in several cases:

  • One or both of the GPIOs are used elsewhere (note that the adl_busSubscribe function succeeds!)
  • The bus is busy (SDA or SCL is held low)
  • The chip address is wrong
  • The pAccessMode is NULL

It is also possible to generate a Repeat condition using the pAccessMode.address: you can write 1-4 bytes to the bus, then a repeat condition is set, then you can read or write as many bytes as you want.

Notes on the code: I’ve removed all error checking to keep it short. Also it uses local variables in adl_busRead and Write because I’m using synchronous mode. Feel free to add some buffers and wm_memmove()s.

const adl_busI2CSettings_t DefaultBusGpsSettings=
 {
  0x00000084>>1, //chip address = 0x84
  ADL_BUS_I2C_CLK_STD, //_STD, _FAST, _HIGH
  ADL_BUS_I2C_ADDR_7_BITS,
  ADL_BUS_I2C_MASTER_MODE
 };
int addressLength=0;
s32 busI2CGpsHandle=-1;

void i2cOpen()
 {
  adl_busI2CSettings_t busGpsSettings;
  wm_memmove(&busGpsSettings, &DefaultBusGpsSettings, sizeof(busGpsSettings));
  busI2CGpsHandle=adl_busSubscribe(ADL_BUS_ID_I2C, 1, (adl_busSettings_u *)&busGpsSettings);
 }

void i2cClose()
 {
  adl_busIOCtl(busI2CGpsHandle, ADL_BUS_CMD_RESET_BLOC, 0); //seems to help here and there :-/
  adl_busUnsubscribe(busI2CGpsHandle);
  busI2CGpsHandle=-1;
 }

adl_busAccess_t i2cAccessR=
 {
  0xFD000000, //used: SET_ADD_SIZE 8
  0 //ignored for I2C
 };
adl_busAccess_t i2cAccessW=
 {
  0xFF000000, //ignored: SET_ADD_SIZE 0
  0 //ignored for I2C
 };

int i2cSendRecv(int wrlen, u8 *wrdata, int rdlen, u8 *rddata)
 {
  //write 'wrdata' data only
  addressLength=0*8;
  adl_busIOCtl(busI2CGpsHandle, ADL_BUS_CMD_SET_ADD_SIZE, &addressLength);
  adl_busWrite(busI2CGpsHandle, &i2cAccessW, wrlen, wrdata);
  
  //write 1 byte '\xFD', repeat condition, then read 'rdlen' bytes
  addressLength=1*8;
  adl_busIOCtl(busI2CGpsHandle, ADL_BUS_CMD_SET_ADD_SIZE, &addressLength);
  adl_busRead(busI2CGpsHandle, &i2cAccessR, rdlen, rddata);

  return 0;
 }

Hi milan,
Thanks for sharing this… :smiley: