timer and ppi on nrf connect sdk

hello Nordic

i work with nrf52832, nrf52840 with ncs 1.9

i have 2 issues, is there some example or guid fo using 2 ppi channels for the same gpiote, one timer pullup the gpio and the other timer pulls the same gpio down .. what functions are a must ?  gpioite_channel allocation is a must or ppi_channel_allocations are enough etc.

second issue is that i use three timers in my code and it looks like one of them does not work ok, 

also if i look at pin toggle in ppk power profiler i see that if i light a led while the sampling then i the gpio (pulled up by ppi and pulled down by spi_done handler) sometimes miss some toggling every some time .. any ideas why ?

hope to read from you soon

best regards

Ziv

  • Hi

    Have you remembered to connect the TIMER interrupt using the Zephyr API? IRQ_CONNECT()

    i haven't done that, i also wonder if i can use IRQ_DIRECT_CONNECT if i will need more real time performance? 

    but before that, i m not sure if the instance number i give to the timer dictates which timer i am working with .. meaning if 

    #define CONFIG_ADS8866_CHAIN_XFER_TIMER_INST 2
    static const nrfx_timer_t timer_cycle_done = NRFX_TIMER_INSTANCE(CONFIG_ADS8866_CHAIN_XFER_TIMER_INST);
    
    and initialisation looks like so :

     

    rfx_timer_config_t timer_cfg = {
            .frequency = NRF_TIMER_FREQ_16MHz,
            .mode = NRF_TIMER_MODE_TIMER,
            .bit_width = NRF_TIMER_BIT_WIDTH_32,
            .p_context = handler_context,
        };
    
        int res = nrfx_timer_init(timer, &timer_cfg, ads8866_spi_done_event_handler);
        if (res != NRFX_SUCCESS)
        {
            AUGU_LOG_ERR("error in nrfx_timer_init %x", res);
            return -EINVAL;
        }
        IRQ_DIRECT_CONNECT(TIMER2_IRQn, 0, nrfx_timer_2_irq_handler, 0);

    but i had to try &error to see if it is TIMER1_IRQ / TIMER2_IRQ / TIMER0_IRQ

    is there a way to know in advance, also what if i use instance 4 of a timer ?

    best regards

    Ziv

  • ziv123 said:
    i haven't done that, i also wonder if i can use IRQ_DIRECT_CONNECT if i will need more real time performance? 

    Yes.

    ziv123 said:

    but i had to try &error to see if it is TIMER1_IRQ / TIMER2_IRQ / TIMER0_IRQ

    is there a way to know in advance

    If you set the instance to 2 in the NRFX_TIMER_INSTANCE() macro, this is the instance that will be used. If your question is how you can use the number from the instance definition to select the IRQn object, this can be achieved using the concatenation operator (##), see e.g NRFX_CONCAT_2() macro.

    ziv123 said:
    also what if i use instance 4 of a timer ?

    Then you should use TIMER4_IRQn.

  • i haven't done that, i also wonder if i can use IRQ_DIRECT_CONNECT if i will need more real time performance? 

    Yes.

    what affects can it have on other parts of my application if i use the DIRECT and does it have limitations to take under consideration, because i see that when i config to use direct my spi_done callback (its my indication via gpio) does not seem to work, it like my flash streaming does not work, maybe cause of use of queues and semaphores and other OS things ?

    is it ok to use all 4 channels of a timer 2 for ppi task, 1 for ppi task and the interrupt call and one for the compare event that clears the timer ?

    to be more specific:

     nrfx_timer_config_t timer_cfg = {
            .frequency = NRF_TIMER_FREQ_16MHz,
            .mode = NRF_TIMER_MODE_TIMER,
            .bit_width = NRF_TIMER_BIT_WIDTH_32,
            .p_context = handler_context,
        };
    
        int res = nrfx_timer_init(timer, &timer_cfg, ads8866_spi_done_event_handler);
        if (res != NRFX_SUCCESS)
        {
            AUGU_LOG_ERR("error in nrfx_timer_init %x", res);
            return -EINVAL;
        }
        // IRQ_DIRECT_CONNECT(TIMER2_IRQn, 0, nrfx_timer_2_irq_handler, 0);
        IRQ_CONNECT(TIMER2_IRQn, 0, nrfx_timer_2_irq_handler, NULL, 0);
    
        nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL0, 1, false);
        uint32_t compar_val = nrfx_timer_us_to_ticks(timer, 2);
        nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL1, compar_val, false);
        compar_val = nrfx_timer_us_to_ticks(timer, 14);
        nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL2, compar_val, true);
        compar_val = nrfx_timer_us_to_ticks(timer, 1000000 / sample_freq);
        nrfx_timer_extended_compare(timer, NRF_TIMER_CC_CHANNEL3, compar_val, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK, false);
    
        *time_conv_up = nrfx_timer_compare_event_address_get(timer, NRF_TIMER_CC_CHANNEL0);
        *time_spi_xfer = nrfx_timer_compare_event_address_get(timer, NRF_TIMER_CC_CHANNEL1);

    this is how i set my timer and what i actually see in the picoscop6 is that i have the 'timer_spi_xfer' event which is timed ok (via ppi) but the interrupt handler called by ch2 compare event seems to be late sometimes .. how can i find why and maybe improve it without going to 'DIRECT' ?

    the red line up at beginning of irq handler and down at the end, it can be seen that sometimse it raises closer to the blue lines start (sp_xfer), any idea what can cause this ?

    hope to read you soon

    best regards

    Ziv

  • hi 

    is it possible to use same timer channel , compare event for both triggering the irq_handler and change a gpio via ppi ? 

    if so, how should i configure a gpio to both SET and CLR task (one compare event will pull up and then mentioned compare event on a different channel will pull down the gpio, both via ppi ) ?

    hope to read you soon

    best regards

    Ziv

  • ziv123 said:
    what affects can it have on other parts of my application if i use the DIRECT and does it have limitations to take under consideration, because i see that when i config to use direct my spi_done callback (its my indication via gpio) does not seem to work, it like my flash streaming does not work, maybe cause of use of queues and semaphores and other OS things ?

    The differences are listed in the API documentation:

    This type of interrupt currently has a few limitations compared to normal Zephyr interrupts:

    • No parameters are passed to the ISR.

    • No stack switch is done, the ISR will run on the interrupted context’s stack, unless the architecture automatically does the stack switch in HW.

    • Interrupt locking state is unchanged from how the HW sets it when the ISR runs. On arches that enter ISRs with interrupts locked, they will remain locked.

    • Scheduling decisions are now optional, controlled by the return value of ISRs implemented with the ISR_DIRECT_DECLARE() macro

    • The call into the OS to exit power management idle state is now optional. Normal interrupts always do this before the ISR is run, but when it runs is now controlled by the placement of a ISR_DIRECT_PM() macro, or omitted entirely.

    ziv123 said:
    is it ok to use all 4 channels of a timer 2 for ppi task, 1 for ppi task and the interrupt call and one for the compare event that clears the timer ?

    Yes, all the COMPARE channels can be used, that is the reason they are implemented.

    ziv123 said:
    this is how i set my timer and what i actually see in the picoscop6 is that i have the 'timer_spi_xfer' event which is timed ok (via ppi) but the interrupt handler called by ch2 compare event seems to be late sometimes .. how can i find why and maybe improve it without going to 'DIRECT' ?

    The execution of the handler will depend on other interrupts and priority of the tasks in your application. If this handler is high priority, you should try to increase its priority.

    The PPI signals are handled purely in HW, and are not affected by CPU usage by other tasks.

    ziv123 said:
    the red line up at beginning of irq handler and down at the end, it can be seen that sometimse it raises closer to the blue lines start (sp_xfer), any idea what can cause this ?

    Likely some other higher/equal priority task in the application is blocking the execution of the handler.

    ziv123 said:
    is it possible to use same timer channel , compare event for both triggering the irq_handler and change a gpio via ppi ? 

    Yes, these are different HW concepts, and not mutually exclusive. The COMPARE event will send a HW signal on any connected PPI channels, and also signal the interrupt if that is enabled.

    ziv123 said:
    if so, how should i configure a gpio to both SET and CLR task (one compare event will pull up and then mentioned compare event on a different channel will pull down the gpio, both via ppi ) ?

    You need to use separate PPI channels for SET and CLR to achieve this. On PPI channel connected from COMPARE event to SET task and another PPI channel connected from COMPARE event to CLR task.

Related