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

32-bit Timer has apparent Non-linearity?

Hi,

I've created a small test program (pasted below) that is intended to help me profile some of my code down to us resolution. Maybe you can quickly run it (no other files needed) to see if you also get what I do.

While it works very well at short durations (us, ms, and <4s), it fails during longer times (say, 30 s) where it reports much shorter durations than truth (see inside main() where I show the actual delay and comment the result). How could this be?

Thanks! Jamie


#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"


/** @def p_timer
 * Enumeration for the timers available for NRF device.
 */
typedef enum
{
  TIMER0 = 0,  /**< Timer 0 module, base address at 0x40008000. */
  TIMER1,      /**< Timer 1 module, base address at 0x40009000. */
  TIMER2       /**< Timer 2 module, base address at 0x4000A000. */
} timer_t;

/**
 * @brief Function for timer initialization.
 */
static volatile NRF_TIMER_Type * timer_init(timer_t timer)
{
    volatile NRF_TIMER_Type * p_timer;

    // Start 16 MHz crystal oscillator.
    NRF_CLOCK->EVENTS_HFCLKSTARTED  = 0;
    NRF_CLOCK->TASKS_HFCLKSTART     = 1;

    // Wait for the external oscillator to start up.
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) 
    {
        // Do nothing.
    }

    switch (timer)
    {
        case TIMER0:
            p_timer = NRF_TIMER0;
            break;

        case TIMER1:
            p_timer = NRF_TIMER1;
            break;

        case TIMER2:
            p_timer = NRF_TIMER2;
            break;

        default:
            p_timer = 0;
            break;
    }
    return p_timer;
}

static volatile NRF_TIMER_Type * timer_StartTiming(timer_t timer)
{
		volatile NRF_TIMER_Type * p_timer = timer_init(timer);

		p_timer->MODE           = TIMER_MODE_MODE_Timer;        // Set the timer in Timer Mode.
		p_timer->PRESCALER      = 4;                            // Prescaler 4 produces 1 MHz timer frequency => 1 tick = 1 us.
		p_timer->BITMODE        = TIMER_BITMODE_BITMODE_32Bit;  // 32 bit mode. Provides 4294.967 seconds between rollovers at 1 MHz frequency.
		p_timer->TASKS_CLEAR    = 1;                            // clear the task first to be usable for later.

		p_timer->TASKS_START    = 1;                    				// Start timer.		
	
		return p_timer;
}

static uint32_t timer_GetTime(volatile NRF_TIMER_Type * p_timer)
{	
		p_timer->TASKS_CAPTURE[0]=1;
	
		return p_timer->CC[0];
}

static void timer_StopTimer(volatile NRF_TIMER_Type * p_timer)
{
		p_timer->TASKS_STOP         = 1;                // Stop timer.
}

/** @brief Function for using the peripheral hardware timers to generate an event after requested number of milliseconds.
 *
 * @param[in] timer Timer to be used for delay, values from @ref p_timer
 * @param[in] number_of_ms Number of milliseconds the timer will count.
 * @note This function will power ON the requested timer, wait until the delay, and then power OFF that timer.
 */



/**
 * @brief Function for main application entry.
 */
int main(void)
{	
		static volatile NRF_TIMER_Type *p_timer;
		uint32_t timedValue;
	
    while (true)
    {			
				// Start the timer
				p_timer = timer_StartTiming(TIMER0);								

#if 1
                                // Profile code: WRONG!
				nrf_delay_ms(30000);											// Do task 1
				timedValue = timer_GetTime(p_timer);	// Get task 1 time: debug shows 13.226536 s				
#else
   // Profile code: WORKS!
				nrf_delay_ms(200);											// Do task 1
				timedValue = timer_GetTime(p_timer);	// Get task 1 time: debug shows 200027 us
				nrf_delay_ms(47);											// Do task 2
				timedValue = timer_GetTime(p_timer);	// Get task 1+2 time: debug shows 247036 us
#endif
				
				// Stop the timer
        timer_StopTimer(p_timer);
    } 
}

/** @} */
Parents Reply Children
No Data
Related