Measuring pulse time with timers/GPIOTE/PPI on the Arduino Nano 33 BLE sense

I'm trying to measure the pulse ON time of an input signal which has a variable duty cycle with the help of the GPIOTE/PPI/Timer interfaces.

#include <Arduino.h>
#include <hal/nrf_timer.h>
#include <hal/nrf_gpiote.h>
#include <hal/nrf_gpio.h>
#include <hal/nrf_ppi.h>

static uint8_t pin = 5;

void setup() {
  // put your setup code here, to run once:

  // timer init
  NRF_TIMER4->MODE = TIMER_MODE_MODE_Timer;
  NRF_TIMER4->TASKS_CLEAR = 1;
  NRF_TIMER4->PRESCALER = 4;    // 1MHz
  NRF_TIMER4->BITMODE = TIMER_BITMODE_BITMODE_16Bit;     //Set counter to 16 bit resolution

  // gpio init
  NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos | 
                                         GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos | 
                                         digitalPinToPinName(pin) << GPIOTE_CONFIG_PSEL_Pos | 
                                        
 GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos;    // 
ignored when gpio is set to event mode
                                         
  NRF_GPIOTE->CONFIG[1] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos | 
                                     GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos | 
                                     digitalPinToPinName(pin) << GPIOTE_CONFIG_PSEL_Pos | 
                                    
 GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos;    // 
ignored when gpio is set to event mode  

  // ppi init
  // start timer on rising edge
  NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
  NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER4->TASKS_CLEAR;
  NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_TIMER4->TASKS_START;
  NRF_PPI->CHENSET = PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos;
  
  // stop timer on falling edge
  NRF_PPI->CH[1].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[1];
  NRF_PPI->CH[1].TEP = (uint32_t)&NRF_TIMER4->TASKS_CAPTURE[1];
  NRF_PPI->FORK[1].TEP = (uint32_t)&NRF_TIMER4->TASKS_STOP;
  NRF_PPI->CHENSET = PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos;
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("Event 0 status - "); Serial.println(NRF_GPIOTE->EVENTS_IN[0]);
  Serial.print("Event 1 status - "); Serial.println(NRF_GPIOTE->EVENTS_IN[1]);
  Serial.print("CC value - "); Serial.println(NRF_TIMER4->CC[1]);
}

The code works fine for slower signals but when I give a signal in the KHz range I get a lot less timer count that expected. In the above code the timer is ticking at 1us, so for a signal with ON time of 60us, I was expecting 60 ticks, but the NRFTIMER->CC[1] register is showing only 5 ticks.

Is this a limitation from the GPIOTE/PPI peripherals? Has anyone tried this approach?

Welcome to the forum

How do you create the pulses?

I modified your sketch and created pulses using another pin, hardwired it to the input and confirmed the pulse length with an oscilloscope. I created pulses from 11us to 1000us using delayMicroseconds(). The CC value matched the values I measured with my oscilloscope.

I then modified the sketch to use __NOP() for delay and tested pulses from 1 to 100us and the CC values matched again.

Thanks Klaus_K!
I was using another arduino board to generate the pulse on one of it's pins. Turns out the delay function I used to generate the pulse on the board was the problem. Using delayMicroseconds(x) instead of delay(0.00x) seems to have fixed the issue.