I2C write error


#1

Hi,
I want to I2C bus of Q2686 module to communicate with a accelerometer. Firstly, I made the subscription of I2C bus and got “0” value to the bus handle. Is it right? Then, I try to send test data to the slave device by using adl_busWrite() function. But, it will return error code: -2 (ADL_RET_ERR_PARAM), I checked my parameters and can not figure out the error. Can anyone help me with this problem? ( the below is my test code)

[color=red]adl_busI2CSettings_t MyI2CConfig =
{
0x18,
ADL_BUS_I2C_CLK_STD
};

#define WRITE_SIZE 5
#define READ_SIZE 3

adl_busAccess_t AccessConfig =
{
0, 0, 0, 0,
ADL_BUS_SIZE_BYTE
};

s32 I2CHandle;
adl_tmr_t *hTmr;

u8 WrtBuff[WRITE_SIZE], RdBuff[READ_SIZE];

void Timer_Handler ( u8 ID )
{
s32 ReadValue;

wm_memset(WrtBuff, WRITE_SIZE, 0);
AccessConfig.AddressLength = 0x08;
AccessConfig.Address = (u32) 0x06 << 24;

ReadValue = adl_busWrite(I2CHandle, &AccessConfig, WRITE_SIZE, WrtBuff);

TRACE (( 3, "Wrtie Bus: %d", ReadValue));

}

void MyFunction ( void )
{

I2CHandle = adl_busSubscribe(ADL_BUS_I2C, (adl_busSettings_u *)&MyI2CConfig);

TRACE (( 2, "Bus Handle: %d", I2CHandle ));

hTmr = adl_tmrSubscribe ( FALSE, 10, ADL_TMR_TYPE_100MS, Timer_Handler );

}

void adl_main ( adl_InitType_e InitType )
{
TRACE (( 1, “Embedded Application : Main” ));

// TO DO : Add your initialization code here
MyFunction();

}


#2

When posting code, you need to use the ‘Code’ button so that your layout is preserved, and then use the ‘Preview’ button to verify that it’s worked:

adl_busI2CSettings_t MyI2CConfig = 
{
	0x18,
	ADL_BUS_I2C_CLK_STD
};

#define WRITE_SIZE	5
#define READ_SIZE	3

adl_busAccess_t	AccessConfig = 
{
	0, 0, 0, 0,
	ADL_BUS_SIZE_BYTE 
};

s32	I2CHandle;
adl_tmr_t *hTmr;

u8 WrtBuff[WRITE_SIZE], RdBuff[READ_SIZE];


void Timer_Handler ( u8 ID )
{
	s32 ReadValue;

	wm_memset(WrtBuff, WRITE_SIZE, 0);
	AccessConfig.AddressLength = 0x08;
	AccessConfig.Address = (u32) 0x06 << 24;

	ReadValue = adl_busWrite(I2CHandle, &AccessConfig, WRITE_SIZE, WrtBuff);

	TRACE (( 3, "Wrtie Bus: %d", ReadValue));
}

void MyFunction ( void )
{
	

	I2CHandle = adl_busSubscribe(ADL_BUS_I2C, (adl_busSettings_u *)&MyI2CConfig);

	TRACE (( 2, "Bus Handle: %d", I2CHandle ));

	hTmr = adl_tmrSubscribe ( FALSE, 10, ADL_TMR_TYPE_100MS, Timer_Handler );

}



void adl_main ( adl_InitType_e InitType )
{
    TRACE (( 1, "Embedded Application : Main" ));
    
    // TO DO : Add your initialization code here
	MyFunction();
}

#3

Hello,

Did you get always -2 return code with the busWrite() Api? Just declare your timer cyclic to test it:

hTmr = adl_tmrSubscribe ( TRUE, 10, ADL_TMR_TYPE_100MS, Timer_Handler );

I don’t know the type of your accelerometer, but some devices don’t like if you are writing values at wrong places. So beware what you are writing and where. I suggest you should read 1 register for testing purposes.

I have a wismo, accelerometer and a controller on the I2C bus, it works but the communication between the controller and the wismo was not easy to develop, because the current wismo firmware (OS 6.61) is very sensible for the I2C bus. If the controller response is not fast and precise it can hang the module. I really hope that it will be corrected in the next release.

Finally here is my working code for LIS3LV02DQ accelerometer:

static adl_busAccess_t acc_iic_a_t =
{
   0, 0, 0, 8,
   ADL_BUS_SIZE_BYTE
};


void iic_acc_init()
{

adl_busI2CSettings_t acc_bus_set =
{
	IIC_ADRESS_ACC,          // ChipAddress
	ADL_BUS_I2C_CLK_FAST     // Clk_Speed 
}; 

u8 val_ctrl_reg1 = 0xC7; //accelator on with 3 axis

////---------Accelerometer i2c init------------- ////
	iic_acc_handle = adl_busSubscribe( ADL_BUS_I2C,  ( adl_busSettings_u * )  &acc_bus_set);

	if (iic_acc_handle >= 0)
	{
		TRACE (( 1, "--- iic acc--- suscribe OK" ));
	}
	else
	{
		SendSerialReport("--- iic acc ERROR --- subscribe FAILED");
		return;
	}

	
	iic_accSend(ACC_CTRL_REG1, 1, &val_ctrl_reg1 );

}

s32 iic_accSend(u8 addr, u32 data_len, ascii* data_p )
{
s32 ret;

	acc_iic_a_t.Address = ((u32)addr) << 24;
	acc_iic_a_t.Address |= 0x80000000; //auto increment adress
	
	ret = adl_busWrite( iic_acc_handle, &acc_iic_a_t, data_len, (void*) data_p );
	
	switch (ret)
	{
		case OK:
			//TRACE (( 1, "--- iic acc--- send: OK" ));
		break;
		case ADL_RET_ERR_BAD_STATE:
			TRACE (( 1, "--- iic acc ERROR --- send: no ack" ));
		break;
		default:
			TRACE (( 1, "--- iic acc ERROR --- send: %d" , ret));
		break;	
	}

	return ret;

}


s32 iic_accRead( u8 addr, u32 data_len, ascii* data_p )
{
s32 ret;

	acc_iic_a_t.Address = ((u32)addr) << 24;
	acc_iic_a_t.Address |= 0x80000000; 

	ret = adl_busRead( iic_acc_handle, &acc_iic_a_t, data_len, (void*) data_p );

	switch (ret)
	{
		case OK:
			//TRACE (( 1, "--- iic acc --- read: OK" ));
		break;
		case ADL_RET_ERR_BAD_STATE:
			TRACE (( 1, "--- iic acc ERROR --- read: no ack" ));
		break;
		default:
			TRACE (( 1, "--- iic acc ERROR --- read: %d" , ret));
		break;	
	}

	return ret;

}

void iic_accRefresh()
{
s16 out_x = 0;
s16 out_y = 0;
s16 out_z = 0;


	iic_accRead( ACC_OUTX_L, 2, (ascii*)&out_x );
	iic_accRead( ACC_OUTY_L, 2, (ascii*)&out_y );
	iic_accRead( ACC_OUTZ_L, 2, (ascii*)&out_z );

	TRACE (( 1, "-- ACC -- X[ %d ] Y[ %d ] Z[ %d ]", out_x, out_y, out_z));

	/*
	...
	*/
}

Best Regards,

tom


#4

Hello, tomalex,
Thank you for your reply. Finally, I found my problem is the address associated with accelerometer is not correct. My accelerometer is Kionix KXP84. Although its slave address is 0x18, I cannot assign 0x18 as the slave address directly. I need to shift one bit so that the chip address should be assigned 0x30.
There is one thing I do not understand. Why the Address parameter for adl_busWrite() function need to do a bit-wise or 0x80000000? (like the below code)
[color=red]acc_iic_a_t.Address = ((u32)addr) << 24;
acc_iic_a_t.Address |= 0x80000000; //auto increment adress

Best Regards,
Lillian


#5

Hello,

That is specific for my device. If that bit is set, the adress in the accelerometer automatically incremented so you can write and read more bytes in one session.

Regards,

tom


#6

I’ am gladly experienced that this stupid bug is corrected in the OS 6.62 beta,
I am starting to like this version. I hope the final version will not spoil everything. :smiley:

Regards,

tom


#7

Hey guys and gals… had a similar problem for a few days now… getting -2 error on bus Read or write…

I am using the new LIS3DH and this is the waveform i get on reading ANY Sub Address, this is on the SDA Line… Looks like 0011001 below for first 7 bits

snippets of my code :

const adl_busI2CSettings_t MyI2CConfig =
{
	0x33,						//Chip Address(not shifted)
	ADL_BUS_I2C_CLK_STD, 		//chip uses the I2C standard clock speed
	ADL_BUS_I2C_ADDR_7_BITS,	//7 bits address length
	ADL_BUS_I2C_MASTER_MODE		//master mode
};

static adl_busAccess_t AccessConfig = {0, 0};
	//Subscribe to the I2C Bus
	//MyI2CHandle = adl_busSubscribe(ADL_BUS_ID_I2C, 1, (void *)&MyI2CConfig);
	MyI2CHandle = adl_busSubscribe(ADL_BUS_ID_I2C, 1, (adl_busSettings_u *)&MyI2CConfig);

	adl_busIOCtl(MyI2CHandle, ADL_BUS_CMD_SET_ADD_SIZE, &byte_size_2);
    //adl_busIOCtl(MyI2CHandle, ADL_BUS_CMD_SET_ASYNC_MODE, NULL );
    adl_busIOCtl(MyI2CHandle, ADL_BUS_CMD_SET_DATA_SIZE, &byte_size_2 );
    adl_busIOCtl(MyI2CHandle, ADL_BUS_CMD_GET_DATA_SIZE, &byte_size_2 );
	adl_busIOCtl(MyI2CHandle, ADL_BUS_CMD_GET_ADD_SIZE, &byte_size_2);

MyI2CHandle returns nice positive value as expected

AccessConfig.Address = ((u32)addr) << 24;

Yes my address’s (addr) are correct… example im parsing reg 45 (out Z low i think) for now…

ret = adl_busRead( MyI2CHandle, &AccessConfig, 1, (void *)ReadBuffer);

ret always = -2

This error exists even trying all the “working” code here, so dont know what the problem is…

APPLICATION OS : 06.32


#8

Problem Found! :

const adl_busI2CSettings_t MyI2CConfig =
{
	//0x33,						//Chip Address(not shifted)
		0x19,
	ADL_BUS_I2C_CLK_STD, 		//chip uses the I2C standard clock speed
	ADL_BUS_I2C_ADDR_7_BITS,	//7 bits address length
	ADL_BUS_I2C_MASTER_MODE		//master mode
};

7 bit address as per ADL_BUS_I2C_ADDR_7_BITS dam i cant believe i missed it and gave 8 bit address (7 bit slave addr + read bit of ‘1’)