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

Using RTC in Mesh Application

Hi,

I'm trying to implement a slow timer which is supposed to be triggered about every 30 minutes or even less frequent, but I'm kind of clueless how to solve this issue.

I tried implementing the app_timer first, as described in this post: https://devzone.nordicsemi.com/nordic/short-range-guides/b/software-development-kit/posts/application-timer-tutorial

but unfortunately I did not find a function or parameter to change the frequency or prescaler of this timer, so for this use-case the app_timer was not the best choice.

(Unless I would catch every interrupt and count them up, which I like to avoid)

As this is a low power application, I want to create as few interrupts as possible and after I read that you can use the RTC to create timers up to 8 hours, I tried to implement that.

Now, I'm basically left with 2 questions:

  • Is there something I need to pay attention to? Like for example messing with the clock configuration. (And I already figured you cannot use instance 0 of the RTC, with this example)

  • And how do I set up the compare interrupt, in a way, that it triggers repeatably?

Here are the steps I've taken so far:

My code is based on the LPN Example from the Mesh SDK.

I attempted to implement the RTC as demonstrated in the SDK\examples\peripheral\rtc example.

static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "COMPARE0 match\n");
    }
    else if (int_type == NRF_DRV_RTC_INT_TICK)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "TICK event\n");
    }
}

static void lfclk_config(void)
{
    ret_code_t err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_clock_lfclk_request(NULL);
}

/** @brief Function initialization and configuration of RTC driver instance.
 */
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(&rtc, &config, rtc_handler);
    APP_ERROR_CHECK(err_code);

    //Enable tick event & interrupt
    nrf_drv_rtc_tick_enable(&rtc,true);

    //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
    err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
    APP_ERROR_CHECK(err_code);

    //Power on RTC instance
    nrf_drv_rtc_enable(&rtc);
}

int main(void)
{

    initialize();
    start();

    
    // lfclk_config(); <- causing Error 133
    rtc_config();
    
    for (;;)
    {
        (void)sd_app_evt_wait();
    }
}

On the first run I got Mesh error 133, wich I think is caused because the function initialize() is probably using the clock somewhere else.

Therefore I used the rtc_config() without calling lfclk_config() first, which seems to work.

It is working in the sense, that ticks is called permanently, but compare is only called once after a certain number of ticks (which makes sense, I just expected it to trigger again after a wrap around of the RTC).

This behaves the same, even when I'm trying to set up a new compare in the rtc_handler.

Since I'm not sure if that is even the proper way of doing things, it would be great to get some advice: How I can start/stop and modify the RTC and if it's fine ignoring the set up of the clock (in this example), or how to do that correctly.

Sincerely,

Heiner

  • Hi Heiner. 

    Just a quick question before starting to look closer into this; 

    Which version of the nRF5 SDK for Mesh are you working with?

    Best regards, 
    Joakim

  • Hi Joakim,

    I'm currently using Version 3.1.0

    Best regards,

    Heiner

  • Thank you! 

    I'll take a closer look and get back to you. 

    Note that we just released the latest version on the nRF5 SDK for Mesh (v.3.2.0)

    Best regards, 
    Joakim

  • Hi Joakim,

    apparently I had to use nrf_drv_rtc_counter_clear and nrf_drv_rtc_cc_set after each compare event.

    The compare timer did not trigger again, because it disables itself after the first use (described in this thread).

    I'm also using instance #2 of the rtc, because it seems like the other instances are in use.

    This might explain, why lfclk_config did not work. Most likely it has already been configured elsewhere in the code.

    Anyways I'm still not quite happy, because I don't really understand what's going on and where the clock is configured in this example.

    If it's possible, could you maybe point me to where the clock configuration of the mesh example is described?

    It would be great to know, so I can calculate the correct compare value instead of just trying.

    Also, it might be easier to understand what parameters I can change, without messing up some other part of the code.

    Note that we just released the latest version on the nRF5 SDK for Mesh (v.3.2.0)

    I also took a look into the new SDK version, but on a first sight the example does not seem to be build much different than it was in the v.3.1.0 version.

    Unless the Mesh Team strongly recommends it, I would probably try to finish the prototype before migrating to the new SDK version.

    Best,

    Heiner

  • Hi. 

    Sorry about the very long delay here. 

    It seems that you are on the right track here. 

    Depending on what you are looking for specifically, you can find most of the clock settings in the sdk_config file. 

    Also, mesh_init() ->  .core.lfclksrc = DEV_BOARD_LF_CLK_CFG, 

    /**
    * Clock configuration for Nordic development boards.
    */
    #if defined(S110)
    #define DEV_BOARD_LF_CLK_CFG NRF_CLOCK_LFCLKSRC_XTAL_20_PPM
    #elif NRF_SD_BLE_API_VERSION >= 5
    #define DEV_BOARD_LF_CLK_CFG { \
    .source = NRF_SDH_CLOCK_LF_SRC, \
    .rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV, \
    .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV, \
    .accuracy = NRF_SDH_CLOCK_LF_ACCURACY \
    }
    #else
    #define DEV_BOARD_LF_CLK_CFG { \
    .source = NRF_CLOCK_LF_SRC_XTAL, \
    .rc_ctiv = 0, \
    .rc_temp_ctiv = 0, \
    .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM \
    }
    #endif

     

    Heiner said:
    Unless the Mesh Team strongly recommends it, I would probably try to finish the prototype before migrating to the new SDK version.

     nRF5 SDK for Mesh v.3.2.0 is a minor feature release. It adds Friend feature support, the RSSI monitoring model, support for nRF5 SDK v15.3.0, significant changes to the DFU documentation, and fixes to several bugs.

    You can take a look at the release notes, and see if any of the changes to the SDK is vital for your application. If not, you should be fine using v.3.1.0. 

    Best regards, 
    Joakim. 

Related