Integrating DPPI in Zephyr-based Firmware

Hello, I started looking into the DPPI from NRF5340 series and planning to integrate some functionality into an existing zephyr-based project.
Specifically, I need timer-based GPIO toggles for an application with precise timing requirements. But I planned to start with a simple example with GPIOTE to LED toggling.
As far as I understand there is no support for this functionality at all in zephyr, and one needs to use the NRFX library.
After a bit of experimenting and reading around, I seem to understand that using the NRFX library alongside existing zephyr code is basically not possible. For example, to use NRFX GPIOTE I need to disable the GPIO driver in zephyr (CONFIG_GPIO=n), which would break basically everything already existing. I'm currently trying to build a sample for the nrf5340_audio_dk board and that does not even work, as the board has the npm1100 regulator that depends on zephyr's GPIO.
The few existing examples only cover the NRFX part and do not address the issue of integration of NRFX code in larger projects (https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/boards/nrf/nrfx)

Am I missing something, or could anyone point me to further resources about this? Is there any plan regarding this at all? What's the best approach to get this done? I'm very surprised that users cannot practically use such a fundamental feature with the recommended SDK.

Thank you!

  • Hi,

     

    For example, to use NRFX GPIOTE I need to disable the GPIO driver in zephyr (CONFIG_GPIO=n), which would break basically everything already existing.

    This was true in older versions of NCS, but now that gpio_nrfx (zephyr "gpio" port) uses nrfx_gpiote, this should not break other instances of GPIO usage:

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.4.99-ncs1-2/drivers/gpio/gpio_nrfx.c#L380

     

    If you are using ncs v2.6 or newer, there's a instance that is passed to nrfx_gpiote_* API calls.

    To make the specific sample run, you need to guard the IRQ_CONNECT and nrfx_gpiote_init call with #if !defined(CONFIG_GPIO) to make it run as you'd expect.

    Here's a suggested fix:

    diff --git a/samples/boards/nrf/nrfx/prj.conf b/samples/boards/nrf/nrfx/prj.conf
    index d4f0c29699f..77bc86c294a 100644
    --- a/samples/boards/nrf/nrfx/prj.conf
    +++ b/samples/boards/nrf/nrfx/prj.conf
    @@ -1,3 +1,3 @@
    -CONFIG_GPIO=n
    +CONFIG_GPIO=y
     CONFIG_LOG=y
     CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
    diff --git a/samples/boards/nrf/nrfx/src/main.c b/samples/boards/nrf/nrfx/src/main.c
    index 0643b1c0911..b6835b8b186 100644
    --- a/samples/boards/nrf/nrfx/src/main.c
    +++ b/samples/boards/nrf/nrfx/src/main.c
    @@ -45,7 +45,7 @@ int main(void)
            uint8_t in_channel, out_channel;
            uint8_t ppi_channel;
            const nrfx_gpiote_t gpiote = NRFX_GPIOTE_INSTANCE(GPIOTE_INST);
    -
    +#if !defined(CONFIG_GPIO)
            /* Connect GPIOTE instance IRQ to irq handler */
            IRQ_CONNECT(DT_IRQN(GPIOTE_NODE), DT_IRQ(GPIOTE_NODE, priority), nrfx_isr,
                        NRFX_CONCAT(nrfx_gpiote_, GPIOTE_INST, _irq_handler), 0);
    @@ -58,7 +58,7 @@ int main(void)
                    LOG_ERR("nrfx_gpiote_init error: 0x%08X", err);
                    return 0;
            }
    -
    +#endif
            err = nrfx_gpiote_channel_alloc(&gpiote, &in_channel);
            if (err != NRFX_SUCCESS) {
                    LOG_ERR("Failed to allocate in_channel, error: 0x%08X", err);
    
    

     

    Kind regards,

    Håkon

  • Hello,

    Ok this is actually interesting. I managed to get the basic example running similarly (using a barrier for the initialization with nrfx_gpiote_init_check(&gpiote) and also toggling some LEDs with timers. I wonder how flexible this approach will be with more complex peripherals, but I do not need that for now.

    Thank you!

Related