CC26xx Driver Library
[osc.h] Oscillator

Data Structures

struct  XoscLf_Params_t
 A structure that defines the polynomial coefficients for calculating the XOSC LF ppm offset as function of temperature. More...
 
struct  HposcDebugData_t
 Data structure for experimental HPOSC polynomials calculation. More...
 

Functions

static void OSCXHfPowerModeSet (uint32_t ui32Mode)
 Set Power Mode for High Frequency XTAL Oscillator. More...
 
static void OSCClockLossEventEnable (void)
 Enables OSC clock loss event detection. More...
 
static void OSCClockLossEventDisable (void)
 Disables OSC clock loss event detection. More...
 
void OSCClockSourceSet (uint32_t ui32SrcClk, uint32_t ui32Osc)
 Configure the oscillator input to the a source clock. More...
 
uint32_t OSCClockSourceGet (uint32_t ui32SrcClk)
 Get the source clock settings. More...
 
static bool OSCHfSourceReady (void)
 Check if the HF clock source is ready to be switched. More...
 
static void OSCHfSourceSwitch (void)
 Switch the high frequency clock. More...
 
static bool OSC_IsHPOSCEnabled (void)
 Identifies if HPOSC is enabled. More...
 
static bool OSC_IsHPOSCEnabledWithHfDerivedLfClock (void)
 Identifies if HPOSC is enabled and that SCLK_LF is derived from XOSC_HF. More...
 
uint32_t OSCHF_GetStartupTime (uint32_t timeUntilWakeupInMs)
 Returns maximum startup time (in microseconds) of XOSC_HF. More...
 
void OSCHF_TurnOnXosc (void)
 Turns on XOSC_HF (but without switching to XOSC_HF). More...
 
bool OSCHF_AttemptToSwitchToXosc (void)
 Switch to XOSC_HF if XOSC_HF is ready. More...
 
void OSCHF_SwitchToRcOscTurnOffXosc (void)
 Switch to RCOSC_HF and turn off XOSC_HF. More...
 
uint32_t OSCHF_DebugGetCrystalAmplitude (void)
 Get crystal amplitude (assuming crystal is running). More...
 
uint32_t OSCHF_DebugGetExpectedAverageCrystalAmplitude (void)
 Get the expected average crystal amplitude. More...
 
uint32_t OSCHF_DebugGetCrystalStartupTime (void)
 Measure the crystal startup time. More...
 
void OSC_HPOSCInitializeFrequencyOffsetParameters (void)
 HPOSC initialization function. Must always be called before using HPOSC. More...
 
void OSC_HPOSC_Debug_InitFreqOffsetParams (HposcDebugData_t *pDebugData)
 Debug function to calculate the HPOSC polynomials for experimental data sets. More...
 
void OSC_HPOSCInitializeSingleInsertionFreqOffsParams (uint32_t measFieldAddress)
 Special HPOSC initialization function for single temperature compensation. More...
 
int32_t OSC_HPOSCRelativeFrequencyOffsetGet (int32_t tempDegC)
 Calculate the temperature dependent relative frequency offset of HPOSC. More...
 
void OSC_CapArrayAdjustWorkaround_Boot (void)
 Special XOSC_HF workaround adjustment for CC13x2 / CC26x2 XOSC_CAPARRAY_DELTA setting in CCFG (Customer configuration) More...
 
void OSC_AdjustXoscHfCapArray (int32_t capArrDelta)
 Adjust the XOSC HF cap array relative to the factory setting. More...
 
int16_t OSC_HPOSCRelativeFrequencyOffsetToRFCoreFormatConvert (int32_t HPOSC_RelFreqOffset)
 Converts the relative frequency offset of HPOSC to the RF Core parameter format. More...
 
void OSC_HPOSCRtcCompensate (int32_t relFreqOffset)
 Compensate the RTC increment based on the relative frequency offset of HPOSC. More...
 
void OSC_LFXOSCInitStaticOffset (void)
 Initialize device specific coefficient for XOSC LF RTC compensation. More...
 
int32_t OSC_LFXOSCRelativeFrequencyOffsetGet (int32_t temperature)
 Calculates the ppm offset of XOSC LF for a given temperature. More...
 

Detailed Description

Function Documentation

§ OSC_AdjustXoscHfCapArray()

void OSC_AdjustXoscHfCapArray ( int32_t  capArrDelta)

Adjust the XOSC HF cap array relative to the factory setting.

The cap array factory setting (FCFG) can be converted to a number in the range 0 - 63. Both this function and the customer configuration (CCFG) setting can apply a delta to the FCFG setting. The CCFG setting is automatically applied at boot time (See ../startup_files/ccfg.c). Calling this function will discard the CCFG setting and adjust relative to the FCFG setting.

Note
Adjusted value will not take effect before XOSC_HF is stopped and restarted
Parameters
capArrDeltaspecifies number of step to adjust the cap array relative to the factory setting.
Returns
None
397 {
399  // Workaround for chip settings like 0x701F0 and 0x701FE which get readjusted with baseline 7001F/6.1pF
401  } else
402  {
403  // Read the MODE_CONF register in CCFG
404  uint32_t ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
405  // Clear CAP_MODE and the CAPARRAY_DELATA field
406  ccfg_ModeConfReg &= ~( CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_M | CCFG_MODE_CONF_XOSC_CAP_MOD_M );
407  // Insert new delta value
408  ccfg_ModeConfReg |= ((((uint32_t)capArrDelta) << CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_S ) & CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_M );
409  // Update the HW register with the new delta value
410  DDI32RegWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_ANABYPASSVAL1, SetupGetTrimForAnabypassValue1( ccfg_ModeConfReg ));
411  }
412 }
static void InternCapArrayAdjustWithBaseline7001F(int32_t capArrayDelta)
Definition: osc.c:337
uint32_t SetupGetTrimForAnabypassValue1(uint32_t ccfg_ModeConfReg)
Returns the trim value to be used for the ANABYPASS_VALUE1 register in OSC_DIG.
Definition: setup_rom.c:436
static uint32_t SpecialCapArrayWorkaroundEnabledAndNeeded(void)
Definition: osc.c:353
void DDI32RegWrite(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Val)
Write a 32 bit value to a register in the DDI slave.
Definition: ddi.c:64
Here is the call graph for this function:

§ OSC_CapArrayAdjustWorkaround_Boot()

void OSC_CapArrayAdjustWorkaround_Boot ( void  )

Special XOSC_HF workaround adjustment for CC13x2 / CC26x2 XOSC_CAPARRAY_DELTA setting in CCFG (Customer configuration)

Implements a workaround for devices with an unfortunate XOSH_HF CAPARRAY factory configuration (FCFG1 setting). The workaround is done only if both enabled and needed (enabled by setting CCFG_SIZE_AND_DIS_FLAGS_DIS_LINEAR_CAPARRAY_DELTA_WORKAROUND = 0) The factory configuration works fine on its own but does not comply with the requirements of the CCFG:XOSC_CAPARRAY_DELTA mechanism. Without this workaround, there will be a larger jump in capacitance (and frequency) between XOSC_CAPARRAY_DELTA setting 7 and 8.

Returns
None
See also
OSC_AdjustXoscHfCapArray()

Referenced by TrimAfterColdResetWakeupFromShutDown().

372 {
373  uint32_t ccfg_ModeConfReg ;
374  int32_t ccfg_CapArrayDelta ;
375 
377  // Workaround for chip settings like 0x701F0 and 0x701FE which get readjusted with baseline 7001F/6.1pF
378  ccfg_CapArrayDelta = 0 ;
379  ccfg_ModeConfReg = HWREG( CCFG_BASE + CCFG_O_MODE_CONF );
380  if (( ccfg_ModeConfReg & CCFG_MODE_CONF_XOSC_CAP_MOD ) == 0 ) {
381  // CCFG CapArrayDelta is enabled get sign-extended delta
382  ccfg_CapArrayDelta =
383  (((int32_t)( ccfg_ModeConfReg << ( 32 - CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_W - CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_S )))
384  >> ( 32 - CCFG_MODE_CONF_XOSC_CAPARRAY_DELTA_W ));
385  }
386  InternCapArrayAdjustWithBaseline7001F( ccfg_CapArrayDelta );
387  }
388 }
static void InternCapArrayAdjustWithBaseline7001F(int32_t capArrayDelta)
Definition: osc.c:337
static uint32_t SpecialCapArrayWorkaroundEnabledAndNeeded(void)
Definition: osc.c:353
Here is the call graph for this function:

§ OSC_HPOSC_Debug_InitFreqOffsetParams()

void OSC_HPOSC_Debug_InitFreqOffsetParams ( HposcDebugData_t pDebugData)

Debug function to calculate the HPOSC polynomials for experimental data sets.

Parameters
pDebugDatapointer to the input data collected in HposcDebugData_t
Returns
None
See also
OSC_HPOSCInitializeFrequencyOffsetParameters()
610 {
611  /* Initialize HPOSC internal parameter */
612  hposc_insertions_t hposcMeas;
613  int64_t pu0[3],pu1[3],pu2[3] = {0};
614  hposc_param_t hposcParm =
615  {
616  .pu0b = {42, 32, 27, 20},
617  .pu0c = {-284,-184,536,-104798},
618  .pu1b = {36, 32, 27, 20},
619  .pu1c = {-1155,44130,-319090,-3563},
620  .pu2b = {36, 32, 27, 20},
621  .pu2c = {-3410,261727,-32194,-116627}
622  };
623 
624  /* Retrieve insertions from FCFG */
625  readTempAndFreq((uint32_t)&pDebugData->meas_1, &hposcMeas.temp[0], &hposcMeas.dFreq[0], pDebugData->offsetD1);
626  readTempAndFreq((uint32_t)&pDebugData->meas_2, &hposcMeas.temp[1], &hposcMeas.dFreq[1], pDebugData->offsetD2);
627  readTempAndFreq((uint32_t)&pDebugData->meas_3, &hposcMeas.temp[2], &hposcMeas.dFreq[2], pDebugData->offsetD3);
628 
629  /* Compute HPOSC polynomial coefficients */
630  findHposcPc(hposcParm.pu0c, hposcParm.pu0b, &hposcMeas.temp[0], 3, pu0);
631  findHposcPc(hposcParm.pu1c, hposcParm.pu1b, &hposcMeas.temp[0], 3, pu1);
632  findHposcPc(hposcParm.pu2c, hposcParm.pu2b, &hposcMeas.temp[0], 3, pu2);
633  findHposcCoefficients(&hposcMeas.dFreq[0], pu0, pu1, pu2, &hposcParm);
634 }
uint8_t pu2b[4]
Definition: osc.c:443
int32_t offsetD3
Offset to measurement set 3.
Definition: osc.h:576
int32_t offsetD1
Offset to measurement set 1.
Definition: osc.h:574
int64_t pu0c[4]
Definition: osc.c:444
static void readTempAndFreq(uint32_t regAddr, int32_t *pTemp, int32_t *pdFreq, int32_t deltaFreq)
Definition: osc.c:558
uint32_t meas_1
Measurement set 1 (typically at room temp)
Definition: osc.h:571
Definition: osc.c:433
uint32_t meas_3
Measurement set 3 (typically at low temp)
Definition: osc.h:573
int64_t pu1c[4]
Definition: osc.c:445
int32_t offsetD2
Offset to measurement set 2.
Definition: osc.h:575
static void findHposcCoefficients(int32_t *pInput, int64_t *col0, int64_t *col1, int64_t *col2, hposc_param_t *pParam)
Definition: osc.c:485
static void findHposcPc(int64_t *pCoeff, uint8_t *pBits, int32_t *pTemp, uint8_t nTemp, int64_t *pOutput)
Definition: osc.c:541
uint32_t meas_2
Measurement set 2 (typically at high temp)
Definition: osc.h:572
int32_t dFreq[3]
Definition: osc.c:436
uint8_t pu0b[4]
Definition: osc.c:441
uint8_t pu1b[4]
Definition: osc.c:442
Definition: osc.c:439
int64_t pu2c[4]
Definition: osc.c:446
int32_t temp[3]
Definition: osc.c:435
Here is the call graph for this function:

§ OSC_HPOSCInitializeFrequencyOffsetParameters()

void OSC_HPOSCInitializeFrequencyOffsetParameters ( void  )

HPOSC initialization function. Must always be called before using HPOSC.

Calculates the fitting curve parameters (polynomials) to be used by the HPOSC temperature compensation.

Returns
None
See also
OSC_HPOSC_Debug_InitFreqOffsetParams(), OSC_HPOSCInitializeSingleInsertionFreqOffsParams()

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock().

579 {
580  /* Initialize HPOSC internal parameter */
581  hposc_insertions_t hposcMeas;
582  int64_t pu0[3],pu1[3],pu2[3] = {0};
583  hposc_param_t hposcParm =
584  {
585  .pu0b = {42, 32, 27, 20},
586  .pu0c = {-284,-184,536,-104798},
587  .pu1b = {36, 32, 27, 20},
588  .pu1c = {-1155,44130,-319090,-3563},
589  .pu2b = {36, 32, 27, 20},
590  .pu2c = {-3410,261727,-32194,-116627}
591  };
592 
593  /* Retrieve insertions from FCFG */
594  readTempAndFreq(FCFG1_BASE + FCFG1_O_HPOSC_MEAS_1, &hposcMeas.temp[0], &hposcMeas.dFreq[0], D1OFFSET_25C);
595  readTempAndFreq(FCFG1_BASE + FCFG1_O_HPOSC_MEAS_2, &hposcMeas.temp[1], &hposcMeas.dFreq[1], D2OFFSET_85C);
596  readTempAndFreq(FCFG1_BASE + FCFG1_O_HPOSC_MEAS_3, &hposcMeas.temp[2], &hposcMeas.dFreq[2], D3OFFSET_n40C);
597 
598  /* Compute HPOSC polynomial coefficients */
599  findHposcPc(hposcParm.pu0c, hposcParm.pu0b, &hposcMeas.temp[0], 3, pu0);
600  findHposcPc(hposcParm.pu1c, hposcParm.pu1b, &hposcMeas.temp[0], 3, pu1);
601  findHposcPc(hposcParm.pu2c, hposcParm.pu2b, &hposcMeas.temp[0], 3, pu2);
602  findHposcCoefficients(&hposcMeas.dFreq[0], pu0, pu1, pu2, &hposcParm);
603 }
uint8_t pu2b[4]
Definition: osc.c:443
int64_t pu0c[4]
Definition: osc.c:444
#define D3OFFSET_n40C
Definition: osc.c:422
static void readTempAndFreq(uint32_t regAddr, int32_t *pTemp, int32_t *pdFreq, int32_t deltaFreq)
Definition: osc.c:558
Definition: osc.c:433
#define D2OFFSET_85C
Definition: osc.c:421
int64_t pu1c[4]
Definition: osc.c:445
static void findHposcCoefficients(int32_t *pInput, int64_t *col0, int64_t *col1, int64_t *col2, hposc_param_t *pParam)
Definition: osc.c:485
static void findHposcPc(int64_t *pCoeff, uint8_t *pBits, int32_t *pTemp, uint8_t nTemp, int64_t *pOutput)
Definition: osc.c:541
int32_t dFreq[3]
Definition: osc.c:436
uint8_t pu0b[4]
Definition: osc.c:441
uint8_t pu1b[4]
Definition: osc.c:442
Definition: osc.c:439
int64_t pu2c[4]
Definition: osc.c:446
int32_t temp[3]
Definition: osc.c:435
#define D1OFFSET_25C
Definition: osc.c:420
Here is the call graph for this function:

§ OSC_HPOSCInitializeSingleInsertionFreqOffsParams()

void OSC_HPOSCInitializeSingleInsertionFreqOffsParams ( uint32_t  measFieldAddress)

Special HPOSC initialization function for single temperature compensation.

Used when a single temperature offset measurement is available. This is espesially designed to get a better crystal performance (SW TCXO) on the SiP module but can also be usful to get better crystal performance over the entire temperature range on a standard design as well.

Returns
None
See also
OSC_HPOSCInitializeFrequencyOffsetParameters()
643 {
644  /* Initialize HPOSC internal parameter */
645  hposc_insertions_t hposcMeas;
646  int64_t pu0;
647  hposc_param_t hposcParm =
648  {
649  /* Coefficients for SW-TCXO */
650  .pu0b = {44, 44, 27, 20},
651  .pu0c = {8183, -2546, -210, -104866}
652  };
653 
654  /* Retrieve insertions from FCFG */
655  readTempAndFreq( measFieldAddress, &hposcMeas.temp[0], &hposcMeas.dFreq[0], 0);
656 
657  /* Compute HPOSC polynomial coefficients */
658  findHposcPc(hposcParm.pu0c, hposcParm.pu0b, &hposcMeas.temp[0], 1, &pu0);
659  findHposcCoefficients(&hposcMeas.dFreq[0], &pu0, NULL, NULL, &hposcParm);
660 }
int64_t pu0c[4]
Definition: osc.c:444
static void readTempAndFreq(uint32_t regAddr, int32_t *pTemp, int32_t *pdFreq, int32_t deltaFreq)
Definition: osc.c:558
Definition: osc.c:433
static void findHposcCoefficients(int32_t *pInput, int64_t *col0, int64_t *col1, int64_t *col2, hposc_param_t *pParam)
Definition: osc.c:485
static void findHposcPc(int64_t *pCoeff, uint8_t *pBits, int32_t *pTemp, uint8_t nTemp, int64_t *pOutput)
Definition: osc.c:541
int32_t dFreq[3]
Definition: osc.c:436
uint8_t pu0b[4]
Definition: osc.c:441
Definition: osc.c:439
int32_t temp[3]
Definition: osc.c:435
Here is the call graph for this function:

§ OSC_HPOSCRelativeFrequencyOffsetGet()

int32_t OSC_HPOSCRelativeFrequencyOffsetGet ( int32_t  tempDegC)

Calculate the temperature dependent relative frequency offset of HPOSC.

The HPOSC (High Precision Oscillator) frequency will vary slightly with chip temperature. The frequency offset from the nominal value can be predicted based on second order linear interpolation using coefficients measured in chip production and stored as factory configuration parameters.

This function calculates the relative frequency offset, defined as:

    F_HPOSC = F_nom * (1 + d/(2^22))

where

  • F_HPOSC is the current HPOSC frequency.
  • F_nom is the nominal oscillator frequency, assumed to be 48.000 MHz.
  • d is the relative frequency offset (the value returned).

By knowing the relative frequency offset it is then possible to compensate any timing related values accordingly.

Parameters
tempDegCis the chip temperature in degrees Celsius. Use the function AONBatMonTemperatureGetDegC() to get current chip temperature.
Returns
Returns the relative frequency offset parameter d.
See also
OSC_HPOSCRelativeFrequencyOffsetToRFCoreFormatConvert(), AONBatMonTemperatureGetDegC()
725 {
726  // Estimate HPOSC frequency offset, using temperature and curve fitting parameters
727 
728  // Now we can find the HPOSC freq offset, given as a signed variable d, expressed by:
729  //
730  // F_HPOSC = F_nom * (1 + d/(2^22)) , where: F_HPOSC = HPOSC frequency
731  // F_nom = nominal clock source frequency (e.g. 48.000 MHz)
732  // d = describes relative freq offset
733 
734  // We can estimate the d variable, using temperature compensation parameters:
735  //
736  // d = P[3]*(t - T0)^3 + P[2]*(t - T0)^2 + P[1]*(t - T0) + P[0], where: P0,P1,P2,P3 are curve fitting parameters
737  // t = current temperature (from temp sensor) in deg C
738  // T0 = 27 deg C (fixed temperature constant)
739 
740  int32_t d,t1,t2,t3;
741 
742  t1 = tempDegC - 27;
743  t2 = t1 * t1;
744  t3 = t2 * t1;
745 
746  d = ((((int64_t)_hposcCoeffs[3]*t3 + (int64_t)_hposcCoeffs[2]*t2 + (int64_t)_hposcCoeffs[1]*t1) >> HPOSC_COEFF0_SHIFT) +
747  (int64_t)_hposcCoeffs[0]) >> HPOSC_COEFF0_BITS;
748 
749  return ( d );
750 }
#define HPOSC_COEFF0_SHIFT
Definition: osc.c:427
#define HPOSC_COEFF0_BITS
Definition: osc.c:425
int32_t _hposcCoeffs[4]
Definition: osc.c:431

§ OSC_HPOSCRelativeFrequencyOffsetToRFCoreFormatConvert()

int16_t OSC_HPOSCRelativeFrequencyOffsetToRFCoreFormatConvert ( int32_t  HPOSC_RelFreqOffset)

Converts the relative frequency offset of HPOSC to the RF Core parameter format.

The HPOSC (High Precision Oscillator) clock is used by the RF Core. To compensate for a frequency offset in the frequency of the clock source, a frequency offset parameter can be provided as part of the radio configuration override setting list to enable compensation of the RF synthesizer frequency, symbol timing, and radio timer to still achieve correct frequencies.

The RF Core takes a relative frequency offset parameter defined differently compared to the relative frequency offset parameter returned from function OSC_HPOSCRelativeFrequencyOffsetGet() and thus needs to be converted:

    F_nom = F_HPOSC * (1 + RfCoreRelFreqOffset/(2^22))

where

  • F_nom is the nominal oscillator frequency, assumed to be 48.000 MHz.
  • F_HPOSC is the current HPOSC frequency.
  • RfCoreRelFreqOffset is the relative frequency offset in the "RF Core" format (the value returned).
Parameters
HPOSC_RelFreqOffsetis the relative frequency offset parameter d returned from OSC_HPOSCRelativeFrequencyOffsetGet()
Returns
Returns the relative frequency offset in RF Core format.
See also
OSC_HPOSCRelativeFrequencyOffsetGet()
759 {
760  // The input argument, hereby referred to simply as "d", describes the frequency offset
761  // of the HPOSC relative to the nominal frequency in this way:
762  //
763  // F_HPOSC = F_nom * (1 + d/(2^22))
764  //
765  // But for use by the radio, to compensate the frequency error, we need to find the
766  // frequency offset "rfcFreqOffset" defined in the following format:
767  //
768  // F_nom = F_HPOSC * (1 + rfCoreFreqOffset/(2^22))
769  //
770  // To derive "rfCoreFreqOffset" from "d" we combine the two above equations and get:
771  //
772  // (1 + rfCoreFreqOffset/(2^22)) = (1 + d/(2^22))^-1
773  //
774  // Which can be rewritten into:
775  //
776  // rfCoreFreqOffset = -d*(2^22) / ((2^22) + d)
777  //
778  // = -d * [ 1 / (1 + d/(2^22)) ]
779  //
780  // To avoid doing a 64-bit division due to the (1 + d/(2^22))^-1 expression,
781  // we can use Taylor series (Maclaurin series) to approximate it:
782  //
783  // 1 / (1 - x) ~= 1 + x + x^2 + x^3 + x^4 + ... etc (Maclaurin series)
784  //
785  // In our case, we have x = - d/(2^22), and we only include up to the first
786  // order term of the series, as the second order term ((d^2)/(2^44)) is very small:
787  //
788  // freqError ~= -d + d^2/(2^22) (+ small approximation error)
789  //
790  // The approximation error is negligible for our use.
791 
792  int32_t rfCoreFreqOffset = -HPOSC_RelFreqOffset + (( HPOSC_RelFreqOffset * HPOSC_RelFreqOffset ) >> 22 );
793 
794  return ( rfCoreFreqOffset );
795 }

§ OSC_HPOSCRtcCompensate()

void OSC_HPOSCRtcCompensate ( int32_t  relFreqOffset)

Compensate the RTC increment based on the relative frequency offset of HPOSC.

The HPOSC (High Precision Oscillator) frequency will vary slightly with chip temperature. This variation forces the RTC increment to be compensated if SCLK_LF is configured to be derived from the HF clock of HPOSC. This function must only be called if SCLK_LF is configured to be derived from the HF clock of HPOSC. The status of this configuration can be determined by calling the OSC_IsHPOSCEnabledWithHfDerivedLfClock() function.

This function first calculates the HPOSC frequency, defined as:

    F_HPOSC = F_nom * (1 + d/(2^22))

where

  • F_HPOSC is the current HPOSC frequency.
  • F_nom is the nominal oscillator frequency, assumed to be 48.000 MHz.
  • d is the relative frequency offset given by the input argument relFreqOffset. Then the SCLK_LF frequency is calculated, defined as:
        F_SCLK_LF = F_HPOSC / 1536
    
    Then the RTC increment SUBSECINC is calculated, defined as;
        SUBSECINC = (2^38) / F_SCLK_LF
    
    Finally the RTC module is updated with the calculated SUBSECINC value.
Parameters
relFreqOffsetis the relative frequency offset parameter d returned from OSC_HPOSCRelativeFrequencyOffsetGet()
Returns
None
804 {
805  uint32_t rtcSubSecInc;
806  uint32_t lfClkFrequency;
807  uint32_t hfFreq;
808  int64_t calcFactor;
809 
810  // Calculate SCLK_HF frequency, defined as:
811  // hfFreq = 48000000 * (1 + relFreqOffset/(2^22))
812  if( relFreqOffset >= 0 )
813  {
814  calcFactor = ( ( 48000000 * (int64_t)relFreqOffset ) + 0x200000 ) / 0x400000;
815  }
816  else
817  {
818  calcFactor = ( ( 48000000 * (int64_t)relFreqOffset ) - 0x200000 ) / 0x400000;
819  }
820  hfFreq = 48000000 + calcFactor;
821 
822  // Calculate SCLK_LF frequency, defined as SCLK_LF_FREQ = SCLK_HF_FREQ / 1536
823  lfClkFrequency = ( hfFreq + 768 ) / 1536;
824 
825  // Calculate SUBSECINC, defined as: SUBSECINC = 2^38 / SCLK_LF_FREQ
826  rtcSubSecInc = 0x4000000000 / lfClkFrequency;
827 
828  /* Update SUBSECINC value */
829  SetupSetAonRtcSubSecInc(rtcSubSecInc);
830 }
void SetupSetAonRtcSubSecInc(uint32_t subSecInc)
Doing the tricky stuff needed to enter new RTCSUBSECINC value.
Definition: setup_rom.c:927
Here is the call graph for this function:

§ OSC_IsHPOSCEnabled()

static bool OSC_IsHPOSCEnabled ( void  )
inlinestatic

Identifies if HPOSC is enabled.

This function checks if the device supports HPOSC and that HPOSC is selected as HF oscillator for use when the radio is active.

Returns
Returns status of HPOSC functionality:
  • true : HPOSC is enabled.
  • false : HPOSC is not enabled.
389 {
390  bool enabled = false;
391 
392  if((( HWREG(CCFG_BASE + CCFG_O_MODE_CONF) & CCFG_MODE_CONF_XOSC_FREQ_M) == CCFG_MODE_CONF_XOSC_FREQ_HPOSC) &&
393  (( HWREG(FCFG1_BASE + FCFG1_O_OSC_CONF) & FCFG1_OSC_CONF_HPOSC_OPTION) == 0))
394  {
395  enabled = true;
396  }
397 
398  return (enabled);
399 }

§ OSC_IsHPOSCEnabledWithHfDerivedLfClock()

static bool OSC_IsHPOSCEnabledWithHfDerivedLfClock ( void  )
inlinestatic

Identifies if HPOSC is enabled and that SCLK_LF is derived from XOSC_HF.

This function checks if the device supports HPOSC and that HPOSC is selected as HF oscillator for use when the radio is active and also that SCLK_LF is derived from XOSC_HF.

Returns
Returns status of HPOSC and SCLK_LF configuration:
  • true : HPOSC is enabled and SCLK_LF is derived from XOSC_HF.
  • false : Either HPOSC not enabled or SCLK_LF is not derived from XOSC_HF.
416 {
417  bool enabled = false;
418 
419  // Check configuration by reading lower half of the 32-bit CTL0 register
420  uint16_t regVal = HWREGH(AUX_DDI0_OSC_BASE + DDI_0_OSC_O_CTL0);
421  if( ( ( regVal & DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_M ) == DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_XOSCHFDLF ) &&
422  ( ( regVal & DDI_0_OSC_CTL0_HPOSC_MODE_EN_M ) == DDI_0_OSC_CTL0_HPOSC_MODE_EN ) )
423  {
424  enabled = true;
425  }
426 
427  return (enabled);
428 }
Here is the call graph for this function:

§ OSC_LFXOSCInitStaticOffset()

void OSC_LFXOSCInitStaticOffset ( void  )

Initialize device specific coefficient for XOSC LF RTC compensation.

Calculates the device specific static offset of XOSC LF and stores it as a coefficient in the internal _lfXoscParams polynomial structure.

Warning
_lfXoscParams must be defined and populated with polynomial coefficients a, b, and c if this function is called.
Note
This function must be called once, before calling OSC_LFXOSCRelativeFrequencyOffsetGet.
Returns
None
668 {
669  int16_t xoscLfCorrection;
670  int8_t xoscLfCorrectionTemperature;
671 
672  /* If device is untrimmed, apply default values */
673  if (HWREG(FCFG1_BASE + FCFG1_O_HPOSC_MEAS_5) == 0xFFFFFFFF)
674  {
675  /* These values correspond to a 0 ppm offset measurement at 25 degC */
676  xoscLfCorrection = 0;
677  xoscLfCorrectionTemperature = 25;
678  }
679  else
680  {
681  xoscLfCorrection = (int16_t)((HWREG(FCFG1_BASE + FCFG1_O_HPOSC_MEAS_5) & FCFG1_HPOSC_MEAS_5_HPOSC_D5_M) >>
682  FCFG1_HPOSC_MEAS_5_HPOSC_D5_S);
683  xoscLfCorrectionTemperature = (int8_t)((
684  HWREG(FCFG1_BASE + FCFG1_O_HPOSC_MEAS_5) & FCFG1_HPOSC_MEAS_5_HPOSC_T5_M) >>
685  FCFG1_HPOSC_MEAS_5_HPOSC_T5_S);
686  /* Temperature in FCFG is offset by 27 degrees */
687  xoscLfCorrectionTemperature += 27;
688  }
689 
690  /* Calculate the difference between expected offset at FCFG1 temperature, vs actual offset at FCFG1 temperature.
691  * This becomes a static offset whenever a new temperature offset is calculated.
692  * ppm(T) = a*T^2 + b*T + c - d, where d represents a device specific offset from the ideal polynomial
693  * d = ppm(T_trim) - ppm_trim, where ppm_trim is the actual ppm offset measured at production, at the temperature T_trim
694  * ppm_trim is found from FCFG1_HPOSC_MEAS_5_HPOSC_D5 in FCFG, where FCFG1_HPOSC_MEAS_5_HPOSC_D5 = (f/32768 - 1) * 2^22
695  */
696  _lfXoscParams.coeffD = (_lfXoscParams.coeffA * xoscLfCorrectionTemperature * xoscLfCorrectionTemperature +
697  _lfXoscParams.coeffB * xoscLfCorrectionTemperature + _lfXoscParams.coeffC) -
698  (int32_t)((int64_t)xoscLfCorrection * (1000000LL << _lfXoscParams.shift) / 4194304LL);
699 }

§ OSC_LFXOSCRelativeFrequencyOffsetGet()

int32_t OSC_LFXOSCRelativeFrequencyOffsetGet ( int32_t  temperature)

Calculates the ppm offset of XOSC LF for a given temperature.

The offset (measured in ppm) is given by a second order polynomial function of temperature, T: ppm(T) = a*T^2 + b*T + c - d. The coefficients a, b, c, and d are taken from _lfXoscParams.coeffA, _lfoXscParams.coeffB, _lfXoscParams.coeffC and _lfXoscParams.coeffD and scaled down for fixed point arithmetic by a factor of 2^_lfXoscParams.shift. _lfXoscParams must be defined by the application, and must be fully initialized by calling OSC_LFXOSCInitStaticOffset once, before this function is called.

Note
OSC_LFXOSCInitStaticOffset should be called once, before this function is used.
Parameters
temperatureis the on-chip temperature in degrees Celcius.
Returns
Returns the offset in XOSC LF from the nominal frequency, in ppm.
707 {
708  /* The offset (ppm) is given by
709  * ppm(T) = a*T^2 + b*T + c - d
710  * The coefficients a, b, c and d are taken from the internal structure _lfXoscParams, which
711  * must be defined and initialised before this function is called.
712  */
713  return ((_lfXoscParams.coeffA * temperature * temperature) + (_lfXoscParams.coeffB * temperature) +
714  _lfXoscParams.coeffC - _lfXoscParams.coeffD) >>
715  _lfXoscParams.shift;
716 }

§ OSCClockLossEventDisable()

static void OSCClockLossEventDisable ( void  )
inlinestatic

Disables OSC clock loss event detection.

Disabling the OSC clock loss event does also clear the clock loss event flag.

Note
OSC clock loss event must be disabled before SCLK_LF clock source is changed (by calling OSCClockSourceSet()) and remain disabled until the change is confirmed (by calling OSCClockSourceGet()).
Returns
None
See also
OSCClockLossEventEnable()
240 {
241  DDI16BitfieldWrite( AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
242  DDI_0_OSC_CTL0_CLK_LOSS_EN_M,
243  DDI_0_OSC_CTL0_CLK_LOSS_EN_S, 0 );
244 }
void DDI16BitfieldWrite(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift, uint16_t ui32Data)
Write a bit field via the DDI using 16-bit maskable write.
Definition: ddi.c:115
Here is the call graph for this function:

§ OSCClockLossEventEnable()

static void OSCClockLossEventEnable ( void  )
inlinestatic

Enables OSC clock loss event detection.

Enables the clock loss event flag to be raised if a clock loss is detected.

Note
OSC clock loss event must be disabled before SCLK_LF clock source is changed (by calling OSCClockSourceSet()) and remain disabled until the change is confirmed (by calling OSCClockSourceGet()).
Returns
None
See also
OSCClockLossEventDisable()
217 {
218  DDI16BitfieldWrite( AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
219  DDI_0_OSC_CTL0_CLK_LOSS_EN_M,
220  DDI_0_OSC_CTL0_CLK_LOSS_EN_S, 1 );
221 }
void DDI16BitfieldWrite(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift, uint16_t ui32Data)
Write a bit field via the DDI using 16-bit maskable write.
Definition: ddi.c:115
Here is the call graph for this function:

§ OSCClockSourceGet()

uint32_t OSCClockSourceGet ( uint32_t  ui32SrcClk)

Get the source clock settings.

Use this function to get the oscillator source for one of the system source clocks.

Parameters
ui32SrcClkis the source clock to check.
Returns
Returns the type of oscillator that drives the clock source.
See also
OSCClockSourceSet(), OSCHfSourceSwitch()

Referenced by OSCClockLossEventDisable(), OSCHF_AttemptToSwitchToXosc(), OSCHF_SwitchToRcOscTurnOffXosc(), and SetupAfterColdResetWakeupFromShutDownCfg3().

165 {
166  uint32_t ui32ClockSource;
167 
168  // Check the arguments.
169  ASSERT((ui32SrcClk & OSC_SRC_CLK_LF) ||
170  (ui32SrcClk & OSC_SRC_CLK_HF));
171 
172  // Return the source for the selected clock.
173  if(ui32SrcClk == OSC_SRC_CLK_LF)
174  {
175  ui32ClockSource = DDI16BitfieldRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_STAT0,
176  DDI_0_OSC_STAT0_SCLK_LF_SRC_M,
177  DDI_0_OSC_STAT0_SCLK_LF_SRC_S);
178  }
179  else
180  {
181  ui32ClockSource = DDI16BitfieldRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_STAT0,
182  DDI_0_OSC_STAT0_SCLK_HF_SRC_M,
183  DDI_0_OSC_STAT0_SCLK_HF_SRC_S);
184  }
185  return ( ui32ClockSource );
186 }
#define OSC_SRC_CLK_HF
Definition: osc.h:155
#define OSC_SRC_CLK_LF
Definition: osc.h:156
uint16_t DDI16BitfieldRead(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift)
Read a bit field via the DDI using 16-bit read.
Definition: ddi.c:183
#define ASSERT(expr)
Definition: debug.h:71
Here is the call graph for this function:

§ OSCClockSourceSet()

void OSCClockSourceSet ( uint32_t  ui32SrcClk,
uint32_t  ui32Osc 
)

Configure the oscillator input to the a source clock.

Use this function to set the oscillator source for one or more of the system source clocks.

When selecting the high frequency clock source (OSC_SRC_CLK_HF), this function will not do the actual switch. Enabling the high frequency XTAL can take several hundred micro seconds, so the actual switch is done in a separate function, OSCHfSourceSwitch(), leaving System CPU free to perform other tasks as the XTAL starts up.

Note
The High Frequency (OSC_SRC_CLK_HF) can only be derived from the high frequency oscillator. The Low Frequency source clock (OSC_SRC_CLK_LF) can be derived from all 4 oscillators.
If enabling OSC_XOSC_LF it is not safe to go to powerdown/shutdown until the LF clock is running which can be checked using OSCClockSourceGet().
Clock loss reset generation must be disabled before SCLK_LF (OSC_SRC_CLK_LF) clock source is changed and remain disabled until the change is confirmed.
Parameters
ui32SrcClkis the source clocks to configure.
ui32Oscis the oscillator that drives the source clock.
See also
OSCClockSourceGet(), OSCHfSourceSwitch()
Returns
None

Referenced by OSCClockLossEventDisable(), OSCHF_SwitchToRcOscTurnOffXosc(), OSCHF_TurnOnXosc(), and SetupAfterColdResetWakeupFromShutDownCfg3().

128 {
129  // Check the arguments.
130  ASSERT((ui32SrcClk & OSC_SRC_CLK_LF) ||
131  (ui32SrcClk & OSC_SRC_CLK_HF));
132  ASSERT((ui32Osc == OSC_RCOSC_HF) ||
133  (ui32Osc == OSC_RCOSC_LF) ||
134  (ui32Osc == OSC_XOSC_HF) ||
135  (ui32Osc == OSC_XOSC_LF));
136 
137  // Request the high frequency source clock (using 24 MHz XTAL)
138  if(ui32SrcClk & OSC_SRC_CLK_HF)
139  {
140  // Enable the HF XTAL as HF clock source
141  DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
142  DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_M,
143  DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_S,
144  ui32Osc);
145  }
146 
147  // Configure the low frequency source clock.
148  if(ui32SrcClk & OSC_SRC_CLK_LF)
149  {
150  // Change the clock source.
151  DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
152  DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_M,
153  DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_S,
154  ui32Osc);
155  }
156 }
void DDI16BitfieldWrite(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift, uint16_t ui32Data)
Write a bit field via the DDI using 16-bit maskable write.
Definition: ddi.c:115
#define OSC_SRC_CLK_HF
Definition: osc.h:155
#define OSC_RCOSC_HF
Definition: osc.h:158
#define OSC_XOSC_HF
Definition: osc.h:159
#define OSC_SRC_CLK_LF
Definition: osc.h:156
#define ASSERT(expr)
Definition: debug.h:71
#define OSC_RCOSC_LF
Definition: osc.h:160
#define OSC_XOSC_LF
Definition: osc.h:161
Here is the call graph for this function:

§ OSCHF_AttemptToSwitchToXosc()

bool OSCHF_AttemptToSwitchToXosc ( void  )

Switch to XOSC_HF if XOSC_HF is ready.

This is a non-blocking function checking if the XOSC_HF is ready and performs the switching if ready. The function is somewhat blocking in the case where switching is performed.

Returns
Returns status of the XOSC_HF switching:
  • true : Switching to XOSC_HF has occurred.
  • false : Switching has not occurred.

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock(), and OSCHF_DebugGetCrystalStartupTime().

272 {
273  uint32_t startupTimeInUs;
274  uint32_t prevLimmit25InUs;
275 
276 #if ( defined( ROM_OSCClockSourceGet ))
278 #else
280 #endif
281  {
282  // Already on XOSC - nothing to do
283  return ( 1 );
284  }
285  if ( OSCHfSourceReady()) {
287 
288  // Store startup time, but limit to 25 percent reduction each time.
291  prevLimmit25InUs = oscHfGlobals.previousStartupTimeInUs;
292  prevLimmit25InUs -= ( prevLimmit25InUs >> 2 ); // 25 percent margin
293  oscHfGlobals.previousStartupTimeInUs = startupTimeInUs;
294  if ( prevLimmit25InUs > startupTimeInUs ) {
295  oscHfGlobals.previousStartupTimeInUs = prevLimmit25InUs;
296  }
297  return ( 1 );
298  }
299  return ( 0 );
300 }
static void OSCHfSourceSwitch(void)
Switch the high frequency clock.
Definition: osc.h:350
#define ROM_OSCClockSourceGet
Definition: rom.h:688
uint32_t timeXoscStable_CV
Definition: osc.c:107
uint32_t OSCClockSourceGet(uint32_t ui32SrcClk)
Get the source clock settings.
Definition: osc.c:164
#define OSC_SRC_CLK_HF
Definition: osc.h:155
static bool OSCHfSourceReady(void)
Check if the HF clock source is ready to be switched.
Definition: osc.h:322
#define OSC_XOSC_HF
Definition: osc.h:159
uint32_t previousStartupTimeInUs
Definition: osc.c:104
static OscHfGlobals_t oscHfGlobals
Definition: osc.c:111
uint32_t timeXoscOn_CV
Definition: osc.c:106
#define RTC_CV_TO_US(x)
Definition: osc.c:101
static uint32_t AONRTCCurrentCompareValueGet(void)
Get the current value of the RTC counter in a format that matches RTC compare values.
Definition: aon_rtc.h:818
Here is the call graph for this function:

§ OSCHF_DebugGetCrystalAmplitude()

uint32_t OSCHF_DebugGetCrystalAmplitude ( void  )

Get crystal amplitude (assuming crystal is running).

Note
This is a debug function only. It is hence not recommended to call this function in normal operation.

This function uses an on-chip ADC and peak detector for reading the crystal amplitude. The measurement time is set to 4 milliseconds and this function does not return before the measurement is done.

Expected value is OSCHF_DebugGetExpectedAverageCrystalAmplitude +/- 50 millivolt.

Returns
Returns crystal amplitude in millivolt.
See also
OSCHF_DebugGetExpectedAverageCrystalAmplitude()

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock().

839 {
840  uint32_t oscCfgRegCopy ;
841  uint32_t startTime ;
842  uint32_t deltaTime ;
843  uint32_t ampValue ;
844 
845  // The specified method is as follows:
846  // 1. Set minimum interval between oscillator amplitude calibrations.
847  // (Done by setting PER_M=0 and PER_E=1)
848  // 2. Wait approximately 4 milliseconds in order to measure over a
849  // moderately large number of calibrations.
850  // 3. Read out the crystal amplitude value from the peek detector.
851  // 4. Restore original oscillator amplitude calibrations interval.
852  // 5. Return crystal amplitude value converted to millivolt.
853 
854  oscCfgRegCopy = HWREG( AON_PMCTL_BASE + AON_PMCTL_O_OSCCFG );
855  HWREG( AON_PMCTL_BASE + AON_PMCTL_O_OSCCFG ) = ( 1 << AON_PMCTL_OSCCFG_PER_E_S );
856 
857  startTime = AONRTCCurrentCompareValueGet();
858  do {
859  deltaTime = AONRTCCurrentCompareValueGet() - startTime;
860  } while ( deltaTime < ((uint32_t)( 0.004 * FACTOR_SEC_TO_COMP_VAL_FORMAT )));
861  ampValue = ( HWREG( AUX_DDI0_OSC_BASE + DDI_0_OSC_O_STAT1 ) &
862  DDI_0_OSC_STAT1_HPM_UPDATE_AMP_M ) >>
863  DDI_0_OSC_STAT1_HPM_UPDATE_AMP_S ;
864 
865  HWREG( AON_PMCTL_BASE + AON_PMCTL_O_OSCCFG ) = oscCfgRegCopy;
866 
867  return ( ampValue * 15 );
868 }
#define FACTOR_SEC_TO_COMP_VAL_FORMAT
Definition: aon_rtc.h:149
static uint32_t AONRTCCurrentCompareValueGet(void)
Get the current value of the RTC counter in a format that matches RTC compare values.
Definition: aon_rtc.h:818
Here is the call graph for this function:

§ OSCHF_DebugGetCrystalStartupTime()

uint32_t OSCHF_DebugGetCrystalStartupTime ( void  )

Measure the crystal startup time.

Note
This is a debug function that should not be needed in normal operation.

This function assumes that the chip is running on RCOSC_HF when called. It then switches to XOSC_HF while measuring number of LF-clock edges before XOSC_HF has started and are ready to be used. After that, the function switches back to RCOSC_HF and returns number of LF-edges found.

The length in time between the LF clock edges is approximately 15 microseconds. Or more exactly: LF_clock_edges / ( 32768 * 2 ) seconds.

Please note that the startup time, in addition to the crystal itself also can vary depending on the time since the crystal was stopped and the frequency of the RCOSC_HF oscillator. Calling this function intensively will show a shorter startup time than in typical use cases. When running with TI-RTOS there is a background task (optional but default on) adjusting RCOSC_HF to be as equal as possible to the crystal frequency, giving the shortest possible startup time.

Returns
Returns number of LF-clock edges from starting the crystal until it's ready to be used.

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock().

897 {
898  uint32_t lfEdgesFound = 0 ;
899 
900  // Start operation in sync with the LF clock
901  HWREG( AON_RTC_BASE + AON_RTC_O_SYNCLF );
902 
904  while ( ! OSCHF_AttemptToSwitchToXosc() ) {
905  HWREG( AON_RTC_BASE + AON_RTC_O_SYNCLF );
906  lfEdgesFound ++ ;
907  }
909 
910  return ( lfEdgesFound );
911 }
bool OSCHF_AttemptToSwitchToXosc(void)
Switch to XOSC_HF if XOSC_HF is ready.
Definition: osc.c:271
void OSCHF_SwitchToRcOscTurnOffXosc(void)
Switch to RCOSC_HF and turn off XOSC_HF.
Definition: osc.c:309
void OSCHF_TurnOnXosc(void)
Turns on XOSC_HF (but without switching to XOSC_HF).
Definition: osc.c:254
Here is the call graph for this function:

§ OSCHF_DebugGetExpectedAverageCrystalAmplitude()

uint32_t OSCHF_DebugGetExpectedAverageCrystalAmplitude ( void  )

Get the expected average crystal amplitude.

Note
This is a debug function only. It is hence not recommended to call this function in normal operation.

This function read the configured high and low thresholds and returns the mean value converted to millivolt.

Returns
Returns expected average crystal amplitude in millivolt.
See also
OSCHF_DebugGetCrystalAmplitude()

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock().

877 {
878  uint32_t ampCompTh1 ;
879  uint32_t highThreshold ;
880  uint32_t lowThreshold ;
881 
882  ampCompTh1 = HWREG( AUX_DDI0_OSC_BASE + DDI_0_OSC_O_AMPCOMPTH1 );
883  highThreshold = ( ampCompTh1 & DDI_0_OSC_AMPCOMPTH1_HPMRAMP3_HTH_M ) >>
884  DDI_0_OSC_AMPCOMPTH1_HPMRAMP3_HTH_S ;
885  lowThreshold = ( ampCompTh1 & DDI_0_OSC_AMPCOMPTH1_HPMRAMP3_LTH_M ) >>
886  DDI_0_OSC_AMPCOMPTH1_HPMRAMP3_LTH_S ;
887 
888  return ((( highThreshold + lowThreshold ) * 15 ) >> 1 );
889 }

§ OSCHF_GetStartupTime()

uint32_t OSCHF_GetStartupTime ( uint32_t  timeUntilWakeupInMs)

Returns maximum startup time (in microseconds) of XOSC_HF.

The startup time depends on several factors. This function calculates the maximum startup time based on statistical information.

Parameters
timeUntilWakeupInMsindicates how long time (milliseconds) to the startup will occur.
Returns
Time margin to use in microseconds.

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock().

195 {
196  uint32_t deltaTimeSinceXoscOnInMs ;
197  int32_t deltaTempSinceXoscOn ;
198  uint32_t newStartupTimeInUs ;
199 
200  // Check CCFG to determine if device is configured for TCXO.
201  if( ( HWREG( CCFG_BASE + CCFG_O_MODE_CONF ) & CCFG_MODE_CONF_XOSC_FREQ_M ) == CCFG_MODE_CONF_XOSC_FREQ_TCXO )
202  {
203  // Device configured for TCXO. Report fixed startup time located in CCFG with
204  // coversion from number of 100us to number of us.
205  newStartupTimeInUs = (( HWREG( CCFG_BASE + CCFG_O_MODE_CONF_1 ) & CCFG_MODE_CONF_1_TCXO_MAX_START_M ) >>
206  CCFG_MODE_CONF_1_TCXO_MAX_START_S ) * 100;
207  }
208  else
209  {
210  deltaTimeSinceXoscOnInMs = RTC_CV_TO_MS( AONRTCCurrentCompareValueGet() - oscHfGlobals.timeXoscOn_CV );
211  deltaTempSinceXoscOn = AONBatMonTemperatureGetDegC() - oscHfGlobals.tempXoscOff;
212 
213  if ( deltaTempSinceXoscOn < 0 ) {
214  deltaTempSinceXoscOn = -deltaTempSinceXoscOn;
215  }
216 
217  if ( (( timeUntilWakeupInMs + deltaTimeSinceXoscOnInMs ) > 3000 ) ||
218  ( deltaTempSinceXoscOn > 5 ) ||
221  {
222  newStartupTimeInUs = 2000;
223  if (( HWREG( CCFG_BASE + CCFG_O_SIZE_AND_DIS_FLAGS ) & CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR_M ) == 0 ) {
224  newStartupTimeInUs = (( HWREG( CCFG_BASE + CCFG_O_MODE_CONF_1 ) &
225  CCFG_MODE_CONF_1_XOSC_MAX_START_M ) >>
226  CCFG_MODE_CONF_1_XOSC_MAX_START_S ) * 125;
227  // Note: CCFG startup time is "in units of 100us" adding 25% margin results in *125
228  }
229  } else {
231  newStartupTimeInUs += ( newStartupTimeInUs >> 2 ); // Add 25 percent margin
232  if ( newStartupTimeInUs < oscHfGlobals.previousStartupTimeInUs ) {
233  newStartupTimeInUs = oscHfGlobals.previousStartupTimeInUs;
234  }
235  }
236 
237  if ( newStartupTimeInUs < 200 ) {
238  newStartupTimeInUs = 200;
239  }
240  if ( newStartupTimeInUs > 4000 ) {
241  newStartupTimeInUs = 4000;
242  }
243  }
244  return ( newStartupTimeInUs );
245 }
uint32_t timeXoscStable_CV
Definition: osc.c:107
int32_t AONBatMonTemperatureGetDegC(void)
Get the current temperature measurement as a signed value in Deg Celsius.
Definition: aon_batmon.c:58
uint32_t previousStartupTimeInUs
Definition: osc.c:104
static OscHfGlobals_t oscHfGlobals
Definition: osc.c:111
int32_t tempXoscOff
Definition: osc.c:108
uint32_t timeXoscOn_CV
Definition: osc.c:106
#define RTC_CV_TO_US(x)
Definition: osc.c:101
static uint32_t AONRTCCurrentCompareValueGet(void)
Get the current value of the RTC counter in a format that matches RTC compare values.
Definition: aon_rtc.h:818
#define RTC_CV_TO_MS(x)
Definition: osc.c:100
Here is the call graph for this function:

§ OSCHF_SwitchToRcOscTurnOffXosc()

void OSCHF_SwitchToRcOscTurnOffXosc ( void  )

Switch to RCOSC_HF and turn off XOSC_HF.

This operation takes approximately 50 microseconds (can be shorter if RCOSC_HF already was running).

Returns
None

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock(), and OSCHF_DebugGetCrystalStartupTime().

310 {
311 #if ( defined( ROM_OSCClockSourceSet ))
313 #else
315 #endif
316 
317  // Do the switching if not already running on RCOSC_HF
318 #if ( defined( ROM_OSCClockSourceGet ))
320 #else
322 #endif
323  {
325  }
326 
329 }
static void OSCHfSourceSwitch(void)
Switch the high frequency clock.
Definition: osc.h:350
#define ROM_OSCClockSourceSet
Definition: rom.h:692
uint32_t timeXoscOff_CV
Definition: osc.c:105
#define ROM_OSCClockSourceGet
Definition: rom.h:688
int32_t AONBatMonTemperatureGetDegC(void)
Get the current temperature measurement as a signed value in Deg Celsius.
Definition: aon_batmon.c:58
uint32_t OSCClockSourceGet(uint32_t ui32SrcClk)
Get the source clock settings.
Definition: osc.c:164
#define OSC_SRC_CLK_HF
Definition: osc.h:155
#define OSC_RCOSC_HF
Definition: osc.h:158
static OscHfGlobals_t oscHfGlobals
Definition: osc.c:111
int32_t tempXoscOff
Definition: osc.c:108
void OSCClockSourceSet(uint32_t ui32SrcClk, uint32_t ui32Osc)
Configure the oscillator input to the a source clock.
Definition: osc.c:127
static uint32_t AONRTCCurrentCompareValueGet(void)
Get the current value of the RTC counter in a format that matches RTC compare values.
Definition: aon_rtc.h:818
Here is the call graph for this function:

§ OSCHF_TurnOnXosc()

void OSCHF_TurnOnXosc ( void  )

Turns on XOSC_HF (but without switching to XOSC_HF).

This function simply indicates the need for XOSC_HF to the hardware which initiates the XOSC_HF startup.

Returns
None

Referenced by OSC_IsHPOSCEnabledWithHfDerivedLfClock(), and OSCHF_DebugGetCrystalStartupTime().

255 {
256 #if ( defined( ROM_OSCClockSourceSet ))
258 #else
260 #endif
262 }
#define ROM_OSCClockSourceSet
Definition: rom.h:692
#define OSC_SRC_CLK_HF
Definition: osc.h:155
#define OSC_XOSC_HF
Definition: osc.h:159
static OscHfGlobals_t oscHfGlobals
Definition: osc.c:111
uint32_t timeXoscOn_CV
Definition: osc.c:106
void OSCClockSourceSet(uint32_t ui32SrcClk, uint32_t ui32Osc)
Configure the oscillator input to the a source clock.
Definition: osc.c:127
static uint32_t AONRTCCurrentCompareValueGet(void)
Get the current value of the RTC counter in a format that matches RTC compare values.
Definition: aon_rtc.h:818
Here is the call graph for this function:

§ OSCHfSourceReady()

static bool OSCHfSourceReady ( void  )
inlinestatic

Check if the HF clock source is ready to be switched.

If a request to switch the HF clock source has been made, this function can be used to check if the clock source is ready to be switched.

Once the HF clock source is ready the switch can be performed by calling the OSCHfSourceSwitch()

Returns
Returns status of HF clock source:
  • true : HF clock source is ready.
  • false : HF clock source is not ready.

Referenced by OSCHF_AttemptToSwitchToXosc().

323 {
324  // Return the readiness of the HF clock source
325  return (DDI16BitfieldRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_STAT0,
326  DDI_0_OSC_STAT0_PENDINGSCLKHFSWITCHING_M,
327  DDI_0_OSC_STAT0_PENDINGSCLKHFSWITCHING_S)) ?
328  true : false;
329 }
uint16_t DDI16BitfieldRead(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift)
Read a bit field via the DDI using 16-bit read.
Definition: ddi.c:183
Here is the call graph for this function:

§ OSCHfSourceSwitch()

static void OSCHfSourceSwitch ( void  )
inlinestatic

Switch the high frequency clock.

When switching the HF clock source the clock period might be prolonged leaving the clock 'stuck-at' high or low for a few cycles. To ensure that this does not coincide with a read access to the Flash, potentially freezing the device, the HF clock source switch must be executed from ROM.

Note
This function will not return until the clock source has been switched. It is left to the programmer to ensure, that there is a pending request for a HF clock source switch before this function is called.
Returns
None
See also
OSCClockSourceSet()

Referenced by OSCHF_AttemptToSwitchToXosc(), and OSCHF_SwitchToRcOscTurnOffXosc().

351 {
352  // Read target clock (lower half of the 32-bit CTL0 register)
353  uint16_t hfSrc = HWREGH(AUX_DDI0_OSC_BASE + DDI_0_OSC_O_CTL0) & DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_M;
354 
355  // If target clock source is RCOSC, change clock source for DCDC to RCOSC
356  if(hfSrc == DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_RCOSC)
357  {
358  // Force DCDC to use RCOSC before switching SCLK_HF to RCOSC
359  HWREG(AUX_DDI0_OSC_BASE + DDI_O_MASK16B + (DDI_0_OSC_O_CTL0 << 1) + 4) = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_M | (DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_M >> 16);
360  // Dummy read to ensure that the write has propagated
361  HWREGH(AUX_DDI0_OSC_BASE + DDI_0_OSC_O_CTL0);
362  }
363 
364  // Switch the HF clock source
366 
367  // If target clock source is XOSC, change clock source for DCDC to "auto"
368  if(hfSrc == DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_XOSC)
369  {
370  // Set DCDC clock source back to "auto" after SCLK_HF was switched to XOSC
371  HWREG(AUX_DDI0_OSC_BASE + DDI_O_MASK16B + (DDI_0_OSC_O_CTL0 << 1) + 4) = DDI_0_OSC_CTL0_CLK_DCDC_SRC_SEL_M;
372  }
373 }
#define HapiHFSourceSafeSwitch()
Definition: rom.h:152

§ OSCXHfPowerModeSet()

static void OSCXHfPowerModeSet ( uint32_t  ui32Mode)
inlinestatic

Set Power Mode for High Frequency XTAL Oscillator.

Parameters
ui32Modeis the power mode for the HF XTAL.
Returns
None
190 {
191  // Check the arguments.
192  ASSERT((ui32Mode == LOW_POWER_XOSC) ||
193  (ui32Mode == HIGH_POWER_XOSC));
194 
195  // Change the power mode.
196  DDI16BitWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0, DDI_0_OSC_CTL0_XOSC_HF_POWER_MODE,
197  ui32Mode);
198 }
#define LOW_POWER_XOSC
Definition: osc.h:147
void DDI16BitWrite(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32WrData)
Write a single bit using a 16-bit maskable write.
Definition: ddi.c:81
#define HIGH_POWER_XOSC
Definition: osc.h:148
#define ASSERT(expr)
Definition: debug.h:71
Here is the call graph for this function:

Macro Definition Documentation

§ HIGH_POWER_XOSC

#define HIGH_POWER_XOSC   0

Referenced by OSCXHfPowerModeSet().

§ LOW_POWER_XOSC

#define LOW_POWER_XOSC   1

Referenced by OSCXHfPowerModeSet().

§ OSC_RCOSC_HF

#define OSC_RCOSC_HF   0x00000000

§ OSC_RCOSC_LF

#define OSC_RCOSC_LF   0x00000002

§ OSC_SRC_CLK_HF

§ OSC_SRC_CLK_LF

#define OSC_SRC_CLK_LF   0x00000004

§ OSC_XOSC_HF

§ OSC_XOSC_LF

#define OSC_XOSC_LF   0x00000003

§ SCLK_HF_RCOSC_HF

#define SCLK_HF_RCOSC_HF   0

§ SCLK_HF_XOSC_HF

#define SCLK_HF_XOSC_HF   1

§ SCLK_LF_FROM_RCOSC_HF

#define SCLK_LF_FROM_RCOSC_HF   0

§ SCLK_LF_FROM_RCOSC_LF

#define SCLK_LF_FROM_RCOSC_LF   2

§ SCLK_LF_FROM_XOSC_HF

#define SCLK_LF_FROM_XOSC_HF   1

§ SCLK_LF_FROM_XOSC_LF

#define SCLK_LF_FROM_XOSC_LF   3