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

Parents
  • 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.

Reply
  • 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.

Children
No Data
Related