1 /******************************************************************************
2 *  Filename:       osc.h
3 *  Revised:        2015-11-11 17:32:44 +0100 (Wed, 11 Nov 2015)
4 *  Revision:       45043
5 *
6 *  Description:    Defines and prototypes for the system oscillator control.
7 *
8 *  Copyright (c) 2015, Texas Instruments Incorporated
9 *  All rights reserved.
10 *
11 *  Redistribution and use in source and binary forms, with or without
12 *  modification, are permitted provided that the following conditions are met:
13 *
14 *  1) Redistributions of source code must retain the above copyright notice,
15 *     this list of conditions and the following disclaimer.
16 *
17 *  2) Redistributions in binary form must reproduce the above copyright notice,
18 *     this list of conditions and the following disclaimer in the documentation
19 *     and/or other materials provided with the distribution.
20 *
21 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 *     be used to endorse or promote products derived from this software without
23 *     specific prior written permission.
24 *
25 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 *  POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 //*****************************************************************************
40 //
41 //! \addtogroup system_control_group
42 //! @{
43 //! \addtogroup osc_api
44 //! @{
45 //
46 //*****************************************************************************
47 
48 #ifndef __OSC_H__
49 #define __OSC_H__
50 
51 //*****************************************************************************
52 //
53 // If building with a C++ compiler, make all of the definitions in this header
54 // have a C binding.
55 //
56 //*****************************************************************************
57 #ifdef __cplusplus
58 extern "C"
59 {
60 #endif
61 
62 #include <stdbool.h>
63 #include <stdint.h>
64 #include <inc/hw_types.h>
65 #include <inc/hw_memmap.h>
66 #include <inc/hw_ddi.h>
67 #include <inc/hw_ddi_0_osc.h>
68 #include <driverlib/aon_wuc.h>
69 #include <driverlib/aux_wuc.h>
70 #include <driverlib/rom.h>
71 #include <driverlib/ddi.h>
72 #include <driverlib/debug.h>
73 
74 //*****************************************************************************
75 //
76 // Support for DriverLib in ROM:
77 // This section renames all functions that are not "static inline", so that
78 // calling these functions will default to implementation in flash. At the end
79 // of this file a second renaming will change the defaults to implementation in
80 // ROM for available functions.
81 //
82 // To force use of the implementation in flash, e.g. for debugging:
83 // - Globally: Define DRIVERLIB_NOROM at project level
84 // - Per function: Use prefix "NOROM_" when calling the function
85 //
86 //*****************************************************************************
87 #if !defined(DOXYGEN)
88     #define OSCClockSourceSet               NOROM_OSCClockSourceSet
89     #define OSCClockSourceGet               NOROM_OSCClockSourceGet
90     #define OSCInterfaceEnable              NOROM_OSCInterfaceEnable
91 #endif
92 
93 //*****************************************************************************
94 //
95 // Defines for the High Frequency XTAL Power mode
96 //
97 //*****************************************************************************
98 #define LOW_POWER_XOSC          1
99 #define HIGH_POWER_XOSC         0
100 
101 //*****************************************************************************
102 //
103 // Defines for the High Frequency XTAL Power mode
104 //
105 //*****************************************************************************
106 #define OSC_SRC_CLK_HF          0x00000001
107 #define OSC_SRC_CLK_MF          0x00000002
108 #define OSC_SRC_CLK_LF          0x00000004
109 
110 #define OSC_RCOSC_HF            0x00000000
111 #define OSC_XOSC_HF             0x00000001
112 #define OSC_RCOSC_LF            0x00000002
113 #define OSC_XOSC_LF             0x00000003
114 
115 #define SCLK_HF_RCOSC_HF        0
116 #define SCLK_HF_XOSC_HF         1
117 
118 #define SCLK_MF_RCOSC_HF        0
119 #define SCLK_MF_XOSC_HF         1
120 
121 #define SCLK_LF_FROM_RCOSC_HF   0
122 #define SCLK_LF_FROM_XOSC_HF    1
123 #define SCLK_LF_FROM_RCOSC_LF   2
124 #define SCLK_LF_FROM_XOSC_LF    3
125 
126 //*****************************************************************************
127 //
128 // API Functions and prototypes
129 //
130 //*****************************************************************************
131 
132 //*****************************************************************************
133 //
134 //! \brief Set Power Mode for High Frequency XTAL Oscillator.
135 //!
136 //! \param ui32Mode is the power mode for the HF XTAL.
137 //! - \ref LOW_POWER_XOSC
138 //! - \ref HIGH_POWER_XOSC
139 //!
140 //! \return None
141 //
142 //*****************************************************************************
143 __STATIC_INLINE void
OSCXHfPowerModeSet(uint32_t ui32Mode)144 OSCXHfPowerModeSet(uint32_t ui32Mode)
145 {
146     //
147     // Check the arguments.
148     //
149     ASSERT((ui32Mode == LOW_POWER_XOSC) ||
150            (ui32Mode == HIGH_POWER_XOSC));
151 
152     //
153     // Change the power mode.
154     //
155     DDI16BitWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0, DDI_0_OSC_CTL0_XOSC_HF_POWER_MODE,
156                   ui32Mode);
157 }
158 
159 //*****************************************************************************
160 //
161 //! \brief Enables OSC clock loss event detection.
162 //!
163 //! Enables the clock loss event flag to be raised if a clock loss is detected.
164 //!
165 //! \note OSC clock loss event must be disabled before SCLK_LF clock source is
166 //! changed (by calling \ref OSCClockSourceSet()) and remain disabled until the
167 //! change is confirmed (by calling \ref OSCClockSourceGet()).
168 //!
169 //! \return None
170 //!
171 //! \sa \ref OSCClockLossEventDisable()
172 //
173 //*****************************************************************************
174 __STATIC_INLINE void
OSCClockLossEventEnable(void)175 OSCClockLossEventEnable( void )
176 {
177     DDI16BitfieldWrite( AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
178         DDI_0_OSC_CTL0_CLK_LOSS_EN_M,
179         DDI_0_OSC_CTL0_CLK_LOSS_EN_S, 1 );
180 }
181 
182 //*****************************************************************************
183 //
184 //! \brief Disables OSC clock loss event detection.
185 //!
186 //! Disabling the OSC clock loss event does also clear the clock loss event flag.
187 //!
188 //! \note OSC clock loss event must be disabled before SCLK_LF clock source is
189 //! changed (by calling \ref OSCClockSourceSet()) and remain disabled until the
190 //! change is confirmed (by calling \ref OSCClockSourceGet()).
191 //!
192 //! \return None
193 //!
194 //! \sa \ref OSCClockLossEventEnable()
195 //
196 //*****************************************************************************
197 __STATIC_INLINE void
OSCClockLossEventDisable(void)198 OSCClockLossEventDisable( void )
199 {
200     DDI16BitfieldWrite( AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
201         DDI_0_OSC_CTL0_CLK_LOSS_EN_M,
202         DDI_0_OSC_CTL0_CLK_LOSS_EN_S, 0 );
203 }
204 
205 //*****************************************************************************
206 //
207 //! \brief Configure the oscillator input to the a source clock.
208 //!
209 //! Use this function to set the oscillator source for one or more of the
210 //! system source clocks.
211 //!
212 //! When selecting the high frequency clock source, this function will not do
213 //! the actual switch. Enabling the high frequency XTAL can take several hundred
214 //! micro seconds, so the actual switch is split into a separate function,
215 //! leaving System CPU free to perform other tasks as the XTAL starts up.
216 //!
217 //! \note The High Frequency (\ref OSC_SRC_CLK_HF) and Medium Frequency
218 //! (\ref OSC_SRC_CLK_MF) can only be derived from the high frequency
219 //! oscillator. The Low Frequency source clock (\ref OSC_SRC_CLK_LF) can be
220 //! derived from all 4 oscillators.
221 //!
222 //! \note If enabling \ref OSC_XOSC_LF it is not safe to go to powerdown/shutdown
223 //! until the LF clock is running which can be checked using \ref OSCClockSourceGet().
224 //!
225 //! \note Clock loss reset generation must be disabled before SCLK_LF (\ref OSC_SRC_CLK_LF)
226 //! clock source is changed and remain disabled until the change is confirmed.
227 //!
228 //! \param ui32SrcClk is the source clocks to configure.
229 //! - \ref OSC_SRC_CLK_HF
230 //! - \ref OSC_SRC_CLK_MF
231 //! - \ref OSC_SRC_CLK_LF
232 //! \param ui32Osc is the oscillator that drives the source clock.
233 //! - \ref OSC_RCOSC_HF
234 //! - \ref OSC_XOSC_HF
235 //! - \ref OSC_RCOSC_LF (only when ui32SrcClk is \ref OSC_SRC_CLK_LF)
236 //! - \ref OSC_XOSC_LF (only when ui32SrcClk is \ref OSC_SRC_CLK_LF)
237 //!
238 //! \sa OSCClockSourceGet()
239 //!
240 //! \return None
241 //
242 //*****************************************************************************
243 extern void OSCClockSourceSet(uint32_t ui32SrcClk, uint32_t ui32Osc);
244 
245 //*****************************************************************************
246 //
247 //! \brief Get the source clock settings.
248 //!
249 //! Use this function to get the oscillator source for one of the system source
250 //! clocks.
251 //!
252 //! \param ui32SrcClk is the source clock to check.
253 //! - \ref OSC_SRC_CLK_HF
254 //! - \ref OSC_SRC_CLK_MF
255 //! - \ref OSC_SRC_CLK_LF
256 //!
257 //! \return Returns the type of oscillator that drives the clock source.
258 //! - \ref OSC_RCOSC_HF
259 //! - \ref OSC_XOSC_HF
260 //! - \ref OSC_RCOSC_LF
261 //! - \ref OSC_XOSC_LF
262 //!
263 //! \sa \ref OSCClockSourceSet(), \ref OSCHfSourceSwitch()
264 //
265 //*****************************************************************************
266 extern uint32_t OSCClockSourceGet(uint32_t ui32SrcClk);
267 
268 //*****************************************************************************
269 //
270 //! \brief Check if the HF clock source is ready to be switched.
271 //!
272 //! If a request to switch the HF clock source has been made, this function
273 //! can be used to check if the clock source is ready to be switched.
274 //!
275 //! Once the HF clock source is ready the switch can be performed by calling
276 //! the \ref OSCHfSourceSwitch()
277 //!
278 //! \return Returns status of HF clock source:
279 //! - \c true  : HF clock source is ready.
280 //! - \c false : HF clock source is \b not ready.
281 //
282 //*****************************************************************************
283 __STATIC_INLINE bool
OSCHfSourceReady(void)284 OSCHfSourceReady(void)
285 {
286     //
287     // Return the readiness of the HF clock source
288     //
289     return (DDI16BitfieldRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_STAT0,
290                               DDI_0_OSC_STAT0_PENDINGSCLKHFSWITCHING_M,
291                               DDI_0_OSC_STAT0_PENDINGSCLKHFSWITCHING_S)) ?
292         true : false;
293 }
294 
295 //*****************************************************************************
296 //
297 //! \brief Switch the high frequency clock.
298 //!
299 //! When switching the HF clock source the clock period might be prolonged
300 //! leaving the clock 'stuck-at' high or low for a few cycles. To ensure that
301 //! this does not coincide with a read access to the Flash potentially
302 //! freezing the device, the HF clock source switch must be executed from ROM.
303 //!
304 //! \note This function will not return until the clock source has been
305 //! switched. It is left to the programmer to ensure, that there is a pending
306 //! request for a HF clock source switch before this function is called.
307 //!
308 //! \return None
309 //!
310 //! \sa \ref OSCClockSourceSet()
311 //
312 //*****************************************************************************
313 __STATIC_INLINE void
OSCHfSourceSwitch(void)314 OSCHfSourceSwitch(void)
315 {
316     //
317     // Switch the HF clock source
318     //
319     HapiHFSourceSafeSwitch();
320 }
321 
322 //*****************************************************************************
323 //
324 //! \brief Enable System CPU access to the OSC_DIG module.
325 //!
326 //! Force power on AUX and enable clocks to allow System CPU access on the OSC_DIG
327 //! interface.
328 //!
329 //! \note Access to the OSC_DIG interface is a shared resource between the
330 //! Sensor Controller and the CPU, so enabling or disabling this interface must
331 //! be done with consideration.
332 //!
333 //! \return None
334 //
335 //*****************************************************************************
336 extern void OSCInterfaceEnable(void);
337 
338 //*****************************************************************************
339 //
340 //! \brief Disable System CPU access to the OSC_DIG module.
341 //!
342 //! Release the "force power on" of AUX and disable clock to AUX.
343 //!
344 //! \note Access to the OSC_DIG interface is a shared resource between the
345 //! Sensor Controller and the CPU, so enabling or disabling this interface must
346 //! be done with consideration.
347 //!
348 //! \return None
349 //
350 //*****************************************************************************
351 __STATIC_INLINE void
OSCInterfaceDisable(void)352 OSCInterfaceDisable(void)
353 {
354     //
355     // Disable clock for OSC_DIG
356     //
357     AUXWUCClockDisable(AUX_WUC_OSCCTRL_CLOCK);
358 
359     //
360     // Release the 'force power' on AUX
361     //
362     AONWUCAuxWakeupEvent(AONWUC_AUX_ALLOW_SLEEP);
363 }
364 
365 
366 //*****************************************************************************
367 //
368 //! \brief Returns maximum startup time (in microseconds) of XOSC_HF.
369 //!
370 //! The startup time depends on several factors. This function calculates the
371 //! maximum startup time based on statistical information.
372 //!
373 //! \param timeUntilWakeupInMs indicates how long time (milliseconds) to the
374 //! startup will occur.
375 //!
376 //! \return Time margin to use in microseconds.
377 //
378 //*****************************************************************************
379 uint32_t OSCHF_GetStartupTime( uint32_t timeUntilWakeupInMs );
380 
381 
382 //*****************************************************************************
383 //
384 //! \brief Turns on XOSC_HF (but without switching to XOSC_HF).
385 //!
386 //! This function simply indicates the need for XOSC_HF to the hardware which
387 //! initiates the XOSC_HF startup.
388 //!
389 //! \return None
390 //
391 //*****************************************************************************
392 void OSCHF_TurnOnXosc( void );
393 
394 
395 //*****************************************************************************
396 //
397 //! \brief Switch to XOSC_HF if XOSC_HF is ready.
398 //!
399 //! This is a non-blocking function checking if the XOSC_HF is ready and
400 //! performs the switching if ready. The function is somewhat blocking in the
401 //! case where switching is performed.
402 //!
403 //! \return Returns status of the XOSC_HF switching:
404 //! - \c true  : Switching to XOSC_HF has occurred.
405 //! - \c false : Switching has not occurred.
406 //
407 //*****************************************************************************
408 bool OSCHF_AttemptToSwitchToXosc( void );
409 
410 
411 //*****************************************************************************
412 //
413 //! \brief Switch to RCOSC_HF and turn off XOSC_HF.
414 //!
415 //! This operation takes approximately 50 microseconds (can be shorter if
416 //! RCOSC_HF already was running).
417 //!
418 //! \return None
419 //
420 //*****************************************************************************
421 void OSCHF_SwitchToRcOscTurnOffXosc( void );
422 
423 //*****************************************************************************
424 //
425 //! \brief Calculate the temperature dependent relative frequency offset of HPOSC
426 //!
427 //! The HPOSC (High Precision Oscillator) frequency will vary slightly with chip temperature.
428 //! The frequency offset from the nominal value can be predicted based on
429 //! second order linear interpolation using coefficients measured in chip
430 //! production and stored as factory configuration parameters.
431 //!
432 //! This function calculates the relative frequency offset, defined as:
433 //! <pre>
434 //!     F_HPOSC = F_nom * (1 + d/(2^22))
435 //! </pre>
436 //! where
437 //! -   F_HPOSC is the current HPOSC frequency.
438 //! -   F_nom is the nominal oscillator frequency, assumed to be 48.000 MHz.
439 //! -   d is the relative frequency offset (the value returned).
440 //!
441 //! By knowing the relative frequency offset it is then possible to compensate
442 //! any timing related values accordingly.
443 //!
444 //! \param tempDegC is the chip temperature in degrees Celsius. Use the
445 //! function \ref AONBatMonTemperatureGetDegC() to get current chip temperature.
446 //!
447 //! \return Returns the relative frequency offset parameter d.
448 //!
449 //! \sa OSC_HPOSCRelativeFrequencyOffsetToRFCoreFormatConvert(), AONBatMonTemperatureGetDegC()
450 //
451 //*****************************************************************************
452 extern int32_t OSC_HPOSCRelativeFrequencyOffsetGet( int32_t tempDegC );
453 
454 //*****************************************************************************
455 //
456 //! \brief Converts the relative frequency offset of HPOSC to the RF Core parameter format.
457 //!
458 //! The HPOSC (High Precision Oscillator) clock is used by the RF Core.
459 //! To compensate for a frequency offset in the frequency of the clock source,
460 //! a frequency offset parameter can be provided as part of the radio configuration
461 //! override setting list to enable compensation of the RF synthesizer frequency,
462 //! symbol timing, and radio timer to still achieve correct frequencies.
463 //!
464 //! The RF Core takes a relative frequency offset parameter defined differently
465 //! compared to the relative frequency offset parameter returned from function
466 //! \ref OSC_HPOSCRelativeFrequencyOffsetGet() and thus needs to be converted:
467 //! <pre>
468 //!     F_nom = F_HPOSC * (1 + RfCoreRelFreqOffset/(2^22))
469 //! </pre>
470 //! where
471 //! -   F_nom is the nominal oscillator frequency, assumed to be 48.000 MHz.
472 //! -   F_HPOSC is the current HPOSC frequency.
473 //! -   RfCoreRelFreqOffset is the relative frequency offset in the "RF Core" format (the value returned).
474 //!
475 //! \return Returns the relative frequency offset in RF Core format.
476 //!
477 //! \sa OSC_HPOSCRelativeFrequencyOffsetGet()
478 //
479 //*****************************************************************************
480 extern int16_t OSC_HPOSCRelativeFrequencyOffsetToRFCoreFormatConvert( int32_t HPOSC_RelFreqOffset );
481 
482 
483 //*****************************************************************************
484 //
485 // Support for DriverLib in ROM:
486 // Redirect to implementation in ROM when available.
487 //
488 //*****************************************************************************
489 #if !defined(DRIVERLIB_NOROM) && !defined(DOXYGEN)
490     #include <driverlib/rom.h>
491     #ifdef ROM_OSCClockSourceSet
492         #undef  OSCClockSourceSet
493         #define OSCClockSourceSet               ROM_OSCClockSourceSet
494     #endif
495     #ifdef ROM_OSCClockSourceGet
496         #undef  OSCClockSourceGet
497         #define OSCClockSourceGet               ROM_OSCClockSourceGet
498     #endif
499     #ifdef ROM_OSCInterfaceEnable
500         #undef  OSCInterfaceEnable
501         #define OSCInterfaceEnable              ROM_OSCInterfaceEnable
502     #endif
503 #endif
504 
505 //*****************************************************************************
506 //
507 // Mark the end of the C bindings section for C++ compilers.
508 //
509 //*****************************************************************************
510 #ifdef __cplusplus
511 }
512 #endif
513 
514 
515 #endif // __OSC_H__
516 
517 //*****************************************************************************
518 //
519 //! Close the Doxygen group.
520 //! @}
521 //! @}
522 //
523 //*****************************************************************************
524