Assertion error when using RA8875 lib

In the RA8875 lib an IRQ is registered for reading a touch panel:

eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
m_irq->fall(queue.event(callback(this, &RA8875::TouchPanelISR))); 

After starting up, I always get:

++ MbedOS Error Info ++
Error Status: 0x80FF0144 Code: 324 Module: 255
Error Message: Assertion failed: id
Location: 0x8005515
File: ./mbed-os/events/Event.h+166
Error Value: 0x0
Current Thread: application_unnamed_thread Id: 0x20001A98 Entry: 0x800845D StackSize: 0x1000 StackMem: 0x20003CB8 SP: 0x20007EAC
For more info, visit:
-- MbedOS Error Info --

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 *)&reg, 1);

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!