I have 2 devices on the I2C bus. I need to be able to access them in different threads as one is handled with an interrupt input and the other is polled continuously.
I create the I2C device in the main programme and when I create each class that has the threads, I pass in the I2C device to the constructor for each class.
In each class, prior to calling the I2C function to set the configuration and execute the transaction, I enclose the calls within a lock {} block. eg. This is the ADC handler.
lock (McpAdc)
{
SetConfig(0);
if (_configDirty)
{
ConfigDevice();
}
else if (_conversionMode == ConversionMode.OneShot)
{
WriteConfigReg();
}
Result = McpAdc.Execute(_xReadAction, _ReadWriteTimeoutMilliSecs);
}
In the other class, I do something similar for handling touch.
lock (_sharedBus)
{
_sharedBus.Config = _busConfiguration;
if (_sharedBus.Execute(_readActions2, 500) == 0)
{
Debug.Print("Failed to perform I2C transaction");
}
}
The problem is that I am seeing a lot of transaction failures from the first call for the ADC. The other one doesn’t get called until I touch the LCD.
By the way, the old system with just the ADC running on I2C and the touch was SPI, everything was fine without the lock. This has only started since I changed to the shared access.
Is this the correct way to do this or am I going about this the wrong way?
That would work because your calls to the class will, from the look of it, be in the same thread. What would happen in your code if you were to create this and call them from different threads?
I’ve done this before where I have 2 I2C devices and change the configuration on the fly. This works really well as long as the calls are from the same thread. The issue I have is that I am calling them from different threads so I need some way to make it thread safe and I though lock would take care of this. It’s a shame that C# NETMF does not have semaphores that I have been used to with a Real Time OS like UCOS.
This may be another issue altogether. I have disabled the ADC I2C bus access for now and only have it running with the touch driver. I also tried it with the touch disable and only the ADC working. Lots of bus errors in both cases.
This is the same driver that Simon created for the capacitive display that works fine on my G120 board.
The I2C ADC on this board works fine with a ChipworkX module (which it was originally designed for)
The only difference to this and the ChipworkX based system is the fitting of this 5" LCD and that it has I2C for the touch driver connected to the same I2C as the ADC’s. The bus is pulled up with 2K2 resistors. It has a 200mm FPC cable from the main board to the LCD board. This works fine with the original ChipworkX board and the 4.3" LCD with an SPI connected touch screen driver.
I’ll hook up the logic analyser today to check whats happening.
@ Dave McLaughlin - Have you checked voltage level found on the I2C bus ? May be you have double resistors in parallel on the bus. I use on G400HDR 2 of my ADC MCP3424 board on the same bus (the boards are chained) and I have no problem with I2C. I didn’t test in concurrent context with 2 different thread, but I can do that. I think that “lock()” will be enough, but you need to resend again config to mcp3424 each time you request a conversion and remember to poll until RDY bit =0, before leaving lock(). This can be tricky with this chip.