The problem here is that the init procedure for the touch panel controller and the interrupt service routine for the touch detection are using the same I2C resource object. And for some reason there is a touch event during initialization even without touching, which creates a I2C resource collision. You can emulate it by connecting the interrupt pin after initialization. The solution here is to fix the driver with a semaphore everywhere a thread tries to access the I2C object:
if (IICaccess.try_acquire()) {
m_i2c->write(m_addr, (const char *)®, 1);
IICaccess.release();
}
I investigated this problem and I encountered an important bug in the driver. Using a semaphore is not the best solution because a range of I2C transactions can be interrupted by other I2C transactions from another thread and a complete bunch cannot be finished in a clean way. It’s better to make it safe by design. This problem occurs during startup. The IRQ of the capacitive touch panel is enabled in the constructor before the initialization of the touch panel with the FT5206_Init() function. When the initialization happens there are some I2C transactions running and when the interrupt fires at the same time (which sometimes happens), the initialization procedure is interrupted and Mbed-OS chraches. The solution is to disable the interrupt in the first place in the constructor, disable it at the beginning of the FT5206_Init() and enable it when the initialization has been finished. In that way you may call TouchPanelInit() whenever you want in a safe way, and you force the programmer to call the initialization function before interrupts can take place.
Sam and I have been corresponding offline on this, and after a review, I agreed with his assertions that the IRQ enable and the configuration were in the wrong order. I’m not sure why this wasn’t noticed before (I have several of these in 24x7 duty). In any case, I have applied updates to the RA8875 Library, and published those changes. Thanks Sam!