Using I2C & GPIOTE interrupt with soft device enabled

Hi - I wanted to post for the chance it may help others in the future. I'll spare everyone the drama, but I've been stuck on this issue for days and have finally resolved through the help of a few different messages on this forum and my goal here is to bring them together in the context of my resolution.

Background I have an I2C component that separately signals an interrupt when there is data to read (an accelerometer). I have GPIOTE enabled for the interrupt line and I use I2C to then read the data.

I could read the device fine during initialization using I2C and I could receive the interrupt fine, but upon receiving the interrupt I could not reach in and read the data on the device using I2C, it would continually end up in the Hardfault_Handler.

PPI & Soft Device I2C is accomplished by using the TWI and the SDK provides a hardware implementation (twi_hw_master.c) which uses PPI. I have the soft device (S310) enabled and it is documented (shame on me for not reading) in several places that PPI is restricted when the soft device is enabled. Several posts identified this as a potential problem when I discovered I was hard faulting here:

tw_hw_master.c:99 NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TWI1->TASKS_STOP

I found the resolution for this documented here. The resolution was to change all NRF_PPI calls to sd_ppi_* calls after the soft device was enabled.

GPIOTE IRQ Priority One problem solved, but still crashing with hard fault and in the SAME place, but now it was when I was calling sd_ppi_channel_assign(...). It turns out that my problem was described here. The GPIOTE Interrupt handler provided by the SDK in app_gpiote.c was running at HIGH, which was higher than the SVCALL used by sd_ppi_channel_assign and this was creating the hard fault. The fix for this problem was to change app_gpiote.c:161 to a lower priority:


.... Sigh of relief... All is now working. I hope this helps someone and avoids unnecessary grumpiness to one's spouse or co-workers :-)!