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

how to drive multiple timer interrupts in nrf52832?

Hello,

I want to use multiple timer interrupts, want to fetch values from 3 analog pins on every 20secs and then average three collected values at every 60 sec. so i would like to generate two timer interrupts. One at every 20secs, to collect the values and other at every 60sec to average that values. I am using nrf sdk 15.0.0 .

Also, i want to know what is exactly happening in the timer example: Can you explain the use nrf_drv_timer_extended_compare API. 

I tried to modify the timer example but it did not work, it is giving some timer instance id error. 

Obviously i did not understand the example and hence can not debug my code. 

Can you please help me understand the timer interrupts concept. 

Thanks and Regards!

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_drv_timer.h"
#include "bsp.h"
#include "app_error.h"

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);
const nrf_drv_timer_t TIMER_LED1 = NRF_DRV_TIMER_INSTANCE(1);

static volatile uint32_t m_counter;

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    static uint32_t i;
    uint32_t led_to_invert = ((i++) % LEDS_NUMBER);

    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            bsp_board_led_invert(1);
            break;

        default:
            //Do nothing.
            break;
    }
}


void timer_led_event_handler1(nrf_timer_event_t event_type, void* p_context)
{
               static uint32_t i;
    uint32_t led_to_invert = ((i++) % LEDS_NUMBER);

    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
            bsp_board_led_invert(2);
            break;

        default:
            //Do nothing.
            break;
    }
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t time_ms = 100; //Time(in miliseconds) between consecutive compare events.
    uint32_t time_ms1 = 200;
    uint32_t time_ticks;
      uint32_t time_ticks1;
    uint32_t err_code = NRF_SUCCESS;

    //Configure all leds on board.
    bsp_board_init(BSP_INIT_LEDS);

    //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
     nrf_drv_timer_config_t timer_cfg1 = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer_led_event_handler);
    APP_ERROR_CHECK(err_code);
     err_code = nrf_drv_timer_init(&TIMER_LED1, &timer_cfg1, timer_led_event_handler1);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_LED, time_ms);
     time_ticks1 = nrf_drv_timer_ms_to_ticks(&TIMER_LED1, time_ms1);

    nrf_drv_timer_extended_compare(
         &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

           nrf_drv_timer_extended_compare(
         &TIMER_LED1, NRF_TIMER_CC_CHANNEL0, time_ticks1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_LED);
     nrf_drv_timer_enable(&TIMER_LED1);

    while (1)
    {
        __WFI();
    }
}

Parents
  • Hi,

    I would suggest that you use the timer library (app timer) instead, since you are having a long delay between each interrupt. It uses a single RTC instance to realize an arbitrary number of timer instances in a simple and power efficient manner, and should be perfect in this case.

  • void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_timer_config_t timer_config = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_config.frequency = NRF_TIMER_FREQ_31250Hz;
        err_code = nrf_drv_timer_init(&m_timer, &timer_config, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event */
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer,SAADC_SAMPLE_RATE);
        nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer, NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
        
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_event_addr);
        APP_ERROR_CHECK(err_code);
    }

    I would still really like to understand this attached function. It uses the timer API's which i could not find good documentation for.  

    Would really appreciate an explanation of this function .

    Thanks!

  • Hi,

    This function saadc_sampling_event_init() function you have pasted captures several important concepts, so it is no wonder you find it complex if you do not have much previous experience with nRF5 devices.

    I can start by explaining the timer driver functions at a high level. The nrf_drv_timer_extended_compare() function (implemented by nrfx_timer_extended_compare() in the latest SDK 15) does two things:

    1. Configures a short(cut) given as a parameter to the function. This is a HW connection that links a EVENT to a TASK. In the timer example, you can see it uses NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, which means that whenever there is a COMPARE0 event this will trigger the CLEAR task, resetting the timer value to 0.
    2. Calls the nrfx_timer_compare(), which is the same as calling nrf_drv_timer_compare() directly. This sets up a timer CC register, so that there will be an event when the timer value becomes equal to the CC register. You can also optionally trigger an interrupt. The event can be connected to other peripherals using PPI, as is the case in the saadc_sampling_event_init() function.

    I recommend you look at the product specification for the TIMER documentation and driver implementation if you need more details on the timer.

    In the function above, PPI is used to connect the timer EVENT to the SAADC sample task using PPI. You can see that nrf_drv_timer_compare_event_address_get() is used to get the EVENT address for the timer, and nrf_drv_saadc_sample_task_get() is used to get the TASK address of the SAADC. Then they are connected using PPI, by first allocating a PPI channel using nrf_drv_ppi_channel_alloc() and hooking the TASK and EVENT end points together using nrf_drv_ppi_channel_assign().

    I recommend reading the Peripheral interface chapter in the product specification to understand the details about how peripherals interconnects.

  • Hi Einar,

    Do you have any example that uses app timer in SDK 15.0.0 ? I am pretty clear on how to use app timer API's but i don't know what all drivers and libraries are needed in the project before i can start using its API's. The tutorial that i found was for old SDK. Just let me know what all files should be included and where ? 

    Thanks,

Reply Children
Related