13
13
//! - Implement light sleep
14
14
//! - 32kHz Xtal support
15
15
//! - Allow 8.5MHz clock to be tuned
16
- //! - Global RTC clock reading
17
16
//! - Automatic enabling/disabling of 8MHz source (when not in use for rtc_fast_clk or cpu frequency)
18
17
19
18
use crate :: prelude:: * ;
@@ -24,8 +23,9 @@ use crate::target::rtccntl::clk_conf::*;
24
23
use crate :: target:: rtccntl:: cntl:: * ;
25
24
use crate :: target:: { APB_CTRL , RTCCNTL , TIMG0 } ;
26
25
use core:: fmt;
27
- use xtensa_lx6:: get_cycle_count;
26
+ use xtensa_lx6:: timer :: { delay , get_cycle_count} ;
28
27
28
+ pub mod config;
29
29
pub mod cpu;
30
30
pub mod dfs;
31
31
mod pll;
@@ -199,243 +199,6 @@ static CLOCK_CONTROL_MUTEX: spin::Mutex<()> = spin::Mutex::new(());
199
199
#[ derive( Copy , Clone ) ]
200
200
pub struct ClockControlConfig { }
201
201
202
- impl < ' a > ClockControlConfig {
203
- // All the single word reads of frequencies and sources are thread and interrupt safe
204
- // as these are atomic.
205
-
206
- /// The current CPU frequency
207
- pub fn cpu_frequency ( & self ) -> Hertz {
208
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . cpu_frequency }
209
- }
210
-
211
- /// The current APB frequency
212
- pub fn apb_frequency ( & self ) -> Hertz {
213
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . apb_frequency }
214
- }
215
-
216
- /// The CPU frequency in the default state
217
- pub fn cpu_frequency_default ( & self ) -> Hertz {
218
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . cpu_frequency_default }
219
- }
220
-
221
- /// The CPU frequency in the CPU lock state
222
- pub fn cpu_frequency_locked ( & self ) -> Hertz {
223
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . cpu_frequency_locked }
224
- }
225
-
226
- /// The CPU frequency in the APB lock state
227
- pub fn cpu_frequency_apb_locked ( & self ) -> Hertz {
228
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . cpu_frequency_apb_locked }
229
- }
230
-
231
- /// The APB frequency in the APB lock state
232
- pub fn apb_frequency_apb_locked ( & self ) -> Hertz {
233
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . apb_frequency_apb_locked }
234
- }
235
-
236
- /// Is the reference clock 1MHz under all clock conditions
237
- pub fn is_ref_clock_stable ( & self ) -> bool {
238
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . ref_clock_stable }
239
- }
240
-
241
- /// The current reference frequency
242
- pub fn ref_frequency ( & self ) -> Hertz {
243
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . ref_frequency }
244
- }
245
-
246
- /// The current slow RTC frequency
247
- pub fn slow_rtc_frequency ( & self ) -> Hertz {
248
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . slow_rtc_frequency }
249
- }
250
-
251
- /// The current fast RTC frequency
252
- pub fn fast_rtc_frequency ( & self ) -> Hertz {
253
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . fast_rtc_frequency }
254
- }
255
-
256
- /// The current APLL frequency
257
- pub fn apll_frequency ( & self ) -> Hertz {
258
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . apll_frequency }
259
- }
260
-
261
- /// The current PLL/2 frequency
262
- pub fn pll_d2_frequency ( & self ) -> Hertz {
263
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . pll_d2_frequency }
264
- }
265
-
266
- /// The Xtal frequency
267
- pub fn xtal_frequency ( & self ) -> Hertz {
268
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . xtal_frequency }
269
- }
270
-
271
- /// The 32kHz Xtal frequency
272
- pub fn xtal32k_frequency ( & self ) -> Hertz {
273
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . xtal32k_frequency }
274
- }
275
-
276
- /// The current PLL frequency
277
- pub fn pll_frequency ( & self ) -> Hertz {
278
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . pll_frequency }
279
- }
280
-
281
- /// The current 8MHz oscillator frequency
282
- pub fn rtc8m_frequency ( & self ) -> Hertz {
283
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . rtc8m_frequency }
284
- }
285
-
286
- /// The current 8MHz oscillator frequency / 256
287
- pub fn rtc8md256_frequency ( & self ) -> Hertz {
288
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . rtc8md256_frequency }
289
- }
290
-
291
- /// The current 150kHz oscillator frequency
292
- pub fn rtc_frequency ( & self ) -> Hertz {
293
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . rtc_frequency }
294
- }
295
-
296
- /// The current source for the CPU and APB frequencies
297
- pub fn cpu_source ( & self ) -> CPUSource {
298
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . cpu_source }
299
- }
300
-
301
- /// The current source for the slow RTC frequency
302
- pub fn slow_rtc_source ( & self ) -> SlowRTCSource {
303
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . slow_rtc_source }
304
- }
305
-
306
- /// The current source for the fast RTC frequency
307
- pub fn fast_rtc_source ( & self ) -> FastRTCSource {
308
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . fast_rtc_source }
309
- }
310
-
311
- // The lock and unlock calls are thread and interrupt safe because this is handled inside
312
- // the DFS routines
313
-
314
- /// Obtain a RAII lock to use the high CPU frequency
315
- pub fn lock_cpu_frequency ( & self ) -> dfs:: LockCPU {
316
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . lock_cpu_frequency ( ) }
317
- }
318
-
319
- /// Obtain a RAII lock to use the APB CPU frequency
320
- pub fn lock_apb_frequency ( & self ) -> dfs:: LockAPB {
321
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . lock_apb_frequency ( ) }
322
- }
323
-
324
- /// Obtain a RAII lock to keep the CPU from sleeping
325
- pub fn lock_awake ( & self ) -> dfs:: LockAwake {
326
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . lock_awake ( ) }
327
- }
328
-
329
- /// Obtain a RAII lock to keep the PLL/2 from being turned off
330
- pub fn lock_plld2 ( & self ) -> dfs:: LockPllD2 {
331
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . lock_plld2 ( ) }
332
- }
333
-
334
- /// Add callback which will be called when clock speeds are changed.
335
- ///
336
- /// NOTE: these callbacks are called in an interrupt free environment,
337
- /// so should be as short as possible
338
- // TODO: at the moment only static lifetime callbacks are allow
339
- pub fn add_callback < F > ( & self , f : & ' static F ) -> Result < ( ) , Error >
340
- where
341
- F : Fn ( ) ,
342
- {
343
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . add_callback ( f) }
344
- }
345
-
346
- /// Get the current count of the PCU, APB, Awake and PLL/2 locks
347
- pub fn get_lock_count ( & self ) -> dfs:: Locks {
348
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . get_lock_count ( ) }
349
- }
350
-
351
- // The following routines are made thread and interrupt safe here
352
-
353
- /// Halt the designated core
354
- pub unsafe fn park_core ( & mut self , core : crate :: Core ) {
355
- interrupt:: free ( |_| {
356
- CLOCK_CONTROL_MUTEX . lock ( ) ;
357
- CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . park_core ( core) ;
358
- } )
359
- }
360
-
361
- /// Start the APP (second) core
362
- ///
363
- /// The second core will start running with the function `entry`.
364
- pub fn unpark_core ( & mut self , core : crate :: Core ) {
365
- interrupt:: free ( |_| {
366
- CLOCK_CONTROL_MUTEX . lock ( ) ;
367
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . unpark_core ( core) }
368
- } )
369
- }
370
-
371
- /// Start the APP (second) core
372
- ///
373
- /// The second core will start running with the function `entry`.
374
- pub fn start_app_core ( & mut self , entry : fn ( ) -> !) -> Result < ( ) , Error > {
375
- interrupt:: free ( |_| {
376
- CLOCK_CONTROL_MUTEX . lock ( ) ;
377
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . start_app_core ( entry) }
378
- } )
379
- }
380
-
381
- // The following routines handle thread and interrupt safety themselves
382
-
383
- /// Get RTC tick count since boot
384
- ///
385
- /// *Note: this function takes up to one slow RTC clock cycle (can be up to 300us) and
386
- /// interrupts are blocked during this time.*
387
- pub fn rtc_tick_count ( & self ) -> TicksU64 {
388
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . rtc_tick_count ( ) }
389
- }
390
-
391
- /// Get nanoseconds since boot based on RTC tick count
392
- ///
393
- /// *Note: this function takes up to one slow RTC clock cycle (can be up to 300us) and
394
- /// interrupts are blocked during this time.*
395
- pub fn rtc_nanoseconds ( & self ) -> NanoSecondsU64 {
396
- unsafe { CLOCK_CONTROL . as_mut ( ) . unwrap ( ) . rtc_nanoseconds ( ) }
397
- }
398
- }
399
-
400
- impl fmt:: Debug for ClockControlConfig {
401
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
402
- unsafe { CLOCK_CONTROL . as_ref ( ) . unwrap ( ) . fmt ( f) }
403
- }
404
- }
405
-
406
- /// cycle accurate delay using the cycle counter register
407
- pub fn delay_cycles ( clocks : u32 ) {
408
- let start = get_cycle_count ( ) ;
409
- loop {
410
- if get_cycle_count ( ) . wrapping_sub ( start) >= clocks {
411
- break ;
412
- }
413
- }
414
- }
415
-
416
- impl fmt:: Debug for ClockControl {
417
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
418
- f. debug_struct ( "ClockControl" )
419
- . field ( "cpu_frequency" , & self . cpu_frequency )
420
- . field ( "apb_frequency" , & self . apb_frequency )
421
- . field ( "ref_frequency" , & self . ref_frequency )
422
- . field ( "apll_frequency" , & self . apll_frequency )
423
- . field ( "pll_d2_frequency" , & self . pll_d2_frequency )
424
- . field ( "slow_rtc_frequency" , & self . slow_rtc_frequency )
425
- . field ( "fast_rtc_frequency" , & self . fast_rtc_frequency )
426
- . field ( "xtal_frequency" , & self . xtal_frequency )
427
- . field ( "xtal32k_frequency" , & self . xtal32k_frequency )
428
- . field ( "rtc8m_frequency" , & self . rtc8m_frequency )
429
- . field ( "rtc8md256_frequency" , & self . rtc8md256_frequency )
430
- . field ( "rtc_frequency" , & self . rtc_frequency )
431
- . field ( "pll_frequency" , & self . pll_frequency )
432
- . field ( "cpu_source" , & self . cpu_source )
433
- . field ( "slow_rtc_source" , & self . slow_rtc_source )
434
- . field ( "fast_rtc_source" , & self . fast_rtc_source )
435
- . finish ( )
436
- }
437
- }
438
-
439
202
/// Clock Control for initialization. Once initialization is done, call the freeze function to lock
440
203
/// the clock configuration. This will return a [ClockControlConfig](ClockControlConfig), which can
441
204
/// be copied for e.g. use in multiple peripherals.
@@ -828,7 +591,7 @@ impl ClockControl {
828
591
829
592
/// delay a certain time by spinning
830
593
fn delay < T : Into < NanoSeconds > > ( & self , time : T ) {
831
- delay_cycles ( self . time_to_cpu_cycles ( time) ) ;
594
+ delay ( self . time_to_cpu_cycles ( time) ) ;
832
595
}
833
596
834
597
/// Check if a value from RTC_XTAL_FREQ_REG or RTC_APB_FREQ_REG are valid clocks
@@ -1565,3 +1328,27 @@ impl ClockControl {
1565
1328
self . rtc_tick_count ( ) / self . slow_rtc_frequency
1566
1329
}
1567
1330
}
1331
+
1332
+ /// Custom debug formatter
1333
+ impl fmt:: Debug for ClockControl {
1334
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1335
+ f. debug_struct ( "ClockControl" )
1336
+ . field ( "cpu_frequency" , & self . cpu_frequency )
1337
+ . field ( "apb_frequency" , & self . apb_frequency )
1338
+ . field ( "ref_frequency" , & self . ref_frequency )
1339
+ . field ( "apll_frequency" , & self . apll_frequency )
1340
+ . field ( "pll_d2_frequency" , & self . pll_d2_frequency )
1341
+ . field ( "slow_rtc_frequency" , & self . slow_rtc_frequency )
1342
+ . field ( "fast_rtc_frequency" , & self . fast_rtc_frequency )
1343
+ . field ( "xtal_frequency" , & self . xtal_frequency )
1344
+ . field ( "xtal32k_frequency" , & self . xtal32k_frequency )
1345
+ . field ( "rtc8m_frequency" , & self . rtc8m_frequency )
1346
+ . field ( "rtc8md256_frequency" , & self . rtc8md256_frequency )
1347
+ . field ( "rtc_frequency" , & self . rtc_frequency )
1348
+ . field ( "pll_frequency" , & self . pll_frequency )
1349
+ . field ( "cpu_source" , & self . cpu_source )
1350
+ . field ( "slow_rtc_source" , & self . slow_rtc_source )
1351
+ . field ( "fast_rtc_source" , & self . fast_rtc_source )
1352
+ . finish ( )
1353
+ }
1354
+ }
0 commit comments