I2C Read/Write functions in GPIO Interrupt

Hi.

I've configured an I2C device to gather data and if finished it will trigger an interrupt line which I connected to the an GPIO interrupt of the NRF52.
I'm using i2c_burst_read(...) from within that GPIO interrupt but always get the following error:

 <err> i2c_nrfx_twim: Error on I2C line occurred for message 0

With polling the GPIO line and then reading the data out of the I2C device everything works fine. Is there a restriction accessing I2C functions within an interrupt? How would be the solution to this? I was thinking of using an event which i set in the GPIO interrupt and in a thread I read out the data with I2C functions. But would't that be way slower that just reading a few registers within the ISR?

I configured the GPIO interrupt using:

gpio_pin_configure_dt(&int1, GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&int1, GPIO_INT_EDGE_TO_ACTIVE);
gpio_init_callback(&irq1, int1_callback, BIT(int1.pin));
gpio_add_callback(int1.port, &irq1);
I appreciate every help.
Thanks & Best Regards,
Phobios
  • Hello Phobios,

    But would't that be way slower that just reading a few registers within the ISR

    The API initiates the read transaction and doesn't return until the transaction completes, making it more involved than reading some registers. As a result, the blocking time can be relatively long.

    The i2c driver is using semaphores with waits to allow the API to be blocking/synchronous, and these cannot be called from an interrupt context. 

    How would be the solution to this? I was thinking of using an event which i set in the GPIO interrupt and in a thread I read out the data with I2C functions

    If you create a separate thread, you can use k_sem_give() from the gpio interrupt to wake-up this thread and perform the burst read. Alternatively, you can create a workqueue item to read the sensor. 

    Best regards,

    Vidar

  • Thanks a lot Vidar for the clarification.

    I've a thread anyway, since I have some other heavy duty work to do there so I think I'll go with that. Since I have two ISR GPIO lines, aka two interrupts I'm using k_event_post() and k_event_wait() instead of semaphores. Then I can distinguish which event has occurred. Is there any downside using this; should I go with the semaphore or is it anyway the same procedure in the SDK background (from timing, awake time and battery aspects)

  • Happy to help. Yes, it seems that k_event_* might be more suitable for your situation. The main reason I suggested using a semaphore was its simplicity. However, there are several options available to signal an event from the ISR to your thread.

Related