GPIOTE with Arduino Nano 33 BLE SENSE

I intend to use hardware timing for an Arduino project. The final goal is to use a timer to trigger TWI-reads from a sensor. The nRF52 uC has a nice interface called PPI (programmable peripheral interconnect) that allows to do all of this in hardware.

I have already been able to set up a timer to blink an LED using NRF_TIMER1 plus the Arduino digitalWrite(…) function inside an interrupt service routine (i.e., not via PPI). It was not easy but reading the Nordic and Arduino forums and some trial and error did the job.

My next step is to create a GPIOTE task to blink that LED. I have tried hard by I cannot get it to work. I have reduced my code to the bare minimum getting rid of anything that I thought could interfere but still no luck. Can anyone see what I’m doing wrong? I expect that the following code will turn on the red LED (but it does not):

#include <Arduino.h>

void setup() {
  // clear any previous GPIOTE config:
  unsigned char i;
  for (i=0; i<8; i++) {
      NRF_GPIOTE->CONFIG[i] = 0;

  // configure task [0]:
  NRF_GPIOTE->CONFIG[0] = (0 << GPIOTE_CONFIG_OUTINIT_Pos) |                                    // initial state of pin
                          (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos) |       // operation to do
                          (LEDR << GPIOTE_CONFIG_PSEL_Pos) |                                    // pin associated with this task
                          (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos);                  // event or task mode

  // LEDR should already be initialized to LOW (i.e. ON). Do it again here:

void loop() {

I usually develop using PlatformIO, but to exclude that as well I compiled and uploaded this code

  • using Arduino IDE 1.8.12
  • to Arduino NANO 33 BLE SENSE
  • running on MacOS 10.15.5 (don’t think that matters)

I have verified that the config is actually written and nobody (Arduino / mbed OS) is overwriting it. Reading the CONFIG register back for verification inside loop() returns the expected value.
I have verified that those constants (GPIOTE_CONFIG*) actually have the values specified in the nRF52840 Product Specification v1.1. I also checked the address of the register (NRF_GPIOTE->CONFIG[0]). Therefore, I believe that I am writing the right value to the right place.

I have not been able to verify the pin number directly. But as “LEDR” works flawlessly in “normal” Arduino code (digitalWrite(…)) I think it should be correct.

I have also tried using the higher level interface called NRFX_GPIOTE (note the additional “X”) without success.