CC26xx Driver Library |

- Main Page
- Related Pages
- CC26xx APIs
- Register Descriptions
- Online Resources

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
osc.c
Go to the documentation of this file.
1 /******************************************************************************
2 * Filename: osc.c
3 * Revised: 2015-01-13 16:59:55 +0100 (ti, 13 jan 2015)
4 * Revision: 42365
5 *
6 * Description: Driver for setting up the system Oscillators
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 #include <inc/hw_types.h>
40 #include <inc/hw_ccfg.h>
41 #include <driverlib/aon_batmon.h>
42 #include <driverlib/aon_rtc.h>
43 #include <driverlib/osc.h>
44
45 //*****************************************************************************
46 //
47 // Handle support for DriverLib in ROM:
48 // This section will undo prototype renaming made in the header file
49 //
50 //*****************************************************************************
51 #ifndef DRIVERLIB_GENERATE_ROM
52 #undef OSCClockSourceSet
53 #define OSCClockSourceSet NOROM_OSCClockSourceSet
54 #undef OSCClockSourceGet
55 #define OSCClockSourceGet NOROM_OSCClockSourceGet
56 #undef OSCInterfaceEnable
57 #define OSCInterfaceEnable NOROM_OSCInterfaceEnable
58 #endif
59
60 //*****************************************************************************
61 //
62 // OSCHF switch time calculator defines and globals
63 //
64 //*****************************************************************************
65
66 #define RTC_CV_TO_MS(x) (( 1000 * ( x )) >> 16 )
67 #define RTC_CV_TO_US(x) (( 1000000 * ( x )) >> 16 )
68
69 typedef struct {
70 uint32_t previousStartupTimeInUs ;
71 uint32_t timeXoscOff_CV ;
72 uint32_t timeXoscOn_CV ;
73 uint32_t timeXoscStable_CV ;
74 int32_t tempXoscOff ;
75 } OscHfGlobals_t;
76
77 static OscHfGlobals_t oscHfGlobals;
78
79 //*****************************************************************************
80 //
82 //
83 //*****************************************************************************
84 void
85 OSCClockSourceSet(uint32_t ui32SrcClk, uint32_t ui32Osc)
86 {
87 //
88 // Check the arguments.
89 //
90 ASSERT((ui32SrcClk & OSC_SRC_CLK_LF) ||
91 (ui32SrcClk & OSC_SRC_CLK_MF) ||
92 (ui32SrcClk & OSC_SRC_CLK_HF));
93 ASSERT((ui32Osc == OSC_RCOSC_HF) ||
94 (ui32Osc == OSC_RCOSC_LF) ||
95 (ui32Osc == OSC_XOSC_HF) ||
96 (ui32Osc == OSC_XOSC_LF));
97
98 //
99 // Request the high frequency source clock (using 24 MHz XTAL)
100 //
101 if(ui32SrcClk & OSC_SRC_CLK_HF)
102 {
103 //
104 // Enable the HF XTAL as HF clock source
105 //
106 DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
107 DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_M,
108 DDI_0_OSC_CTL0_SCLK_HF_SRC_SEL_S,
109 ui32Osc);
110
111 // TBD-EIE: Setting 24 MHz Xtal should not be needed here since it's
112 // done in trimDevice(), but keep it for now since we cant be sure that
113 // it's not turned off again.
114 //
115 // Using 24 MHz Xtal...
116 //
117 DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
118 DDI_0_OSC_CTL0_XTAL_IS_24M_M,
119 DDI_0_OSC_CTL0_XTAL_IS_24M_S,
120 0x1);
121 }
122
123 //
124 // Configure the medium frequency source clock
125 //
126 if(ui32SrcClk & OSC_SRC_CLK_MF)
127 {
128 DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
129 DDI_0_OSC_CTL0_SCLK_MF_SRC_SEL_M,
130 DDI_0_OSC_CTL0_SCLK_MF_SRC_SEL_S,
131 ui32Osc);
132 }
133
134 //
135 // Configure the low frequency source clock.
136 //
137 if(ui32SrcClk & OSC_SRC_CLK_LF)
138 {
139 //
140 // Change the clock source.
141 //
142 DDI16BitfieldWrite(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0,
143 DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_M,
144 DDI_0_OSC_CTL0_SCLK_LF_SRC_SEL_S,
145 ui32Osc);
146 }
147 }
148
149 //*****************************************************************************
150 //
152 //
153 //*****************************************************************************
154 uint32_t
155 OSCClockSourceGet(uint32_t ui32SrcClk)
156 {
157 uint32_t ui32ClockSource;
158
159 //
160 // Check the arguments.
161 //
162 ASSERT((ui32SrcClk & OSC_SRC_CLK_LF) ||
163 (ui32SrcClk & OSC_SRC_CLK_HF));
164
165 //
166 // Return the source for the selected clock.
167 //
168 if(ui32SrcClk == OSC_SRC_CLK_LF)
169 {
170 ui32ClockSource = DDI16BitfieldRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_STAT0,
171 DDI_0_OSC_STAT0_SCLK_LF_SRC_M,
172 DDI_0_OSC_STAT0_SCLK_LF_SRC_S);
173 }
174 else
175 {
176 ui32ClockSource = DDI16BitfieldRead(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_STAT0,
177 DDI_0_OSC_STAT0_SCLK_HF_SRC_M,
178 DDI_0_OSC_STAT0_SCLK_HF_SRC_S);
179 }
180 return (ui32ClockSource);
181 }
182
183 //*****************************************************************************
184 //
186 //
187 //*****************************************************************************
188 void
189 OSCInterfaceEnable(void)
190 {
191 //
192 // Force power on AUX to ensure CPU has access
193 //
194 AONWUCAuxWakeupEvent(AONWUC_AUX_WAKEUP);
195 while(!(AONWUCPowerStatus() & AONWUC_AUX_POWER_ON))
196 { }
197
198 //
199 // Enable the AUX domain OSC clock and wait for it to be ready
200 //
201 AUXWUCClockEnable(AUX_WUC_OSCCTRL_CLOCK);
202 while(AUXWUCClockStatus(AUX_WUC_OSCCTRL_CLOCK) != AUX_WUC_CLOCK_READY)
203 { }
204 }
205
206
207 //*****************************************************************************
208 //
209 // Returns maximum startup time (in microseconds) of XOSC_HF
210 //
211 //*****************************************************************************
212 uint32_t
213 OSCHF_GetStartupTime( uint32_t timeUntilWakeupInMs )
214 {
215 uint32_t deltaTimeSinceXoscOnInMs ;
216 int32_t deltaTempSinceXoscOn ;
217 uint32_t newStartupTimeInUs ;
218
219 deltaTimeSinceXoscOnInMs = RTC_CV_TO_MS( AONRTCCurrentCompareValueGet() - oscHfGlobals.timeXoscOff_CV );
220 deltaTempSinceXoscOn = AON_BatmonTempGetDegC() - oscHfGlobals.tempXoscOff;
221
222 if ( deltaTempSinceXoscOn < 0 ) {
223 deltaTempSinceXoscOn = -deltaTempSinceXoscOn;
224 }
225
226 if ( (( timeUntilWakeupInMs + deltaTimeSinceXoscOnInMs ) > 3000 ) ||
227 ( deltaTempSinceXoscOn > 5 ) ||
228 ( oscHfGlobals.timeXoscStable_CV < oscHfGlobals.timeXoscOn_CV ) ||
229 ( oscHfGlobals.previousStartupTimeInUs == 0 ) )
230 {
231 newStartupTimeInUs = 2000;
232 if (( HWREG( CCFG_BASE + CCFG_O_SIZE_AND_DIS_FLAGS ) & CCFG_SIZE_AND_DIS_FLAGS_DIS_XOSC_OVR_M ) == 0 ) {
233 newStartupTimeInUs = (( HWREG( CCFG_BASE + CCFG_O_MODE_CONF_1 ) &
234 CCFG_MODE_CONF_1_XOSC_MAX_START_M ) >>
235 CCFG_MODE_CONF_1_XOSC_MAX_START_S ) * 125;
236 // Note: CCFG startup time is "in units of 100us" adding 25% margine results in *125
237 }
238 } else {
239 newStartupTimeInUs = RTC_CV_TO_US( oscHfGlobals.timeXoscStable_CV - oscHfGlobals.timeXoscOn_CV );
240 newStartupTimeInUs += ( newStartupTimeInUs >> 2 ); // Add 25 percent margin
241 if ( newStartupTimeInUs < oscHfGlobals.previousStartupTimeInUs ) {
242 newStartupTimeInUs = oscHfGlobals.previousStartupTimeInUs;
243 }
244 }
245
246 if ( newStartupTimeInUs < 200 ) {
247 newStartupTimeInUs = 200;
248 }
249 if ( newStartupTimeInUs > 4000 ) {
250 newStartupTimeInUs = 4000;
251 }
252 return ( newStartupTimeInUs );
253 }
254
255
256 //*****************************************************************************
257 //
258 // Turns on XOSC_HF (but without switching to XOSC_HF)
259 //
260 //*****************************************************************************
261 void
262 OSCHF_TurnOnXosc( void )
263 {
264 OSCClockSourceSet( OSC_SRC_CLK_HF | OSC_SRC_CLK_MF, OSC_XOSC_HF );
265 oscHfGlobals.timeXoscOn_CV = AONRTCCurrentCompareValueGet();
266 }
267
268
269 //*****************************************************************************
270 //
271 // Switch to XOSC_HF if XOSC_HF is ready.
272 //
273 //*****************************************************************************
274 bool
275 OSCHF_AttemptToSwitchToXosc( void )
276 {
277 uint32_t startupTimeInUs;
278 uint32_t prevLimmit25InUs;
279
280 if ( OSCClockSourceGet( OSC_SRC_CLK_HF ) == OSC_XOSC_HF ) {
281 // Already on XOSC - nothing to do
282 return ( 1 );
283 }
284 if ( OSCHfSourceReady()) {
285 OSCHfSourceSwitch();
286
287 //
288 // Store startup time, but limit to 25 percent reduction each time.
289 //
290 oscHfGlobals.timeXoscStable_CV = AONRTCCurrentCompareValueGet();
291 startupTimeInUs = RTC_CV_TO_US( oscHfGlobals.timeXoscStable_CV - oscHfGlobals.timeXoscOn_CV );
292 prevLimmit25InUs = oscHfGlobals.previousStartupTimeInUs;
293 prevLimmit25InUs -= ( prevLimmit25InUs >> 2 ); // 25 percent margin
294 oscHfGlobals.previousStartupTimeInUs = startupTimeInUs;
295 if ( prevLimmit25InUs > startupTimeInUs ) {
296 oscHfGlobals.previousStartupTimeInUs = prevLimmit25InUs;
297 }
298 return ( 1 );
299 }
300 return ( 0 );
301 }
302
303
304 //*****************************************************************************
305 //
306 // Switch to RCOSC_HF and turn off XOSC_HF
307 //
308 //*****************************************************************************
309 void
310 OSCHF_SwitchToRcOscTurnOffXosc( void )
311 {
312 //
313 // Set SCLK_HF and SCLK_MF to RCOSC_HF without checking
314 // Doing this anyway to keep HF and MF in sync
315 //
316 OSCClockSourceSet( OSC_SRC_CLK_HF | OSC_SRC_CLK_MF, OSC_RCOSC_HF );
317
318 //
319 // Do the swithing if not alrady running on RCOSC_HF
320 //
321 if ( OSCClockSourceGet( OSC_SRC_CLK_HF ) != OSC_RCOSC_HF ) {
322 OSCHfSourceSwitch();
323 }
324
325 oscHfGlobals.timeXoscOff_CV = AONRTCCurrentCompareValueGet();
326 oscHfGlobals.tempXoscOff = AON_BatmonTempGetDegC();
327 }
AUXWUCClockEnable
void AUXWUCClockEnable(uint32_t ui32Clocks)
Enable clocks for peripherals in the AUX domain.
Definition: aux_wuc.c:64
OSC_SRC_CLK_MF
#define OSC_SRC_CLK_MF
Definition: osc.h:107
AUX_WUC_OSCCTRL_CLOCK
#define AUX_WUC_OSCCTRL_CLOCK
Definition: aux_wuc.h:109
OscHfGlobals_t::timeXoscOff_CV
uint32_t timeXoscOff_CV
Definition: osc.c:71
AUXWUCClockStatus
uint32_t AUXWUCClockStatus(uint32_t ui32Clocks)
Get the status of a clock.
Definition: aux_wuc.c:162
OscHfGlobals_t::timeXoscStable_CV
uint32_t timeXoscStable_CV
Definition: osc.c:73
OSCClockSourceGet
uint32_t OSCClockSourceGet(uint32_t ui32SrcClk)
Get the source clock settings.
Definition: osc.c:155
ASSERT
#define ASSERT(expr)
Definition: debug.h:65
AUX_WUC_CLOCK_READY
#define AUX_WUC_CLOCK_READY
Definition: aux_wuc.h:119
DDI16BitfieldWrite
void DDI16BitfieldWrite(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift, uint16_t ui32Data)
Write a bitfield via the DDI using 16-bit maskable write.
Definition: ddi.c:108
OSCInterfaceEnable
void OSCInterfaceEnable(void)
Enable CM3 access to the OSC_DIG module.
Definition: osc.c:189
OSCHF_GetStartupTime
uint32_t OSCHF_GetStartupTime(uint32_t timeUntilWakeupInMs)
Returns maximum startup time (in microseconds) of XOSC_HF.
Definition: osc.c:213
AONWUC_AUX_POWER_ON
#define AONWUC_AUX_POWER_ON
Definition: aon_wuc.h:178
OSC_SRC_CLK_HF
#define OSC_SRC_CLK_HF
Definition: osc.h:106
OSCHfSourceReady
__STATIC_INLINE bool OSCHfSourceReady(void)
Check if the HF clock source is ready to be switched.
Definition: osc.h:235
OSCHF_AttemptToSwitchToXosc
bool OSCHF_AttemptToSwitchToXosc(void)
Switch to XOSC_HF if XOSC_HF is ready.
Definition: osc.c:275
OSC_RCOSC_HF
#define OSC_RCOSC_HF
Definition: osc.h:110
aon_rtc.h
OSC_XOSC_HF
#define OSC_XOSC_HF
Definition: osc.h:111
AONWUC_AUX_WAKEUP
#define AONWUC_AUX_WAKEUP
Definition: aon_wuc.h:158
OSC_SRC_CLK_LF
#define OSC_SRC_CLK_LF
Definition: osc.h:108
OscHfGlobals_t::previousStartupTimeInUs
uint32_t previousStartupTimeInUs
Definition: osc.c:70
AON_BatmonTempGetDegC
int32_t AON_BatmonTempGetDegC(void)
Get the current temperature measurement as a signed value in Deg Celsius.
Definition: aon_batmon.c:55
DDI16BitfieldRead
uint16_t DDI16BitfieldRead(uint32_t ui32Base, uint32_t ui32Reg, uint32_t ui32Mask, uint32_t ui32Shift)
Read a bitfield via the DDI using 16-bit read.
Definition: ddi.c:198
osc.h
AONWUCAuxWakeupEvent
void AONWUCAuxWakeupEvent(uint32_t ui32Mode)
Control the wake up procedure of the AUX domain.
Definition: aon_wuc.c:158
OscHfGlobals_t
Definition: osc.c:69
OSC_RCOSC_LF
#define OSC_RCOSC_LF
Definition: osc.h:112
aon_batmon.h
OscHfGlobals_t::tempXoscOff
int32_t tempXoscOff
Definition: osc.c:74
OSCHF_SwitchToRcOscTurnOffXosc
void OSCHF_SwitchToRcOscTurnOffXosc(void)
Switch to RCOSC_HF and turn off XOSC_HF.
Definition: osc.c:310
OscHfGlobals_t::timeXoscOn_CV
uint32_t timeXoscOn_CV
Definition: osc.c:72
RTC_CV_TO_US
#define RTC_CV_TO_US(x)
Definition: osc.c:67
OSCClockSourceSet
void OSCClockSourceSet(uint32_t ui32SrcClk, uint32_t ui32Osc)
Configure the oscillator input to the a source clock.
Definition: osc.c:85
OSCHfSourceSwitch
__STATIC_INLINE void OSCHfSourceSwitch(void)
Switch the high frequency clock.
Definition: osc.h:265
OSCHF_TurnOnXosc
void OSCHF_TurnOnXosc(void)
Turns on XOSC_HF (but without switching to XOSC_HF).
Definition: osc.c:262
AONRTCCurrentCompareValueGet
__STATIC_INLINE uint32_t AONRTCCurrentCompareValueGet(void)
Get the current value of the RTC counter in a format compatible to the compare registers.
Definition: aon_rtc.h:631
AONWUCPowerStatus
__STATIC_INLINE uint32_t AONWUCPowerStatus(void)
Get the power status of the device.
Definition: aon_wuc.h:707
OSC_XOSC_LF
#define OSC_XOSC_LF
Definition: osc.h:113
RTC_CV_TO_MS
#define RTC_CV_TO_MS(x)
Definition: osc.c:66