Higher Priority for GPIOTE Interrupt.

I have an IoT project that reads data from a proprietary device via an I2c SBIffer.
The device consists of a controller and a small display, which are connected via an I2C bus.

I'm using a   XIAO-nrF52840 from Seed-Studio
My IDE is Segger Embedded-Studio 5-70a with nRF5_SDK_17.1.0 and Softdevice 140
I started with ble_app_blinky example from the SDK-folder:
.\Nordic Semiconductor\nRF5_SDK_17.1.0_ddde560\examples\ble_peripheral\ble_app_blinky\pca10056\s140\ses

The I2C sniffer works perfectly as long as I don't activate the BLE stack and disable the RTC1 interrupt.
But now I want to send my data (as a BLE-peripheral) via Bluetooth, but when activating the BLE-Stack my sniffer is no longer working.
I discovered that the BLE stack, along with Timer0 and RTC1, is running at priority level 0 and the SDK does not allow other interrupts running with priority = 0.
My I2C sniffer uses the GPIO interrupt to evaluate the edges of the SDA and SCL signals. The I2C communication runs at approximately 83 kHz, and I need the shortest possible interrupt latency to capture the signals correctly.
On the other hand, only a very short interrupt execution time (< 3us) is required.


Therefore, I tried a hack without permission of the SDK and  moved the interrupts use by the BLE-stack to priority level 1.
Hoping that the SDK will tolerate my sacrilege.

NVIC_SetPriority (RADIO_IRQn,1);
NVIC_SetPriority (TIMER0_IRQn,1);
NVIC_SetPriority (RTC0_IRQn,1);


And yes the BLE communication is still working :-)
Now I tried a test with a timer-3 interrupt, which I programmed without the SDK using direct register access and set the timer interrupt priority to level 0.
The interrupt service routine does nothing except clearing the interrupt event.
void TIMER3_IRQHandler(void)
{
  nrf_timer->EVENTS_COMPARE[0] = 0; 
}


Unfortunately, I get an application error as soon as the timer interrupt is executet.
<error> app: SOFTDEVICE: INVALID MEMORY ACCESS


- Is there perhaps still a small chance of getting my interrupt to work with priority 0?
- What triggers the error? Or how does the SDK manage to figure out that someone is above it?
- Do I have a better chance if I use the NRF-Connect SDK?

Maybe I'll have a second chance.
The I2c communication has a polling sequence of 10ms.


I could try switching between I2C sniffer and BLE communication.
Reading an I2C packet takes about 1-2 ms; the remaining time could be used by the BLE stack.
Simply disabling the BLE interrupt for 1-2 ms does not work, but perhaps there is an SDK function to stop BLE for a short time.

If all of that is not possible, unfortunately I have no other option than to provide another controller for the I2C sniffer and connect it to the NRF chip via a serial interface for example.

BTW 
As far as I know, there is no chance to create an I2C sniffer using the CPU's I2C (TWI) controller.

Parents
  • Since my attempt is doomed to failure and a minimal interrupt delay is not possible on the nRF5380 , I went over to ESP32.S3. Unless someone has another idea regarding my second question above, how one might be able to pause the BLE stack for some ms.There might be also the option of using a Nordic Dual Core (nRF5340). Unfortunately, there isn't a compact board available for it yet. The ESP32 solution is now working perfectly.

Reply
  • Since my attempt is doomed to failure and a minimal interrupt delay is not possible on the nRF5380 , I went over to ESP32.S3. Unless someone has another idea regarding my second question above, how one might be able to pause the BLE stack for some ms.There might be also the option of using a Nordic Dual Core (nRF5340). Unfortunately, there isn't a compact board available for it yet. The ESP32 solution is now working perfectly.

Children
  • There are two other ways to achieve the goals. Both work around the fact that the Softdevice will eclipse any interrupt code for periods of time.

    Serial protocols such as i2c and SENT can be decoded by latching edge transition times into multiple Timer CC registers and with the result processed periodically; the more Timers and Timer CC registers are available the longer the SD eclipse interval can be without data loss. I wrote some code to do this for SENT (Single Edge Nibble Transfer) used in modern vehicles which works well; SENT is 1-wire rather than 2-wire, but the principle is the same for i2c/twi except twice the number of CC registers would be required for a given number of edges. There is a rather long post which will provide timing details:

     sent-protocol-based-sensor-configuration-with-nrf

    The other option is to leverage a sampling peripheral which has DMA-into-buffer availability, unaffected by the SD, for example the SAADC. Not particularly efficient, but ok for sniffing slow periodic messages.

Related