Using a 2nd I2C bus on iMX6 with Iris carrier (part 2)

This is a follow-up question to a previous one:

To review: we are trying to use I2C3 off of connector X16 (pins 8 & 11) of an Iris carrier board fitted with an iMX6 Solo module. Thank you for your explanation of the I2C numbering in the previous response.

Your response also suggested the use of the Toradex libraries to configure I2C. So we’re trying that, but with little success so far.

What we’re seeing on the 'scope is exactly the same as when we configured things with the GPIO tool: When I do an I2C read, X16 pin 8 (SCL) and pin 11 (SDA) drop to ground for about 1/4 second, and there is no recognizable I2C signal apparent.

Here is our I2C init code. I have removed most error checking for brevity but each of the library functions succeeds when stepping through with the debugger:

private void InitI2C()
{
	Boolean result;

	String i2cName = "I2C3";
	i2cHandle = i2c.I2c_Init(i2cName);                                        

	// Create uIo for SCL pin mapping to SODIMM 88
	gpio.uIo i2cSclPin = new gpio.uIo();
	i2cSclPin.ColibriPin.tp = (UInt16)gpio.tIoType.ioColibriPin;
	i2cSclPin.ColibriPin.nr = 88;

	// Create uIo for DSA pin mapping to SODIMM 92
	gpio.uIo i2cSdaPin = new gpio.uIo();
	i2cSdaPin.ColibriPin.tp = (UInt16)gpio.tIoType.ioColibriPin;
	i2cSdaPin.ColibriPin.nr = 92;

	// Configure the new I2C pins.
	IntPtr gpioHandle = gpio.Gpio_Init("SOFTWARE\\Toradex\\gpio");
	result = gpio.Gpio_SetConfigString(gpioHandle, i2cSclPin, null, "altfn=6", TdxCommon.ParamStorageType.StoreVolatile);
	result = gpio.Gpio_SetConfigString(gpioHandle, i2cSdaPin, null, "altfn=1", TdxCommon.ParamStorageType.StoreVolatile);
	result = i2c.I2c_SetConfigInt(i2cHandle, "ioScl", i2cSclPin.GenericDefinition, TdxCommon.ParamStorageType.StoreVolatile);
	result = i2c.I2c_SetConfigInt(i2cHandle, "ioSda", i2cSdaPin.GenericDefinition, TdxCommon.ParamStorageType.StoreVolatile);

	if (!i2c.I2c_Open(i2cHandle))                                                    
	{
		Debug.WriteLine("Error: I2C Open");
	}
	i2c.I2c_SetConfigInt(i2cHandle, "BitRateHz", 100000, TdxCommon.ParamStorageType.StoreVolatile);
	i2c.I2c_SetConfigInt(i2cHandle, "SlaveAddrSize", 7, TdxCommon.ParamStorageType.StoreVolatile);
	i2c.I2c_SetConfigInt(i2cHandle, "RegisterAddrSize", 8, TdxCommon.ParamStorageType.StoreVolatile);

	Debug.WriteLine(i2cName + " opened successfully.");
}

I suspect I’m missing something basic but I’m unable to figure it out.

Any help would be appreciated.

I should mention that there is nothing in the registry at “SOFTWARE\Toradex\gpio”, but I had to provide a path for the Gpio_init function.

This is required if you want to make the GPIO configuration permanent, so your app will not have to specify parms at every restart, but it’s optional, you can pass NULL.
I’ll try to reproduce the issue and hope to provide a solution soon.

Can you try to move those instructions:

Gpio_SetConfigString(gpio,i2cSclPin,NULL,TEXT("altfn=6,sion=force"),StoreVolatile);
Gpio_SetConfigString(gpio,i2cSdaPin,NULL,TEXT("altfn=1,sion=force"),StoreVolatile);

after the I2C_open call?
That should be a workaround.

Your suggestion worked. Thanks very much. Hopefully will find this information useful.

I’ll post the working code in an answer. It may be be useful to others.

This is the working I2C init code to re-map Iris carrier X16 pins 8 and 11 to I2C3 SCL and SDA respectively.

Thanks to valter.tx for the suggestion to re-arrange the initialization code. His suggestion was to put the GPIO init code after the I2C open call. That made all the difference.

private void InitI2C()
{
	Boolean result;

	String i2cName = "I2C3";
	i2cHandle = i2c.I2c_Init(i2cName);                                        

	// Create uIo for SCL pin mapping to SODIMM 88
	gpio.uIo i2cSclPin = new gpio.uIo();
	i2cSclPin.ColibriPin.tp = (UInt16)gpio.tIoType.ioColibriPin;
	i2cSclPin.ColibriPin.nr = 88;

	// Create uIo for DSA pin mapping to SODIMM 92
	gpio.uIo i2cSdaPin = new gpio.uIo();
	i2cSdaPin.ColibriPin.tp = (UInt16)gpio.tIoType.ioColibriPin;
	i2cSdaPin.ColibriPin.nr = 92;

	// Configure the new I2C pins.
	result = i2c.I2c_SetConfigInt(i2cHandle, "ioScl", i2cSclPin.GenericDefinition, 
											TdxCommon.ParamStorageType.StoreVolatile);
	result = i2c.I2c_SetConfigInt(i2cHandle, "ioSda", i2cSdaPin.GenericDefinition, 
											TdxCommon.ParamStorageType.StoreVolatile);

	if (!i2c.I2c_Open(i2cHandle))                                                    
	{
		Debug.WriteLine("Error: I2C Open");
	}

	IntPtr gpioHandle = gpio.Gpio_Init( null );
	result = gpio.Gpio_SetConfigString(gpioHandle, i2cSclPin, null, "altfn=6,sion=force", 
												TdxCommon.ParamStorageType.StoreVolatile);
	result = gpio.Gpio_SetConfigString(gpioHandle, i2cSdaPin, null, "altfn=1,sion=force", 
												TdxCommon.ParamStorageType.StoreVolatile);
	
	i2c.I2c_SetConfigInt(i2cHandle, "BitRateHz", 100000, TdxCommon.ParamStorageType.StoreVolatile);
	i2c.I2c_SetConfigInt(i2cHandle, "SlaveAddrSize", 7, TdxCommon.ParamStorageType.StoreVolatile);
	i2c.I2c_SetConfigInt(i2cHandle, "RegisterAddrSize", 8, TdxCommon.ParamStorageType.StoreVolatile);

	Debug.WriteLine(i2cName + " opened successfully.");
}

Thank you very much for publishing the code and providing other people a ready-to-use solution. We appreciate your efforts in the community.
We also found the issue and it’s going to be fixed in next release of the libraries, so additional GPIO settings won’t be needed (but will not do any damage if left in place, of course).

The only thing I should mention is that the posted code really needs some error checking, and could be refactored using some simp,e support functions. However, it does accurately show the steps required to remap the I2C bus.