Accuracy of uncalibrated LFRC oscillator

Hi

As part of attempting to write code for self testing I'm trying to measure the HFXO frequency using the LFRC (we don have an LFXO)
I'm expecting that the measured HFXO frequency error should basically at worst be the worst case error of the LFRC.

At cold start I get a deviation of 6.3%.
According to the product specification for the nrf52832 "19.4.3 32.768 kHz RC oscillator (LFRC)" I would have expected this to be below 2%

screen shot of the LRFC specification

After a warm boot where the LFRC has been calibrated the deviation is 0.00060625%
This low deviation makes me believe that the measuring method is working correctly.

I'm also slightly puzzled that the HFINT has a specification of +-6%

Anyhow my question:

Is the uncalibrated LFRC accurate to within +-2% over the operating temperature range of the the nRF52832,
if not what is the accuracy of the LFRC over the operating temperature range?

Thanks in advance.

Parents
  • In case it helps, this is the test code used

    #include "self_test_freqency.h"
    
    #define DEBUG_ENABLED
    
    #include "app_debug_stream.h"
    
    #include "nrf52.h"
    #include "nrf_delay.h"
    
    
    //RTC clock is 32.768kHzd
    #define TEST_PERIOD (32768)
    #define TEST_PRECOUNT (1000)
    
    
    
    void self_test_freqency_testAtStartup(void){
      //Starting clocks
      NRF_CLOCK->LFCLKSRC = 0; //RC osc, should it already be after reset
      NRF_CLOCK->TASKS_LFCLKSTART = 1;
      NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
      //Waiting for the clocks to start up
      while (NRF_CLOCK->HFCLKSTAT != ((1<<16) | 1) ||
             NRF_CLOCK->LFCLKSTAT != (1<<16)) {  }
    
    
      //Configure the RTC (uses the LF clock, configured to use the RC oscilator) to time a
      //timer (HF clock, configured to use the 32MHz xtal)
      NRF_RTC0->INTENSET = 0;
      NRF_RTC0->TASKS_STOP = 1;
      NRF_RTC0->EVTEN = 0b11<<16;
      NRF_RTC0->CC[0] = TEST_PRECOUNT;
      NRF_RTC0->CC[1] = TEST_PRECOUNT+TEST_PERIOD;
      NRF_RTC0->PRESCALER = 0;
      NRF_RTC0->TASKS_CLEAR = 1;
    
      //Configure the timer for measuring the xtal frequency
      NRF_TIMER0->PRESCALER = 0;
      NRF_TIMER0->MODE  = 0;
      NRF_TIMER0->BITMODE = 3; //32 bit counter
    
      //Configure PPI system to time the test
      NRF_PPI->CH[0].EEP = (uint32_t)(&(NRF_RTC0->EVENTS_COMPARE[0]));
      NRF_PPI->CH[0].TEP = (uint32_t)(&(NRF_TIMER0->TASKS_CAPTURE[0]));
      NRF_PPI->CH[1].EEP = (uint32_t)(&(NRF_RTC0->EVENTS_COMPARE[1]));
      NRF_PPI->CH[1].TEP = (uint32_t)(&(NRF_TIMER0->TASKS_CAPTURE[1]));
      NRF_PPI->CHEN = 0b11;
    
    
      //Start the test 
      NRF_TIMER0->TASKS_START = 1;
      NRF_RTC0->TASKS_START = 1;
    
      //Wait for the test to be done
      while (NRF_RTC0->COUNTER < TEST_PRECOUNT+TEST_PERIOD+100){
      }
    
      //Stop the timers
      NRF_RTC0->TASKS_STOP = 1;
      NRF_TIMER0->TASKS_STOP = 0;
    
      //Evaluate the result
      uint32_t counts = NRF_TIMER0->CC[1] - NRF_TIMER0->CC[0];
      DEBUG_PRINT("CLK count %lu\n", counts);
    
      //Return the PPI to its reset configuration
      NRF_PPI->CH[0].EEP = 0;
      NRF_PPI->CH[0].TEP = 0;
      NRF_PPI->CH[1].EEP = 0;
      NRF_PPI->CH[1].TEP = 0;
      NRF_PPI->CHEN = 0;
    
      //Return the RTC to its reset configuration
      NRF_RTC0->EVTEN = 0;
      NRF_RTC0->CC[0] = 0;
      NRF_RTC0->CC[0] = 1;
      NRF_RTC0->TASKS_CLEAR = 1;
    
      //Return the timer to its reset configuration
      NRF_TIMER0->BITMODE = 0;
      NRF_TIMER0->CC[0] = 0;
      NRF_TIMER0->CC[1] = 0;
      NRF_TIMER0->TASKS_CLEAR = 1;
    
    
      //Stopping the clocks 
      NRF_CLOCK->TASKS_LFCLKSTOP = 1;
      NRF_CLOCK->TASKS_HFCLKSTOP = 1;
    
      //Waiting for the clocks to stop
      while ((NRF_CLOCK->HFCLKSTAT & 1) != 0 ||
             NRF_CLOCK->LFCLKSTAT != 0) {  }
    }

Reply
  • In case it helps, this is the test code used

    #include "self_test_freqency.h"
    
    #define DEBUG_ENABLED
    
    #include "app_debug_stream.h"
    
    #include "nrf52.h"
    #include "nrf_delay.h"
    
    
    //RTC clock is 32.768kHzd
    #define TEST_PERIOD (32768)
    #define TEST_PRECOUNT (1000)
    
    
    
    void self_test_freqency_testAtStartup(void){
      //Starting clocks
      NRF_CLOCK->LFCLKSRC = 0; //RC osc, should it already be after reset
      NRF_CLOCK->TASKS_LFCLKSTART = 1;
      NRF_CLOCK->TASKS_HFCLKSTART = 1;
    
      //Waiting for the clocks to start up
      while (NRF_CLOCK->HFCLKSTAT != ((1<<16) | 1) ||
             NRF_CLOCK->LFCLKSTAT != (1<<16)) {  }
    
    
      //Configure the RTC (uses the LF clock, configured to use the RC oscilator) to time a
      //timer (HF clock, configured to use the 32MHz xtal)
      NRF_RTC0->INTENSET = 0;
      NRF_RTC0->TASKS_STOP = 1;
      NRF_RTC0->EVTEN = 0b11<<16;
      NRF_RTC0->CC[0] = TEST_PRECOUNT;
      NRF_RTC0->CC[1] = TEST_PRECOUNT+TEST_PERIOD;
      NRF_RTC0->PRESCALER = 0;
      NRF_RTC0->TASKS_CLEAR = 1;
    
      //Configure the timer for measuring the xtal frequency
      NRF_TIMER0->PRESCALER = 0;
      NRF_TIMER0->MODE  = 0;
      NRF_TIMER0->BITMODE = 3; //32 bit counter
    
      //Configure PPI system to time the test
      NRF_PPI->CH[0].EEP = (uint32_t)(&(NRF_RTC0->EVENTS_COMPARE[0]));
      NRF_PPI->CH[0].TEP = (uint32_t)(&(NRF_TIMER0->TASKS_CAPTURE[0]));
      NRF_PPI->CH[1].EEP = (uint32_t)(&(NRF_RTC0->EVENTS_COMPARE[1]));
      NRF_PPI->CH[1].TEP = (uint32_t)(&(NRF_TIMER0->TASKS_CAPTURE[1]));
      NRF_PPI->CHEN = 0b11;
    
    
      //Start the test 
      NRF_TIMER0->TASKS_START = 1;
      NRF_RTC0->TASKS_START = 1;
    
      //Wait for the test to be done
      while (NRF_RTC0->COUNTER < TEST_PRECOUNT+TEST_PERIOD+100){
      }
    
      //Stop the timers
      NRF_RTC0->TASKS_STOP = 1;
      NRF_TIMER0->TASKS_STOP = 0;
    
      //Evaluate the result
      uint32_t counts = NRF_TIMER0->CC[1] - NRF_TIMER0->CC[0];
      DEBUG_PRINT("CLK count %lu\n", counts);
    
      //Return the PPI to its reset configuration
      NRF_PPI->CH[0].EEP = 0;
      NRF_PPI->CH[0].TEP = 0;
      NRF_PPI->CH[1].EEP = 0;
      NRF_PPI->CH[1].TEP = 0;
      NRF_PPI->CHEN = 0;
    
      //Return the RTC to its reset configuration
      NRF_RTC0->EVTEN = 0;
      NRF_RTC0->CC[0] = 0;
      NRF_RTC0->CC[0] = 1;
      NRF_RTC0->TASKS_CLEAR = 1;
    
      //Return the timer to its reset configuration
      NRF_TIMER0->BITMODE = 0;
      NRF_TIMER0->CC[0] = 0;
      NRF_TIMER0->CC[1] = 0;
      NRF_TIMER0->TASKS_CLEAR = 1;
    
    
      //Stopping the clocks 
      NRF_CLOCK->TASKS_LFCLKSTOP = 1;
      NRF_CLOCK->TASKS_HFCLKSTOP = 1;
    
      //Waiting for the clocks to stop
      while ((NRF_CLOCK->HFCLKSTAT & 1) != 0 ||
             NRF_CLOCK->LFCLKSTAT != 0) {  }
    }

Children
No Data
Related