Skip to main content

atsam4_hal/
clock.rs

1#![allow(clippy::upper_case_acronyms)]
2
3use crate::pac::{pmc, PMC, SUPC};
4
5#[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
6use crate::pac::EFC;
7
8#[cfg(feature = "atsam4s")]
9use crate::pac::EFC0;
10
11#[cfg(feature = "atsam4sd")]
12use crate::pac::EFC1;
13
14use core::marker::PhantomData;
15use fugit::{HertzU32 as Hertz, RateExtU32};
16
17static mut MASTER_CLOCK_FREQUENCY: Hertz = Hertz::from_raw(0);
18
19#[cfg(all(feature = "atsam4s", feature = "usb"))]
20static mut PLLB_MULTIPLIER: u16 = 0;
21
22// NOTE: More frequencies and crystals can be added
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub enum MainClock {
25    #[cfg(not(feature = "atsam4n"))]
26    RcOscillator4Mhz, // USB Unsupported
27    RcOscillator8Mhz,  // USB Unsupported
28    RcOscillator12Mhz, // USB Unsupported
29    Crystal12Mhz,      // USB Supported
30                       // Crystal11289Khz, // USB Supported - Not implemented
31                       // Crystal16MHz     // USB Supported - Not implemented
32                       // Crystal18432Khz, // USB Supported - Not implemented
33}
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub enum SlowClock {
37    RcOscillator32Khz,
38    Crystal32Khz,
39    OscillatorBypass32Khz,
40}
41
42pub fn get_master_clock_frequency() -> Hertz {
43    unsafe { MASTER_CLOCK_FREQUENCY }
44}
45
46fn setup_slow_clock(supc: &SUPC, slow_clock: SlowClock) -> Hertz {
47    match slow_clock {
48        // Nothing to do, defaults to 32 kHz
49        // You cannot set the Slow Clock back to RC until VDDIO is reset
50        SlowClock::RcOscillator32Khz => {}
51        SlowClock::Crystal32Khz => {
52            // Enable crystal oscillator (also disables Slow RC Oscillator)
53            unsafe {
54                supc.cr
55                    .write_with_zero(|w| w.key().passwd().xtalsel().crystal_sel());
56            }
57        }
58        SlowClock::OscillatorBypass32Khz => {
59            // Enable bypass mode
60            supc.mr.modify(|_, w| w.key().passwd().oscbypass().bypass());
61            // Enable crystal oscillator (also disables Slow RC Oscillator)
62            unsafe {
63                supc.cr
64                    .write_with_zero(|w| w.key().passwd().xtalsel().crystal_sel());
65            }
66        }
67    }
68    // 32.768 kHz
69    32768.Hz()
70}
71
72fn setup_main_clock(pmc: &PMC, main_clock: MainClock) -> Hertz {
73    let prescaler = match main_clock {
74        #[cfg(not(feature = "atsam4n"))]
75        MainClock::RcOscillator4Mhz => {
76            switch_main_clock_to_fast_rc_4mhz(pmc);
77
78            // Set up the PLL for 120Mhz operation (4Mhz RC * (30 / 1) = 120Mhz)
79            let multiplier: u16 = 30;
80            let divider: u8 = 1;
81            enable_plla_clock(pmc, multiplier, divider);
82
83            // 0 = no prescaling
84            0
85        }
86        #[cfg(not(feature = "atsam4n"))]
87        MainClock::RcOscillator8Mhz => {
88            switch_main_clock_to_fast_rc_8mhz(pmc);
89
90            // Set up the PLL for 120Mhz operation (8Mhz RC * (15 / 1) = 120Mhz)
91            let multiplier: u16 = 15;
92            let divider: u8 = 1;
93            enable_plla_clock(pmc, multiplier, divider);
94
95            // 0 = no prescaling
96            0
97        }
98        #[cfg(feature = "atsam4n")]
99        MainClock::RcOscillator8Mhz => {
100            switch_main_clock_to_fast_rc_8mhz(pmc);
101
102            // Set up the PLL for 100Mhz operation (8Mhz RC * (25 / 2) = 100Mhz)
103            let multiplier: u16 = 25;
104            let divider: u8 = 2;
105            enable_plla_clock(pmc, multiplier, divider);
106
107            // 0 = no prescaling
108            0
109        }
110        #[cfg(not(feature = "atsam4n"))]
111        MainClock::RcOscillator12Mhz => {
112            switch_main_clock_to_fast_rc_12mhz(pmc);
113
114            // Set up the PLL for 120Mhz operation (12Mhz RC * (10 / 1) = 120Mhz)
115            let multiplier: u16 = 10;
116            let divider: u8 = 1;
117            enable_plla_clock(pmc, multiplier, divider);
118
119            // 0 = no prescaling
120            0
121        }
122        #[cfg(feature = "atsam4n")]
123        MainClock::RcOscillator12Mhz => {
124            switch_main_clock_to_fast_rc_12mhz(pmc);
125
126            // Set up the PLL for 100Mhz operation (12Mhz RC * (25 / 3) = 100Mhz)
127            let multiplier: u16 = 25;
128            let divider: u8 = 3;
129            enable_plla_clock(pmc, multiplier, divider);
130
131            // 0 = no prescaling
132            0
133        }
134        #[cfg(feature = "atsam4e")]
135        MainClock::Crystal12Mhz => {
136            switch_main_clock_to_external_12mhz(pmc);
137
138            #[cfg(feature = "usb")]
139            {
140                // Set up the PLL for 240MHz operation (12 MHz * (20 / 1) = 240 MHz)
141                // 240 MHz can be used to generate both master 120 MHz clock and USB 48 MHz clock
142                let multiplier: u16 = 20;
143                let divider: u8 = 1;
144                enable_plla_clock(pmc, multiplier, divider);
145
146                // 1 = /2 prescaling
147                1
148            }
149
150            #[cfg(not(feature = "usb"))]
151            {
152                // Set up the PLL for 120MHz operation (12 MHz * (10 / 1) = 120 MHz)
153                // Uses less power than running the PLL at 240 MHz
154                let multiplier: u16 = 10;
155                let divider: u8 = 1;
156                enable_plla_clock(pmc, multiplier, divider);
157
158                // 0 = no prescaling
159                0
160            }
161        }
162        #[cfg(feature = "atsam4n")]
163        MainClock::Crystal12Mhz => {
164            switch_main_clock_to_external_12mhz(pmc);
165
166            // Set up the PLL for 100MHz operation (12 MHz * (25 / 3) = 100 MHz)
167            let multiplier: u16 = 25;
168            let divider: u8 = 3;
169            enable_plla_clock(pmc, multiplier, divider);
170
171            // 0 = no prescaling
172            0
173        }
174
175        #[cfg(feature = "atsam4s")]
176        MainClock::Crystal12Mhz => {
177            switch_main_clock_to_external_12mhz(pmc);
178
179            // Setup PLLA for 120 MHz operation (12 MHz * (10 / 1) = 120 MHz)
180            let multiplier: u16 = 10;
181            let divider: u8 = 1;
182            enable_plla_clock(pmc, multiplier, divider);
183
184            #[cfg(feature = "usb")]
185            {
186                // Setup PLLB for 96 MHz operation (12 MHz * (8 / 1) = 96 MHz)
187                // 96 MHz will be /2 to get 48 MHz
188                let multiplier: u16 = 8;
189                let divider: u8 = 1;
190                enable_pllb_clock(pmc, multiplier, divider);
191            }
192
193            // 0 = no prescaling
194            0
195        }
196    };
197    wait_for_main_clock_ready(pmc);
198
199    wait_for_plla_lock(pmc);
200
201    switch_master_clock_to_plla(pmc, prescaler);
202
203    calculate_master_clock_frequency(pmc)
204}
205
206fn calculate_master_clock_frequency(pmc: &PMC) -> Hertz {
207    let mut mclk_freq = match pmc.pmc_mckr.read().css().bits() {
208        0 => {
209            // Slow clock
210            panic!("Unsupported clock source: Slow clock.")
211        }
212        1 => {
213            // Main clock
214            panic!("Unsupported clock source: Main clock.")
215        }
216        2 => {
217            // PLL
218            let mut mclk_freq = match pmc.ckgr_mor.read().moscsel().bit_is_set() {
219                true => 12_u32.MHz(),
220                false => {
221                    if pmc.ckgr_mor.read().moscrcf().is_12_mhz() {
222                        12_u32.MHz()
223                    } else if pmc.ckgr_mor.read().moscrcf().is_8_mhz() {
224                        8_u32.MHz()
225                    } else if pmc.ckgr_mor.read().moscrcf().is_4_mhz() {
226                        4_u32.MHz()
227                    } else {
228                        panic!("Unexpected value detected read from pmc.ckgr_mor.moscrcf")
229                    }
230                }
231            };
232
233            let plla_clock_source: u8 = 2; // 2 = PLLA
234            if pmc.pmc_mckr.read().css().bits() == plla_clock_source {
235                mclk_freq *= (pmc.ckgr_pllar.read().mula().bits() + 1) as u32;
236                mclk_freq /= (pmc.ckgr_pllar.read().diva().bits()) as u32;
237            }
238
239            mclk_freq
240        }
241        _ => panic!("Invalid value found in PMC_MCKR.CSS"),
242    };
243
244    // Factor in the prescaler
245    mclk_freq = match pmc.pmc_mckr.read().pres().bits() {
246        7 => mclk_freq / 3, // Special case for a 3 prescaler
247        prescaler => (mclk_freq.raw() >> prescaler).Hz(),
248    };
249
250    mclk_freq
251}
252
253fn get_flash_wait_states_for_clock_frequency(clock_frequency: Hertz) -> u8 {
254    match clock_frequency {
255        c if c < 20_u32.MHz::<1, 1>() => 0,
256        c if c < 40_u32.MHz::<1, 1>() => 1,
257        c if c < 60_u32.MHz::<1, 1>() => 2,
258        c if c < 80_u32.MHz::<1, 1>() => 3,
259        c if c < 100_u32.MHz::<1, 1>() => 4,
260        c if c < 123_u32.MHz::<1, 1>() => 5,
261        _ => panic!(
262            "Invalid frequency provided to get_flash_wait_states(): {} ",
263            clock_frequency
264        ),
265    }
266}
267
268#[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
269fn set_flash_wait_states_to_maximum(efc: &EFC) {
270    efc.fmr
271        .modify(|_, w| unsafe { w.fws().bits(5).cloe().set_bit() });
272}
273
274#[cfg(all(feature = "atsam4s", not(feature = "atsam4sd")))]
275fn set_flash_wait_states_to_maximum(efc0: &EFC0) {
276    efc0.fmr
277        .modify(|_, w| unsafe { w.fws().bits(5).cloe().set_bit() });
278}
279
280#[cfg(feature = "atsam4sd")]
281fn set_flash_wait_states_to_maximum(efc0: &EFC0, efc1: &EFC1) {
282    efc0.fmr
283        .modify(|_, w| unsafe { w.fws().bits(5).cloe().set_bit() });
284    efc1.fmr
285        .modify(|_, w| unsafe { w.fws().bits(5).cloe().set_bit() });
286}
287
288#[cfg(any(feature = "atsam4n", feature = "atsam4e"))]
289fn set_flash_wait_states_to_match_frequency(efc: &EFC, clock_frequency: Hertz) {
290    let wait_state_count = get_flash_wait_states_for_clock_frequency(clock_frequency);
291
292    efc.fmr
293        .modify(|_, w| unsafe { w.fws().bits(wait_state_count).cloe().set_bit() });
294}
295
296#[cfg(feature = "atsam4s")]
297fn set_flash_wait_states_to_match_frequency(
298    efc0: &EFC0,
299    #[cfg(feature = "atsam4sd")] efc1: &EFC1,
300    clock_frequency: Hertz,
301) {
302    let wait_state_count = get_flash_wait_states_for_clock_frequency(clock_frequency);
303
304    efc0.fmr
305        .modify(|_, w| unsafe { w.fws().bits(wait_state_count).cloe().set_bit() });
306    #[cfg(feature = "atsam4sd")]
307    efc1.fmr
308        .modify(|_, w| unsafe { w.fws().bits(wait_state_count).cloe().set_bit() });
309}
310
311fn switch_main_clock_to_external_12mhz(pmc: &PMC) {
312    // Activate external oscillator
313    // As we are clocking the core from internal Fast RC, we keep the bit CKGR_MOR_MOSCRCEN.
314    // Main Crystal Oscillator Start-up Time (CKGR_MOR_MOSCXTST) is set to maximum value.
315    // Then, we wait the startup time to be finished by checking PMC_SR_MOSCXTS in PMC_SR.
316    activate_crystal_oscillator(pmc);
317    wait_for_main_crystal_ready(pmc);
318
319    // Switch the MAINCK to the main crystal oscillator
320    // We add the CKGR_MOR_MOSCSEL bit.
321    // Then we wait for the selection to be done by checking PMC_SR_MOSCSELS in PMC_SR.
322    change_main_clock_to_crystal(pmc);
323    wait_for_main_clock_ready(pmc);
324}
325
326fn activate_crystal_oscillator(pmc: &PMC) {
327    // ATSAM4S Datasheet 38.5.3
328    // Maximum crystal startup time is 62 ms (worst-case)
329    // Slow clock is 32 kHz
330    // MOSCXTST is the number of slow clocks x8
331    // 62 ms / (1 / 32 kHz) / 8 = 248
332    //let crystal_startup_cycles = 248;
333
334    // From the datasheet 8 MHz and 16 MHz crystals take between 4 and 2.5 ms to start
335    // Using 4 ms for 12 MHz should be sufficient
336    // 4 ms / (1 / 32 kHz) / 8 = 16
337    let crystal_startup_cycles = 16;
338
339    pmc.ckgr_mor.modify(|_, w| unsafe {
340        w.key()
341            .passwd()
342            .moscrcen()
343            .set_bit()
344            .moscxten()
345            .set_bit()
346            .moscxtst()
347            .bits(crystal_startup_cycles)
348    });
349}
350
351fn is_main_crystal_ready(pmc: &PMC) -> bool {
352    pmc.pmc_sr.read().moscxts().bit_is_set()
353}
354
355fn wait_for_main_crystal_ready(pmc: &PMC) {
356    while !is_main_crystal_ready(pmc) {}
357}
358
359fn change_main_clock_to_crystal(pmc: &PMC) {
360    // Switch to fast crystal
361    // Disable RC oscillator
362    pmc.ckgr_mor
363        .modify(|_, w| w.key().passwd().moscrcen().clear_bit().moscsel().set_bit());
364}
365
366#[cfg(not(feature = "atsam4n"))]
367fn switch_main_clock_to_fast_rc_4mhz(pmc: &PMC) {
368    enable_fast_rc_oscillator(pmc);
369    wait_for_fast_rc_oscillator_to_stabilize(pmc);
370    change_fast_rc_oscillator_to_4mhz(pmc);
371    wait_for_fast_rc_oscillator_to_stabilize(pmc);
372    switch_to_fast_rc_oscillator(pmc);
373}
374
375fn switch_main_clock_to_fast_rc_8mhz(pmc: &PMC) {
376    enable_fast_rc_oscillator(pmc);
377    wait_for_fast_rc_oscillator_to_stabilize(pmc);
378    change_fast_rc_oscillator_to_8mhz(pmc);
379    wait_for_fast_rc_oscillator_to_stabilize(pmc);
380    switch_to_fast_rc_oscillator(pmc);
381}
382
383fn switch_main_clock_to_fast_rc_12mhz(pmc: &PMC) {
384    enable_fast_rc_oscillator(pmc);
385    wait_for_fast_rc_oscillator_to_stabilize(pmc);
386    change_fast_rc_oscillator_to_12mhz(pmc);
387    wait_for_fast_rc_oscillator_to_stabilize(pmc);
388    switch_to_fast_rc_oscillator(pmc);
389}
390
391fn enable_fast_rc_oscillator(pmc: &PMC) {
392    pmc.ckgr_mor
393        .modify(|_, w| w.key().passwd().moscrcen().set_bit());
394}
395
396#[cfg(not(feature = "atsam4n"))]
397fn change_fast_rc_oscillator_to_4mhz(pmc: &PMC) {
398    pmc.ckgr_mor
399        .modify(|_, w| w.key().passwd().moscrcf()._4_mhz());
400}
401
402fn change_fast_rc_oscillator_to_8mhz(pmc: &PMC) {
403    pmc.ckgr_mor
404        .modify(|_, w| w.key().passwd().moscrcf()._8_mhz());
405}
406
407fn change_fast_rc_oscillator_to_12mhz(pmc: &PMC) {
408    pmc.ckgr_mor
409        .modify(|_, w| w.key().passwd().moscrcf()._12_mhz());
410}
411
412fn switch_to_fast_rc_oscillator(pmc: &PMC) {
413    pmc.ckgr_mor
414        .modify(|_, w| w.key().passwd().moscsel().clear_bit());
415}
416
417fn wait_for_fast_rc_oscillator_to_stabilize(pmc: &PMC) {
418    while pmc.pmc_sr.read().moscrcs().bit_is_clear() {}
419}
420
421fn is_main_clock_ready(pmc: &PMC) -> bool {
422    pmc.pmc_sr.read().moscsels().bit_is_set()
423}
424
425fn wait_for_main_clock_ready(pmc: &PMC) {
426    while !is_main_clock_ready(pmc) {}
427}
428
429fn enable_plla_clock(pmc: &PMC, multiplier: u16, divider: u8) {
430    disable_plla_clock(pmc);
431
432    // Per ATSAM4S 44.6 and ATSAM4E16 46.5
433    // PLL settling time is between 60 and 150 us
434    // (1 / 32 kHz) = 31.25 us
435    // 60  / (1 / 32 kHz) = 1.92 -> 2
436    // 150 / (1 / 32 kHz) = 4.8 -> 5
437    let settling_cycles = 5;
438
439    // NOTE: the datasheet indicates the multplier used it MULA + 1 - hence the subtraction when setting the multiplier.
440    pmc.ckgr_pllar.modify(|_, w| unsafe {
441        w.one()
442            .set_bit()
443            .pllacount()
444            .bits(settling_cycles)
445            .mula()
446            .bits(multiplier - 1)
447            .diva()
448            .bits(divider)
449    });
450}
451
452fn disable_plla_clock(pmc: &PMC) {
453    pmc.ckgr_pllar
454        .modify(|_, w| unsafe { w.one().set_bit().mula().bits(0) });
455}
456
457fn is_plla_locked(pmc: &PMC) -> bool {
458    pmc.pmc_sr.read().locka().bit_is_set()
459}
460
461fn wait_for_plla_lock(pmc: &PMC) {
462    while !is_plla_locked(pmc) {}
463}
464
465fn switch_master_clock_to_plla(pmc: &PMC, prescaler: u8) {
466    // Set the master clock prescaler
467    pmc.pmc_mckr.modify(|_, w| w.pres().bits(prescaler));
468
469    wait_for_master_clock_ready(pmc);
470
471    // Set the master clock source to PLLA
472    // BUGBUG: What requires the 'unsafe' on SAM4?  SVD issue?
473    let clock_source: u8 = 2; // 2 = PLLA
474    #[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
475    pmc.pmc_mckr
476        .modify(|_, w| unsafe { w.css().bits(clock_source) });
477
478    #[cfg(feature = "atsam4s")]
479    pmc.pmc_mckr.modify(|_, w| w.css().bits(clock_source));
480
481    wait_for_master_clock_ready(pmc);
482}
483
484fn is_master_clock_ready(pmc: &PMC) -> bool {
485    pmc.pmc_sr.read().mckrdy().bit_is_set()
486}
487
488fn wait_for_master_clock_ready(pmc: &PMC) {
489    while !is_master_clock_ready(pmc) {}
490}
491
492#[cfg(all(feature = "atsam4s", feature = "usb"))]
493fn enable_pllb_clock(pmc: &PMC, multiplier: u16, divider: u8) {
494    disable_pllb_clock(pmc);
495
496    // Per ATSAM4S 44.6 and ATSAM4E16 46.5
497    // PLL settling time is between 60 and 150 us
498    // (1 / 32 kHz) = 31.25 us
499    // 60  / (1 / 32 kHz) = 1.92 -> 2
500    // 150 / (1 / 32 kHz) = 4.8 -> 5
501    let settling_cycles = 5;
502
503    // NOTE: the datasheet indicates the multplier used it MULB + 1 - hence the subtraction when setting the multiplier.
504    pmc.ckgr_pllbr.modify(|_, w| unsafe {
505        w.pllbcount()
506            .bits(settling_cycles)
507            .mulb()
508            .bits(multiplier - 1)
509            .divb()
510            .bits(divider)
511    });
512
513    unsafe { PLLB_MULTIPLIER = multiplier - 1 }; // Save for reenable_pllb_clock
514}
515
516/// Used to re-enable pllb clock if disabled later at runtime
517/// For use with UDP suspend
518#[cfg(all(feature = "atsam4s", feature = "usb"))]
519pub fn reenable_pllb_clock(pmc: &PMC) {
520    pmc.ckgr_pllbr
521        .modify(|_, w| unsafe { w.mulb().bits(PLLB_MULTIPLIER) });
522}
523
524#[cfg(all(feature = "atsam4s", feature = "usb"))]
525pub fn disable_pllb_clock(pmc: &PMC) {
526    pmc.ckgr_pllbr.modify(|_, w| unsafe { w.mulb().bits(0) });
527}
528
529#[cfg(all(feature = "atsam4s", feature = "usb"))]
530fn is_pllb_locked(pmc: &PMC) -> bool {
531    pmc.pmc_sr.read().lockb().bit_is_set()
532}
533
534#[cfg(all(feature = "atsam4s", feature = "usb"))]
535pub fn wait_for_pllb_lock(pmc: &PMC) {
536    while !is_pllb_locked(pmc) {}
537}
538
539// Peripheral Clock State
540#[derive(Default)]
541pub struct Enabled;
542
543#[derive(Default)]
544pub struct Disabled;
545
546#[derive(Default)]
547pub struct PeripheralClock<STATE> {
548    _state: PhantomData<STATE>,
549}
550
551macro_rules! peripheral_clocks {
552    (
553        $($PeripheralType:ident, $peripheral_ident:ident, $i:expr,)+
554    ) => {
555        #[derive(Default)]
556        pub struct PeripheralClocks {
557            $(
558                pub $peripheral_ident: $PeripheralType<Disabled>,
559            )+
560        }
561
562        impl PeripheralClocks {
563            pub fn new() -> Self {
564                PeripheralClocks {
565                    $(
566                        $peripheral_ident: $PeripheralType { _state: PhantomData },
567                    )+
568                }
569            }
570        }
571
572        $(
573            #[derive(Default)]
574            pub struct $PeripheralType<STATE> {
575                _state: PhantomData<STATE>,
576            }
577
578            impl<STATE> $PeripheralType<STATE> {
579                pub(crate) fn pcer0(&mut self) -> &pmc::PMC_PCER0 {
580                    unsafe { &(*PMC::ptr()).pmc_pcer0 }
581                }
582
583                #[cfg(not(feature = "atsam4n"))]
584                pub(crate) fn pcer1(&mut self) -> &pmc::PMC_PCER1 {
585                    unsafe { &(*PMC::ptr()).pmc_pcer1 }
586                }
587
588                pub(crate) fn pcdr0(&mut self) -> &pmc::PMC_PCDR0 {
589                    unsafe { &(*PMC::ptr()).pmc_pcdr0 }
590                }
591
592                #[cfg(not(feature = "atsam4n"))]
593                pub(crate) fn pcdr1(&mut self) -> &pmc::PMC_PCDR1 {
594                    unsafe { &(*PMC::ptr()).pmc_pcdr1 }
595                }
596
597                #[cfg(not(feature = "atsam4n"))]
598                pub fn into_enabled_clock(&mut self) -> $PeripheralType<Enabled> {
599                    if $i <= 31 {
600                        let shift = $i;
601                        unsafe {self.pcer0().write_with_zero(|w| w.bits(1 << shift) )};
602                    }
603                    else {
604                        let shift = ($i - 32);
605                        unsafe {self.pcer1().write_with_zero(|w| w.bits(1 << shift) )};
606                    }
607                    $PeripheralType { _state: PhantomData }
608                }
609
610                #[cfg(feature = "atsam4n")]
611                pub fn into_enabled_clock(&mut self) -> $PeripheralType<Enabled> {
612                    let shift = $i;
613                    unsafe {self.pcer0().write_with_zero(|w| w.bits(1 << shift) )};
614                    $PeripheralType { _state: PhantomData }
615                }
616
617                #[cfg(not(feature = "atsam4n"))]
618                pub fn into_disabled_clock(&mut self) -> $PeripheralType<Disabled> {
619                    if $i <= 31 {
620                        let shift = $i;
621                        unsafe {self.pcdr0().write_with_zero(|w| w.bits(1 << shift) )};
622                    }
623                    else {
624                        let shift = ($i - 32);
625                        unsafe {self.pcdr1().write_with_zero(|w| w.bits(1 << shift) )};
626                    }
627                    $PeripheralType { _state: PhantomData }
628                }
629
630                #[cfg(feature = "atsam4n")]
631                pub fn into_disabled_clock(&mut self) -> $PeripheralType<Disabled> {
632                    let shift = $i;
633                    unsafe {self.pcdr0().write_with_zero(|w| w.bits(1 << shift) )};
634                    $PeripheralType { _state: PhantomData }
635                }
636
637                pub fn frequency(&self) -> Hertz {
638                    get_master_clock_frequency()
639                }
640            }
641        )+
642    }
643}
644
645#[cfg(feature = "atsam4e")]
646peripheral_clocks!(
647    Uart0Clock,
648    uart_0,
649    7,
650    SmcClock,
651    smc,
652    8,
653    PioAClock,
654    pio_a,
655    9,
656    PioBClock,
657    pio_b,
658    10,
659    PioCClock,
660    pio_c,
661    11,
662    PioDClock,
663    pio_d,
664    12,
665    PioEClock,
666    pio_e,
667    13,
668    Usart0Clock,
669    usart_0,
670    14,
671    Usart1Clock,
672    usart_1,
673    15,
674    HsmciClock,
675    hsmci,
676    16,
677    Twi0Clock,
678    twi_0,
679    17,
680    Twi1Clock,
681    twi_1,
682    18,
683    SpiClock,
684    spi,
685    19,
686    DmacClock,
687    dmac,
688    20,
689    Tc0Clock,
690    tc_0,
691    21,
692    Tc1Clock,
693    tc_1,
694    22,
695    Tc2Clock,
696    tc_2,
697    23,
698    Tc3Clock,
699    tc_3,
700    24,
701    Tc4Clock,
702    tc_4,
703    25,
704    Tc5Clock,
705    tc_5,
706    26,
707    Tc6Clock,
708    tc_6,
709    27,
710    Tc7Clock,
711    tc_7,
712    28,
713    Tc8Clock,
714    tc_8,
715    29,
716    Afec0Clock,
717    afec_0,
718    30,
719    Afec1Clock,
720    afec_1,
721    31,
722    DaccClock,
723    dacc,
724    32,
725    AccClock,
726    acc,
727    33,
728    UdpClock,
729    udp,
730    35,
731    PwmClock,
732    pwm,
733    36,
734    Can0Clock,
735    can_0,
736    37,
737    Can1Clock,
738    can_1,
739    38,
740    AesClock,
741    aes,
742    39,
743    GmacClock,
744    gmac,
745    44,
746    Uart1Clock,
747    uart_1,
748    45,
749);
750
751#[cfg(feature = "atsam4n")]
752peripheral_clocks!(
753    Uart0Clock,
754    uart_0,
755    8,
756    Uart1Clock,
757    uart_1,
758    9,
759    Uart2Clock,
760    uart_2,
761    10,
762    PioAClock,
763    pio_a,
764    11,
765    PioBClock,
766    pio_b,
767    12,
768    PioCClock,
769    pio_c,
770    13,
771    Usart0Clock,
772    usart_0,
773    14,
774    Usart1Clock,
775    usart_1,
776    15,
777    Uart3Clock,
778    uart_3,
779    16,
780    Usart2Clock,
781    usart_2,
782    17,
783    Twi0Clock,
784    twi_0,
785    19,
786    Twi1Clock,
787    twi_1,
788    20,
789    SpiClock,
790    spi,
791    21,
792    Twi2Clock,
793    twi_2,
794    22,
795    Tc0Clock,
796    tc_0,
797    23,
798    Tc1Clock,
799    tc_1,
800    24,
801    Tc2Clock,
802    tc_2,
803    25,
804    Tc3Clock,
805    tc_3,
806    26,
807    Tc4Clock,
808    tc_4,
809    27,
810    Tc5Clock,
811    tc_5,
812    28,
813    AdcClock,
814    adc,
815    29,
816    DaccClock,
817    dacc,
818    30,
819    PwmClock,
820    pwm,
821    31,
822);
823
824#[cfg(feature = "atsam4s")]
825peripheral_clocks!(
826    Uart0Clock,
827    uart_0,
828    8,
829    Uart1Clock,
830    uart_1,
831    9,
832    SmcClock,
833    smc,
834    10,
835    PioAClock,
836    pio_a,
837    11,
838    PioBClock,
839    pio_b,
840    12,
841    PioCClock,
842    pio_c,
843    13,
844    Usart0Clock,
845    usart_0,
846    14,
847    Usart1Clock,
848    usart_1,
849    15,
850    HsmciClock,
851    hsmci,
852    18,
853    Twi0Clock,
854    twi_0,
855    19,
856    Twi1Clock,
857    twi_1,
858    20,
859    SpiClock,
860    spi,
861    21,
862    SscClock,
863    ssc,
864    22,
865    Tc0Clock,
866    tc_0,
867    23,
868    Tc1Clock,
869    tc_1,
870    24,
871    Tc2Clock,
872    tc_2,
873    25,
874    Tc3Clock,
875    tc_3,
876    26,
877    Tc4Clock,
878    tc_4,
879    27,
880    Tc5Clock,
881    tc_5,
882    28,
883    AdcClock,
884    adc,
885    29,
886    DaccClock,
887    dacc,
888    30,
889    PwmClock,
890    pwm,
891    31,
892    CrccuClock,
893    crccu,
894    32,
895    AccClock,
896    acc,
897    33,
898    UdpClock,
899    udp,
900    34,
901);
902
903pub struct ClockController {
904    pub peripheral_clocks: PeripheralClocks,
905    pub pmc: PMC,
906    master_clock: Hertz,
907    slow_clock: Hertz,
908}
909
910impl ClockController {
911    pub fn new(
912        pmc: PMC,
913        supc: &SUPC,
914        #[cfg(any(feature = "atsam4e", feature = "atsam4n"))] efc: &EFC,
915        #[cfg(feature = "atsam4s")] efc0: &EFC0,
916        #[cfg(feature = "atsam4sd")] efc1: &EFC1,
917        main_clock: MainClock,
918        slow_clock: SlowClock,
919    ) -> Self {
920        // Make sure write protection has been disabled
921        pmc.pmc_wpmr
922            .modify(|_, w| w.wpkey().passwd().wpen().clear_bit());
923
924        set_flash_wait_states_to_maximum(
925            #[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
926            efc,
927            #[cfg(feature = "atsam4s")]
928            efc0,
929            #[cfg(feature = "atsam4sd")]
930            efc1,
931        );
932        let slow_clock_frequency = setup_slow_clock(supc, slow_clock);
933        let master_clock_frequency = setup_main_clock(&pmc, main_clock);
934        set_flash_wait_states_to_match_frequency(
935            #[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
936            efc,
937            #[cfg(feature = "atsam4s")]
938            efc0,
939            #[cfg(feature = "atsam4sd")]
940            efc1,
941            master_clock_frequency,
942        );
943
944        // Setup USB clock
945        #[cfg(feature = "usb")]
946        match main_clock {
947            // TODO (HaaTa): Does USB even work without a crystal oscillator?
948            //               The bootloader requires an external oscillator for USB to work.
949            #[cfg(not(feature = "atsam4n"))]
950            MainClock::RcOscillator4Mhz => {}
951            MainClock::RcOscillator8Mhz => {}
952            MainClock::RcOscillator12Mhz => {}
953            MainClock::Crystal12Mhz => {
954                // PLLA
955                // 240 MHz / 5 = 48 MHz
956                // This works for both sam4s and sam4e as sam4e only has 1 pll (sam4s has 2)
957                // However, using plla and pllb, lower current usage can be achieved on sam4s
958                // Per the datasheet ~1 mA
959                // NOTE: the datasheet indicates divider is USBDIV + 1
960                #[cfg(feature = "atsam4e")]
961                {
962                    let usbdiv = 5;
963                    pmc.pmc_usb
964                        .modify(|_, w| unsafe { w.usbdiv().bits(usbdiv - 1) });
965                }
966
967                // Use PLLB for sam4s
968                // 96 MHz / 2 = 48 MHz
969                // NOTE: the datasheet indicates divider is USBDIV + 1
970                #[cfg(feature = "atsam4s")]
971                {
972                    wait_for_pllb_lock(&pmc);
973
974                    let usbdiv = 2;
975                    pmc.pmc_usb
976                        .modify(|_, w| unsafe { w.usbs().set_bit().usbdiv().bits(usbdiv - 1) });
977                }
978            }
979        }
980
981        unsafe {
982            MASTER_CLOCK_FREQUENCY = master_clock_frequency;
983        }
984
985        ClockController {
986            peripheral_clocks: PeripheralClocks::new(),
987            pmc,
988            master_clock: master_clock_frequency,
989            slow_clock: slow_clock_frequency,
990        }
991    }
992
993    pub fn master_clock(self) -> Hertz {
994        self.master_clock
995    }
996
997    pub fn slow_clock(self) -> Hertz {
998        self.slow_clock
999    }
1000}