This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF52840 input interrupt real-time response & output line SDK toggling time performance

Hi,

We have been developing our system around nRF52840 and we are now looking closer into the real-time performance of the MCU & SDK. The scenario is simple: a signal ‘YELLOW’ is detected at pin 1.13 and the corresponding interrupt service routine toggles an LED ‘GREEN’.

  1. The input ISR starts executing only 20.3usecs after the external event takes place. Given the clock is at 32MHz, 20.3usecs is more than 600 instruction executions (please correct me if my calculations are wrong). Is this the expected timing performance? Is there a way to optimise the response time?
  2. Also, toggling the output line using NRF SDK takes 3.50usecs, while toggling the same line using OUTSET/CLR register directly takes less than 300nsecs. Again, is there a way to optimise the performance?

(SDK 15.0.0, eclipse IDE, no SoftDevice, Windows)

I would like to achieve the best performance possible without skipping or heavily modifying the Nordic SDK, since that would make very difficult to upgrade to future SDK releases.

Oscilloscope screenshots and code follow.

Toggling pin via SDK:

Toggling pin via register access:

The pins:

#define PULSEIN     NRF_GPIO_PIN_MAP(1, 13)
#define LED         NRF_GPIO_PIN_MAP(0, 10)

The configuration:

nrfx_gpiote_out_config_t OutLowConfig = NRFX_GPIOTE_CONFIG_OUT_SIMPLE(false);
if (nrfx_gpiote_out_init(LED, &OutLowConfig) != SUCCESS)
	NRF_LOG_ERROR("Failed to initialise Debug LEDs.");

nrfx_gpiote_in_config_t inter_config= NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
inter_config.pull = NRF_GPIO_PIN_PULLDOWN;
if (nrfx_gpiote_in_init(PULSEIN, &inter_config, AnISR) != SUCCESS)
	NRF_LOG_ERROR("Failed to initialise input interrupt.");

The input interrupt service routine:

static void AnIsrTogglingViaSdk(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
	nrfx_gpiote_out_set(LED);
	nrfx_gpiote_out_clear(LED);
}

static void AnIsrTogglingViaRegisters(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
	NRF_P0->OUTSET = 1 << 10;
	NRF_P0->OUTCLR = 1 << 10;
}

Thank you in advance,

Christos

Parents
    1. Yes, you need to enable Constant Latency, see Sub power modes
      NRF_POWER->TASK_CONSTLAT = 1;


    2. Well, you can use GPIOTE if you're gonna control a GPIO based on a HW event, like a GPIO toggling, SPI transfer, SAADC conversion, TIMER compare event, etc.

      Other than that you'll want to stick to the GPIO HAL if you want to optimize for low latency. Try the nrf_gpio_pin_set and nrf_gpio_pin_clear

      The drivers checks for all sorts of states before actually doing anything in order not to break itself or other drivers and libraries. It is also been thuroughly tested, which is why it's a good idea to use it, but I understand that the CPU overhead can be too much for some use-cases.  
Reply
    1. Yes, you need to enable Constant Latency, see Sub power modes
      NRF_POWER->TASK_CONSTLAT = 1;


    2. Well, you can use GPIOTE if you're gonna control a GPIO based on a HW event, like a GPIO toggling, SPI transfer, SAADC conversion, TIMER compare event, etc.

      Other than that you'll want to stick to the GPIO HAL if you want to optimize for low latency. Try the nrf_gpio_pin_set and nrf_gpio_pin_clear

      The drivers checks for all sorts of states before actually doing anything in order not to break itself or other drivers and libraries. It is also been thuroughly tested, which is why it's a good idea to use it, but I understand that the CPU overhead can be too much for some use-cases.  
Children
No Data
Related