This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

how to implement accurate milisecond function

I am new to nrf51822. I am trying to convert my Arduino code into NRF51822

I need something like this

currentMillis = micros(); //microseconds since the Arduino board began running if(currentMillis-past_time>=1000) { do something }

What is the best way to do this in NRF51822? Should I use RTC or go with simple timer? Can anyone share their function if they have already implemented?

Thanks

  • I modified app_timer.c to include a overflow count and then I added an access function to (hopefully) atomically access the current overflow count and the RTC1 counter value. From there you can compute seconds and microseconds or whatever you need. I do all my long term timekeeping stuff in seconds & ticks and my short term timekeeping in RTC1 ticks.

    One quirk is you always need to keep at least one timer active or the app_timer code will disable RTC1 to save power. I happen to have a timer that is always running, so this wasn't an issue for me.

    My access code is:

    void app_timer_ticks(uint32_t *p_overflow, uint32_t *p_ticks)
    {
        volatile uint32_t overflow0, overflow1;
        uint32_t ticks;
        
        /* spin trying to sample clean counters */
        do
        {
            overflow0 = m_overflow_count;
            ticks = NRF_RTC1->COUNTER;
            overflow1 = m_overflow_count;
        } while (overflow0 != overflow1); // unlikely 
        
        *p_overflow = overflow1;
        *p_ticks    = ticks;
    }
    

    I'd imagine this still has a small race window where COUNTER is sampled after it rolls over but before m_overflow_count is updated by the interrupt. Reading the COUNTER twice to make sure the second read is larger then the next might close the window, but I haven't tried this.

    I increment m_overflow_count on EVENTS_OVRFLW in RTC1_IRQHandler() and turn on the overflow event in rtc1_start().

    This might be a useful feature to add to a future version of the SDK.

  • Here's another solution using Nordic's app_timer API to RTC1.

    uint32_t watchdog_timer;
    uint32_t app_timer_cur;
    uint32_t app_timer_diff;
    
    /* Set watchdog timer */
    app_timer_cnt_get(&watchdog_timer);
    
    /* Other processing occurs... */
    
    /* Check for a watchdog timeout */
    app_timer_cnt_get(&app_timer_cur);
    app_timer_cnt_diff_compute(app_timer_cur, watchdog_timer, &app_timer_diff);
    if (app_timer_diff > APP_TIMER_TICKS(WATCHDOG_TMOUT,APP_TIMER_PRESCALER))
    {
        /* Watchdog timeout */
    }
    

    WATCHDOG_TIMOUT is in milliseconds, here it is a constant but it could be a variable.

    The cnt_diff_compute function handles timer range and rollover. This of course has the same constraint that RTC1 is running when you are tracking elapsed time.

  • My problem was the 24 bit counter with a 32khz clock rolls over every 512s. I needed to keep track of time for the power on life of the device. You divide the 32khz down but it depends on how much resolution you need.

  • Indeed, 512s range and roughly 30.5 us per tick is what we have with the bare 24-bit RTC at 32.768 kHz.

Related