Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

RTC every second generates TIMER COUNT through PPI

Hello,

This case is a part of a private case. Unfortunately  havent responded for few days. I believe he has days off or something, therefore I am willing to receive help in a public case because of an upcoming deadline.

My setup is pca10040 board, s132, sdk14.2. ble_app_uart example augmented with rtc and pii examples.

My goal is to track real time using lowest possibile energy consumptions while keeping time as precise as possibile. In code I want to increase RTC2 value every second. This generates an event every second and through PPI triggers TIMER COUNT task. I want to read this task and convert it to seconds:minutes:hours:days.

I have read many posts talking about this, unfortunately I am unable to solve this by myself. These are the initializations I use at the moment:

static const nrf_drv_rtc_t rtc2_instance = NRF_DRV_RTC_INSTANCE(2); /**< Declaring an instance of nrf_drv_rtc for RTC. */
static const nrf_drv_timer_t m_timer0 = NRF_DRV_TIMER_INSTANCE(2);
static nrf_ppi_channel_t m_ppi_channel3;

static void timer0_event_handler(nrf_timer_event_t event_type, void * p_context)
{
}

static void ppi_init(void)
{
    uint32_t err_code = NRF_SUCCESS;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel3);
    APP_ERROR_CHECK(err_code);
    
    uint32_t timer_count_count_task_addr    = nrf_drv_timer_task_address_get(&m_timer0, NRF_TIMER_TASK_COUNT);
    
    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel3,
                                          nrf_drv_rtc_event_address_get(&rtc2_instance, NRF_RTC_EVENT_COMPARE_0),
                                          nrf_drv_timer_task_address_get(&m_timer0, NRF_TIMER_TASK_COUNT));
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_fork_assign(m_ppi_channel3,
                                          nrf_drv_rtc_task_address_get(&rtc2_instance, NRF_RTC_TASK_CLEAR));
    APP_ERROR_CHECK(err_code);
    
    // Enable both configured PPI channels
    err_code = nrf_drv_ppi_channel_enable(m_ppi_channel3);
    APP_ERROR_CHECK(err_code);
}

static void timer0_init(void)
{
    // Check TIMER0 configuration for details.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.mode =NRF_TIMER_MODE_LOW_POWER_COUNTER;
    ret_code_t err_code = nrf_drv_timer_init(&m_timer0, &timer_cfg, timer0_event_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_compare(&m_timer0,
                      NRF_TIMER_CC_CHANNEL0,
                      1, // after one second compare happens
                      true);
}

static void rtc_handler_empty(nrf_drv_rtc_int_type_t int_type)
{

}

static void rtc_config(void)
{
    uint32_t err_code;

    //Initialize RTC instance
    nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
    config.prescaler = 4095;
    err_code = nrf_drv_rtc_init(&rtc2_instance, &config, rtc_handler_empty);
    APP_ERROR_CHECK(err_code);

    //nrf_drv_rtc_tick_enable(&rtc2_instance,true);
    err_code = nrf_drv_rtc_cc_set(&rtc2_instance,0,8,false); // 32768/4096 gives 8 ticks per second.
    APP_ERROR_CHECK(err_code);
	//Power on RTC instance
    nrf_drv_rtc_enable(&rtc2_instance);
}

What I perceive is that RTC is ticking every second, however TIMER is not changing. I do not know where exactly to look for TIMER COUNT value. I have tried to capture values like this:

NRF_TIMER2->TASKS_CAPTURE[2] = 1;  // This is asking to capture the current counter into CC[2]
TIMER_COUNTER = NRF_TIMER1->CC[2];   // counter value  at the instant when capture task was triggered is now ready to be read in CC[2]

by putting these lines in main function while(1) loop and in timer0_event_handler, nevertheless this did not worked out.

Please, pin point where I am making mistake here, where should look for increasing TIMER COUNT value and how to make it increase every second. Thank you.

Parents
  • Found the cause. TIMER COUNT register can be reached using this:

    NRF_TIMER2->TASKS_CAPTURE[2] = 1;  // This is asking to capture the current counter into CC[2]
    TIMER_COUNTER = NRF_TIMER1->CC[2];   // counter value  at the instant when capture task was triggered is now ready to be read in CC[2]

    this was not capturing in my main function while(1) because I was using power_manage(); which somehow blocked capturing.

  • There is no reason to do anything in main.  That would just be a waste of power.

    The point of ppi/gpiote is that tasks and task end points can be tied together as you wish. You don't need interrupt handlers and you certainly don't need to poll registers in main.

    You should read up on ppi/gpiote.  There are many, many examples in the devzone also I think Nordic now includes a calendar function that does precisely what you are looking for in the current SDK.

Reply
  • There is no reason to do anything in main.  That would just be a waste of power.

    The point of ppi/gpiote is that tasks and task end points can be tied together as you wish. You don't need interrupt handlers and you certainly don't need to poll registers in main.

    You should read up on ppi/gpiote.  There are many, many examples in the devzone also I think Nordic now includes a calendar function that does precisely what you are looking for in the current SDK.

Children
  • Thanks for pointing out details. I totaly agree with you that it is waste of energy if being used this method in while(1) loop. I was not specific about how I finished up my situation. I just mentioned that I could not see any Increasement in CC register because I used power_manage(); function in the same while(1) loop. At the moment I use GPIOTE event on button push to read the time.

    Anyway, thanks for replying.

    Cheers!

Related