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

nRF9160 > Count pulse on GPIO

Dear Team,

what is the way to do it in Zephyr? 

I have a signal up-to 10kHz, what is the best way to keep the counter in the background?

Thank you and best

Oleh

Parents
  • Hi.

    You can use Zephyr's GPIO driver to configure interrupts. 

    Have a look at the documentation here.

    Best regards,

    Didrik

  • Hi Didrik,

    thank you, I'm new to Zephyr so trying to map my nrf knowledge to zephyr Slight smile

    To complement and test the counter on gpio, I thought to put the second DevKit board into generation mode. Could you please point on the right track with how can the generation on-off be done in background on Zephyr?

    thanks & best

    Oleh

  • The ppi_trace sample worked for me.

    I did not get any build errors.

    However, I did have to change the pins used to 10, 11, and 12. You can do this in the Kconfig file in the sample, or by adding the relevant configurations in the prj.conf file.

    Also, the sample should be built as a secure application (use target nrf9160_pca10090, no ns).

  • aha! that was the missing part, thank you!

    I will try for the Secure board. 

    In order to use DPPI on the NonSecure, would this be sufficient:

    PERIPH("NRF_DPPI", NRF_DPPIC_NS, CONFIG_SPM_NRF_DPPIC_NS), // adding to spm.c in the periph_cfg periph[]

    And also: 

     if (IS_ENABLED(CONFIG_SPM_NRF_GPIOTE1_NS)) {
      /* Configure DPPI to be Non-Secure */
      NRF_SPU->DPPI[0].PERM = 0;
     }

    thank you!

  • Almost.

    In addition to

    PERPIH("NRF_DPPI", NRF_DPPIC_NS, CONFIG_SPM_NRF_DPPIC_NS),
    in spm.c:304 and

    if (IS_ENABLED(CONFIG_SPM_NRF_GPIOTE1_NS)) {
        NRF_SPU->DPPI[0].PERM = 0;
    }
    in spm.c:326

    I also had to add

    PERIPH("NRF_RTC0", NRF_RTC0, CONFIG_SPM_NRF_RTC0_NS),
    in spm.c:305,

    config SPM_NRF_DPPIC_NS
    	bool "DPPI is Non-Secure"
    	default y
    
    config SPM_NRF_RTC0_NS
    	bool "RTC0 is Non-Secure"
    	default y
    in ncs/nrf/subsys/spm/Kconfig:180, and

    CONFIG_PPI_TRACE_PIN_RTC_COMPARE_EVT=10
    CONFIG_PPI_TRACE_PIN_RTC_TICK_EVT=11
    CONFIG_PPI_TRACE_PIN_LFCLOCK_STARTED_EVT=12
    in prj.conf

  • Hi Didrik, thanks! that was to make the ppi_trace to work. 

    could you please help on wiring Counter and Timer to get it with DPPI as here: https://devzone.nordicsemi.com/f/nordic-q-a/9036/measuring-input-gpio-pin-frequency-with-soft-device-running ?

  • am I on the right way?

    static void timer_init()
    {
     NRF_TIMER1_NS->TASKS_STOP = 1;
     NRF_TIMER1_NS->MODE = TIMER_MODE_MODE_Timer;
     NRF_TIMER1_NS->PRESCALER = 8; // Fhck / 2^8 
     NRF_TIMER1_NS->CC[0] = 62500; // 62500 - 1s
     
     NRF_TIMER1_NS->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos); 
     
     NRF_TIMER1_NS->TASKS_CLEAR = 1;
     NRF_TIMER1_NS->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
     
     NRF_TIMER1_NS->EVENTS_COMPARE[0] = 0;
    }
    
    static void counter_init()
    {
     NRF_TIMER2_NS->TASKS_STOP = 1; 
     NRF_TIMER2_NS->MODE = TIMER_MODE_MODE_Counter;
     NRF_TIMER2_NS->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
     NRF_TIMER2_NS->TASKS_CLEAR = 1;
     NRF_TIMER2_NS->EVENTS_COMPARE[0] = 0;
    }
    
    #define SENSE_PIN 13
    static void gpiote_init(uint32_t pin)
    {
     NRF_GPIOTE1_NS->CONFIG[0]  =  0x01 << 0;         // MODE: Event
     NRF_GPIOTE1_NS->CONFIG[0]  |=  SENSE_PIN << 8;       // Pin number
     NRF_GPIOTE1_NS->CONFIG[0]  |=  NRF_GPIOTE_POLARITY_LOTOHI << 16;  // Event rising edge  
    }
    
    static void ppi_timer_stop_counter_init()
    {
     //NRF_DPPIC_NS->CHEN |= 1 << 0;
     //*(&(NRF_DPPIC_NS->CH0_EEP)) = (uint32_t)&NRF_TIMER1_NS->EVENTS_COMPARE[0];
     //*(&(NRF_DPPIC_NS->CH0_TEP)) = (uint32_t)&NRF_TIMER2_NS->TASKS_STOP;
     //NRF_DPPIC_NS->CHENSET |= 1 << 0;
     
     #define EVT_IX_TIMER1__COMPARE 1
     #define TSK_IX_TIMER2__STOP_COUNTER 1
        // Configure GPIOTE Index 0 to be an Event -> 
        nrf_gpiote_event_configure(EVT_IX_TIMER1__COMPARE, nrf_timer_event_address_get(NRF_TIMER1_NS, NRF_TIMER_EVENT_COMPARE_1) ...);
        // Configure GPIOTE Index 1 to be a Task -> 
        nrf_gpiote_task_configure(TSK_IX_TIMER2__STOP_COUNTER, nrf_timer_event_address_get(NRF_TIMER2_NS, NRF_TIMER_TASK_COUNT) ...);
        // Index 0 will Publish on DPPI Channel 0 
        nrf_gpiote_publish_set(NRF_GPIOTE_EVENTS_IN_0, DPPI_CHANNEL);
        // Index 1 will Subscribe on DPPI Channel 0 
        nrf_gpiote_subscribe_set(NRF_GPIOTE_TASKS_OUT_1, DPPI_CHANNEL);
        // Enable Publish and Subscribe 
        nrf_gpiote_event_enable(EVT_IX_TIMER1__COMPARE);
        nrf_gpiote_task_enable(TSK_IX_TIMER2__STOP_COUNTER);
        // Enable DPPI Channel 
        nrf_dppi_channels_enable(NRF_DPPIC, DPPI_BIT_SET(DPPI_CHANNEL));
    }
    
    static void ppi_gpiote_counter_init()
    {
     NRF_DPPIC_NS->CHEN |= 1 << 1;
     *(&(NRF_DPPIC_NS->CH1_EEP)) = (uint32_t)&NRF_GPIOTE1_NS->EVENTS_IN[0];
     *(&(NRF_DPPIC_NS->CH1_TEP)) = (uint32_t)&NRF_TIMER2_NS->TASKS_COUNT;
     NRF_DPPIC_NS->CHENSET |= 1 << 1;
    }

Reply
  • am I on the right way?

    static void timer_init()
    {
     NRF_TIMER1_NS->TASKS_STOP = 1;
     NRF_TIMER1_NS->MODE = TIMER_MODE_MODE_Timer;
     NRF_TIMER1_NS->PRESCALER = 8; // Fhck / 2^8 
     NRF_TIMER1_NS->CC[0] = 62500; // 62500 - 1s
     
     NRF_TIMER1_NS->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos); 
     
     NRF_TIMER1_NS->TASKS_CLEAR = 1;
     NRF_TIMER1_NS->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
     
     NRF_TIMER1_NS->EVENTS_COMPARE[0] = 0;
    }
    
    static void counter_init()
    {
     NRF_TIMER2_NS->TASKS_STOP = 1; 
     NRF_TIMER2_NS->MODE = TIMER_MODE_MODE_Counter;
     NRF_TIMER2_NS->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
     NRF_TIMER2_NS->TASKS_CLEAR = 1;
     NRF_TIMER2_NS->EVENTS_COMPARE[0] = 0;
    }
    
    #define SENSE_PIN 13
    static void gpiote_init(uint32_t pin)
    {
     NRF_GPIOTE1_NS->CONFIG[0]  =  0x01 << 0;         // MODE: Event
     NRF_GPIOTE1_NS->CONFIG[0]  |=  SENSE_PIN << 8;       // Pin number
     NRF_GPIOTE1_NS->CONFIG[0]  |=  NRF_GPIOTE_POLARITY_LOTOHI << 16;  // Event rising edge  
    }
    
    static void ppi_timer_stop_counter_init()
    {
     //NRF_DPPIC_NS->CHEN |= 1 << 0;
     //*(&(NRF_DPPIC_NS->CH0_EEP)) = (uint32_t)&NRF_TIMER1_NS->EVENTS_COMPARE[0];
     //*(&(NRF_DPPIC_NS->CH0_TEP)) = (uint32_t)&NRF_TIMER2_NS->TASKS_STOP;
     //NRF_DPPIC_NS->CHENSET |= 1 << 0;
     
     #define EVT_IX_TIMER1__COMPARE 1
     #define TSK_IX_TIMER2__STOP_COUNTER 1
        // Configure GPIOTE Index 0 to be an Event -> 
        nrf_gpiote_event_configure(EVT_IX_TIMER1__COMPARE, nrf_timer_event_address_get(NRF_TIMER1_NS, NRF_TIMER_EVENT_COMPARE_1) ...);
        // Configure GPIOTE Index 1 to be a Task -> 
        nrf_gpiote_task_configure(TSK_IX_TIMER2__STOP_COUNTER, nrf_timer_event_address_get(NRF_TIMER2_NS, NRF_TIMER_TASK_COUNT) ...);
        // Index 0 will Publish on DPPI Channel 0 
        nrf_gpiote_publish_set(NRF_GPIOTE_EVENTS_IN_0, DPPI_CHANNEL);
        // Index 1 will Subscribe on DPPI Channel 0 
        nrf_gpiote_subscribe_set(NRF_GPIOTE_TASKS_OUT_1, DPPI_CHANNEL);
        // Enable Publish and Subscribe 
        nrf_gpiote_event_enable(EVT_IX_TIMER1__COMPARE);
        nrf_gpiote_task_enable(TSK_IX_TIMER2__STOP_COUNTER);
        // Enable DPPI Channel 
        nrf_dppi_channels_enable(NRF_DPPIC, DPPI_BIT_SET(DPPI_CHANNEL));
    }
    
    static void ppi_gpiote_counter_init()
    {
     NRF_DPPIC_NS->CHEN |= 1 << 1;
     *(&(NRF_DPPIC_NS->CH1_EEP)) = (uint32_t)&NRF_GPIOTE1_NS->EVENTS_IN[0];
     *(&(NRF_DPPIC_NS->CH1_TEP)) = (uint32_t)&NRF_TIMER2_NS->TASKS_COUNT;
     NRF_DPPIC_NS->CHENSET |= 1 << 1;
    }

Children
  • Hi, and apologies for the late answer.

    I believe that most of the code you posted should work, but especially the parts concerning PPI would not work due to differences between PPI and DPPI.

    I was able to port an example written by  for another case. The sample is made to measure much higher frequencies than what you have, so you might want to edit some of the timer configurations in main().

    dppi_frequency.zip

    To make the sample compile, you must also add

    #define GPIOTE_IRQn GPIOTE0_IRQn

    in ncs/zephyr/ext/hal/nordic/nrfx_config_nrf9160.h, on line 200.

    Also, you must configure the DPPI peripheral as non-secure as done in a previous comment.

    A pre-compiled hex file is included for your convenience.

    Best regards,

    Didrik

  • thank you, now I am trying to make it working on the latest ncs git... but getting errors...

     is there anything I have to change?

    ***** Booting Zephyr OS build v1.14.99-ncs3-snapshot2-2647-gd6e67554cfeb *****
    starting application...
    starting init gpiote...
    prepare time 1 cfg...
    uninit time 1...
    init time 1...
    prepare time 2 cfg...
    uninit time 2...
    init time 2...
    nrfx_timer_ms_to_ticks...
    nrfx_timer_extended_compare...
    gpiote_setup...
    gpiote_setup...
    gpiote_evt_addr: 0x5000d100
    NRF_GPIOTE_EVENTS_IN_0: 0x00000100
    NRF_GPIOTE1_NS: 0x40031000
    gpiote_evt_addr - NRF_GPIOTE0_S: 0x0ffdc100
    [00:00:00.069,274] <err> os: ***** BUS FAULT *****
    [00:00:00.069,274] <err> os:   Precise data bus error
    [00:00:00.069,274] <err> os:   BFAR Address: 0x40010088
    [00:00:00.069,305] <err> os: r0/a1:  0x00000000  r1/a2:  0x00000001  r2/a3:  0x80000000
    [00:00:00.069,305] <err> os: r3/a4:  0x40010088 r12/ip:  0x00000030 r14/lr:  0x0000061f
    [00:00:00.069,305] <err> os:  xpsr:  0x29000000
    [00:00:00.069,305] <err> os: Faulting instruction address (r15/pc): 0x00000632
    [00:00:00.069,335] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception
    [00:00:00.069,335] <err> os: Current thread: 0x20000274 (unknown)
    [00:00:00.140,075] <err> os: Halting system

  • Hi.

    A pull request for a sample demonstrating how to use the nrfx drivers in Zephyr was just opened.

    Hopefully, it is able to help you.

    https://github.com/zephyrproject-rtos/zephyr/pull/20089/files

    Best regards,

    Didrik

  • Hello and thank you!

    short question: what is the best way to suspend / resume the ppi in this sample? 

    and how to safely reset counters?

  • Hi, and sorry for the late reply.

    For resetting counters, I would use the nrfx_timer_clear function.

    For suspending/resuming DPPI, you would have to either stop the events from being generated, not publish the events, or subscribe to them (or all at once).

Related