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

Simple blinky example with DPPI for NRF9160

Hi

I am trying to include DPPI within the zephyr/sample/basic/blinky example, but im so much confused on these DPPI setups, please help me to understand better.

i have created a sequence after referring bunch of resources that 

step1. initialize and enable the peripherals events and tasks

step2. init ppi channel

step3. allocate ppi channel

step4. get the task and event addresses

step5. assign the channel with these addresses

step6. enable the ppi channel

but when i try to implement these steps in the blinky example i simple struck there, since i cant get and understand any of those steps practically, so please make me clear are these steps are correct?

Please help me with any simple example that explains DPPI module (other than ppi_trace example)

Best Regards

Rajender

  • Hi,

     

    I am trying to include DPPI within the zephyr/sample/basic/blinky example

    It might be easier to start directly on the task at hand wrt. DPPI, because the setup is more-or-less equal for each peripheral, but it still requires a call to each peripheral to enable subscribe/publish options.

    Here's an older example that I wrote a couple of years back (will not compile for newer ncs versions), which can be used to see how it's tied together atleast:

    https://github.com/Rallare/fw-nrfconnect-nrf/blob/nrf9160_samples/samples/nrf9160/nrfx_timed_signal/src/main.c

    The sample will take two inputs and time the active pulse.

     

    Please help me with any simple example that explains DPPI module (other than ppi_trace example)

    Several radio modules use dppi for simplifying logic, like ESB:

    https://github.com/nrfconnect/sdk-nrf/blob/v1.6.1/subsys/esb/esb.c#L563

     

    Kind regards,

    Håkon

  • Hi Hakon,

    i have modified your code little for the newer version compatibility, and its building fine but since i have only one button in my board i have tested only one GPIO input. 

    code:

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <nrf9160.h>
    #include <zephyr.h>
    //#include <misc/printk.h>
    #include <string.h>
    #include <stdlib.h>
    //#include <nrfx_pdm_ns.h>
    #include <nrfx_timer.h>
    #include <nrfx_dppi.h>
    #include <nrfx_gpiote.h>
    #include <hal/nrf_gpiote.h>
    #include <hal/nrf_timer.h>
    
    #include <drivers/gpio.h>
    
    const uint32_t rising_edge_pin = 6;
    //const uint32_t falling_edge_pin = 7;
    #define falling_edge_pin   DT_GPIO_PIN(DT_ALIAS(factoryrestore), gpios)
    #define LED_1 DT_GPIO_PIN(DT_ALIAS(led1), gpios)
    #define LED_2 DT_GPIO_PIN(DT_ALIAS(led2), gpios)
    
    static const nrfx_timer_t timer = NRFX_TIMER_INSTANCE(0);
    
    static void gpiote_event_handler(nrfx_gpiote_pin_t pin,
    				 nrf_gpiote_polarity_t action)
    {
    	if (pin == falling_edge_pin) {
    		/* Read out timer CC register and clear it */
    		uint32_t timer_cc_val = nrf_timer_cc_get(timer.p_reg, 0);
    		printk("Raw timer val: %x\n", timer_cc_val);
    		/* Calculate pulse length, 16M base freq */
    		uint32_t pulse_len_us = (timer_cc_val >> 4) - 1;
    		uint32_t pulse_len_ms = pulse_len_us / 1000;
    		printk("ms: %d\n", pulse_len_ms);
    		printk("us: %d\n", pulse_len_us);
    		nrfx_timer_clear(&timer);
    	} else {
    		printk("Unknown pin. Check your button configuration\n");
    	}
            nrf_gpio_pin_toggle(LED_2);
    }
    
    static void timer_init(void)
    {
    	nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG;
    	timer_config.bit_width = 3;
    	timer_config.frequency = NRF_TIMER_FREQ_16MHz;
    
    	uint32_t err = nrfx_timer_init(&timer, &timer_config, NULL);
    	if (err != NRFX_SUCCESS) {
    		printk("Err :%x\n", err);
    	}
    }
    
    static void dppi_init(void)
    {
    	uint8_t dppi_ch_1, dppi_ch_2;
    	uint32_t err = nrfx_dppi_channel_alloc(&dppi_ch_1);
    	if (err != NRFX_SUCCESS) {
    		printk("Err %d\n", err);
    		return;
    	}
    
    	err = nrfx_dppi_channel_alloc(&dppi_ch_2);
    	if (err != NRFX_SUCCESS) {
    		printk("Err %d\n", err);
    		return;
    	}
    
    	err = nrfx_dppi_channel_enable(dppi_ch_1);
    	if (err != NRFX_SUCCESS) {
    		printk("Err %d\n", err);
    		return;
    	}
    
    	err = nrfx_dppi_channel_enable(dppi_ch_2);
    	if (err != NRFX_SUCCESS) {
    		printk("Err %d\n", err);
    		return;
    	}
    
    	/* Tie it all together */
    	nrf_gpiote_publish_set(NRF_GPIOTE, NRF_GPIOTE_EVENT_IN_0, dppi_ch_1);
    	nrf_gpiote_publish_set(NRF_GPIOTE, NRF_GPIOTE_EVENT_IN_1, dppi_ch_2);
    	nrf_timer_subscribe_set(timer.p_reg, NRF_TIMER_TASK_START, dppi_ch_1);
    	nrf_timer_subscribe_set(timer.p_reg, NRF_TIMER_TASK_STOP, dppi_ch_2);
    	nrf_timer_subscribe_set(timer.p_reg, NRF_TIMER_TASK_CAPTURE0,
    				dppi_ch_2);
    
            nrf_gpiote_subscribe_set(NRF_GPIOTE, NRF_GPIOTE_TASK_SET_0, dppi_ch_2);
    }
    
    static void gpiote_init(void)
    {
    	nrfx_gpiote_in_config_t falling_edge = { 0 };
    	nrfx_gpiote_in_config_t rising_edge = { 0 };
    
    	falling_edge.hi_accuracy = 1;
    	falling_edge.pull = NRF_GPIO_PIN_PULLUP;
    	falling_edge.sense = NRF_GPIOTE_POLARITY_LOTOHI;
    
    	rising_edge.hi_accuracy = 1;
    	rising_edge.pull = NRF_GPIO_PIN_PULLUP;
    	rising_edge.sense = NRF_GPIOTE_POLARITY_HITOLO;
    
    	uint32_t err = nrfx_gpiote_init(0);
    	if (err != NRFX_SUCCESS) {
    		printk("gpiote1 err: %x", err);
    		return;
    	}
    
    	err = nrfx_gpiote_in_init(rising_edge_pin, &rising_edge, NULL);
    	if (err != NRFX_SUCCESS) {
    		printk("gpiote1 err: %x", err);
    		return;
    	}
    
    	err = nrfx_gpiote_in_init(falling_edge_pin, &falling_edge,
    				  gpiote_event_handler);
    	if (err != NRFX_SUCCESS) {
    		printk("gpiote2 err: %x", err);
    		return;
    	}
    
            nrf_gpio_cfg_output(LED_1);
            nrf_gpio_cfg_output(LED_2);
    
            nrfx_gpiote_out_task_enable(LED_1);
    
    	nrfx_gpiote_in_event_enable(falling_edge_pin, 1);
    	nrfx_gpiote_in_event_enable(rising_edge_pin, 1);
    }
    
    static void manual_isr_setup()
    {
    	IRQ_DIRECT_CONNECT(GPIOTE1_IRQn, 0, nrfx_gpiote_irq_handler, 0);
    	irq_enable(GPIOTE1_IRQn);
    }
    
    void main(void)
    {
    	const char *devzone_thread =
    		"https://devzone.nordicsemi.com/"
    		"f/nordic-q-a/51450/timer-0-interface-program";
    	printk("Starting nrfx timed signal program!\n");
    	printk("This sample requires DPPIC to be set as nonsecure\n");
    	printk("See %s for more details!\n", devzone_thread);
    	printk("This sample takes in a signal,"
    	       "and uses two GPIOTE IN channels to time it via TIMER0 and DPPIC\n");
    	timer_init();
    	gpiote_init();
    	dppi_init();
    	manual_isr_setup();
    }

    output i observed is:

    *** Booting Zephyr OS build v2.4.99-ncs2  ***
    Flash regions		Domain		Permissions
    00 00 0x00000 0x08000 	Secure		rwxl
    01 31 0x08000 0x100000 	Non-Secure	rwxl
    
    Non-secure callable region 0 placed in flash region 0 with size 32.
    
    SRAM region		Domain		Permissions
    00 07 0x00000 0x10000 	Secure		rwxl
    08 31 0x10000 0x40000 	Non-Secure	rwxl
    
    Peripheral		Domain		Status
    00 NRF_P0               Non-Secure	OK
    01 NRF_CLOCK            Non-Secure	OK
    02 NRF_RTC0             Non-Secure	OK
    03 NRF_RTC1             Non-Secure	OK
    04 NRF_NVMC             Non-Secure	OK
    05 NRF_UARTE1           Non-Secure	OK
    06 NRF_UARTE2           Secure		SKIP
    07 NRF_TWIM2            Non-Secure	OK
    08 NRF_SPIM3            Non-Secure	OK
    09 NRF_TIMER0           Non-Secure	OK
    10 NRF_TIMER1           Non-Secure	OK
    11 NRF_TIMER2           Non-Secure	OK
    12 NRF_SAADC            Non-Secure	OK
    13 NRF_PWM0             Non-Secure	OK
    14 NRF_PWM1             Non-Secure	OK
    15 NRF_PWM2             Non-Secure	OK
    16 NRF_PWM3             Non-Secure	OK
    17 NRF_WDT              Non-Secure	OK
    18 NRF_IPC              Non-Secure	OK
    19 NRF_VMC              Non-Secure	OK
    20 NRF_FPU              Non-Secure	OK
    21 NRF_EGU1             Non-Secure	OK
    22 NRF_EGU2             Non-Secure	OK
    23 NRF_DPPIC            Non-Secure	OK
    24 NRF_REGULATORS       Non-Secure	OK
    25 NRF_GPIOTE1          Non-Secure	OK
    
    SPM: NS image at 0xc000
    SPM: NS MSP at 0x20011368
    SPM: NS reset vector at 0xd855
    SPM: prepare to jump to Non-Secure image.
    Ê*** Booting Zephyr OS build v2.4.99-ncs2  ***
    Starting nrfx timed signal program!
    This sample requires DPPIC to be set as nonsecure
    See https://devzone.nordicsemi.com/f/nordic-q-a/51450/timer-0-interface-program for more details!
    This sample takes in a signal,and uses two GPIOTE IN channels to time it via TIMER0 and DPPIC
    Raw timer val: 0
    ms: 4294967
    us: -1
    Raw timer val: 0
    ms: 4294967
    us: -1
    

    if i understands correct, since i connected my only button to the falling edge pin, it should  generates event NRF_GPIOTE_EVENT_IN_1 since we have falling_edge.sense = NRF_GPIOTE_POLARITY_LOTOHI, correct?

    but what if we need same event for multiple pins and different task?

    if yes, (i believed) i added one more task to the dppi channel 2, that is NRF_GPIOTE_TASK_SET_0, so i thought this set up will set my GPIO of my LED, but my led is not glowing here, its toggling every time i press button, but here led 2 is toggling i am confusing what happening, please help me

    simply, how i can say that this task is mapped to LED1 or LED2?

    please let me know if i did anything wrong,

    Best Regards

    Rajender.

  • Hi Rajender,

     

    The sample I linked to has a very specific application, meaning it will measure a pulse-width of an input signal, which is connected to the two inputs (for rising and falling edge detection).

     

    If you test it with the buttons, you have to have both buttons activated at once to get a valid measurement.

     

    To initialize an GPIOTE OUT channel, you have to first set it up, similar to this:

    https://github.com/nrfconnect/sdk-zephyr/blob/master/samples/boards/nrf/nrfx/src/main.c#L65-L78

     

    Sorry for not linking to the above sample earlier, it seems to fit your needs a bit better than the one I had!

     

    Kind regards,

    Håkon

     

Related