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#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub enum MainClock {
25 #[cfg(not(feature = "atsam4n"))]
26 RcOscillator4Mhz, RcOscillator8Mhz, RcOscillator12Mhz, Crystal12Mhz, }
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 SlowClock::RcOscillator32Khz => {}
51 SlowClock::Crystal32Khz => {
52 unsafe {
54 supc.cr
55 .write_with_zero(|w| w.key().passwd().xtalsel().crystal_sel());
56 }
57 }
58 SlowClock::OscillatorBypass32Khz => {
59 supc.mr.modify(|_, w| w.key().passwd().oscbypass().bypass());
61 unsafe {
63 supc.cr
64 .write_with_zero(|w| w.key().passwd().xtalsel().crystal_sel());
65 }
66 }
67 }
68 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 let multiplier: u16 = 30;
80 let divider: u8 = 1;
81 enable_plla_clock(pmc, multiplier, divider);
82
83 0
85 }
86 #[cfg(not(feature = "atsam4n"))]
87 MainClock::RcOscillator8Mhz => {
88 switch_main_clock_to_fast_rc_8mhz(pmc);
89
90 let multiplier: u16 = 15;
92 let divider: u8 = 1;
93 enable_plla_clock(pmc, multiplier, divider);
94
95 0
97 }
98 #[cfg(feature = "atsam4n")]
99 MainClock::RcOscillator8Mhz => {
100 switch_main_clock_to_fast_rc_8mhz(pmc);
101
102 let multiplier: u16 = 25;
104 let divider: u8 = 2;
105 enable_plla_clock(pmc, multiplier, divider);
106
107 0
109 }
110 #[cfg(not(feature = "atsam4n"))]
111 MainClock::RcOscillator12Mhz => {
112 switch_main_clock_to_fast_rc_12mhz(pmc);
113
114 let multiplier: u16 = 10;
116 let divider: u8 = 1;
117 enable_plla_clock(pmc, multiplier, divider);
118
119 0
121 }
122 #[cfg(feature = "atsam4n")]
123 MainClock::RcOscillator12Mhz => {
124 switch_main_clock_to_fast_rc_12mhz(pmc);
125
126 let multiplier: u16 = 25;
128 let divider: u8 = 3;
129 enable_plla_clock(pmc, multiplier, divider);
130
131 0
133 }
134 #[cfg(feature = "atsam4e")]
135 MainClock::Crystal12Mhz => {
136 switch_main_clock_to_external_12mhz(pmc);
137
138 #[cfg(feature = "usb")]
139 {
140 let multiplier: u16 = 20;
143 let divider: u8 = 1;
144 enable_plla_clock(pmc, multiplier, divider);
145
146 1
148 }
149
150 #[cfg(not(feature = "usb"))]
151 {
152 let multiplier: u16 = 10;
155 let divider: u8 = 1;
156 enable_plla_clock(pmc, multiplier, divider);
157
158 0
160 }
161 }
162 #[cfg(feature = "atsam4n")]
163 MainClock::Crystal12Mhz => {
164 switch_main_clock_to_external_12mhz(pmc);
165
166 let multiplier: u16 = 25;
168 let divider: u8 = 3;
169 enable_plla_clock(pmc, multiplier, divider);
170
171 0
173 }
174
175 #[cfg(feature = "atsam4s")]
176 MainClock::Crystal12Mhz => {
177 switch_main_clock_to_external_12mhz(pmc);
178
179 let multiplier: u16 = 10;
181 let divider: u8 = 1;
182 enable_plla_clock(pmc, multiplier, divider);
183
184 #[cfg(feature = "usb")]
185 {
186 let multiplier: u16 = 8;
189 let divider: u8 = 1;
190 enable_pllb_clock(pmc, multiplier, divider);
191 }
192
193 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 panic!("Unsupported clock source: Slow clock.")
211 }
212 1 => {
213 panic!("Unsupported clock source: Main clock.")
215 }
216 2 => {
217 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; 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 mclk_freq = match pmc.pmc_mckr.read().pres().bits() {
246 7 => mclk_freq / 3, 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_crystal_oscillator(pmc);
317 wait_for_main_crystal_ready(pmc);
318
319 change_main_clock_to_crystal(pmc);
323 wait_for_main_clock_ready(pmc);
324}
325
326fn activate_crystal_oscillator(pmc: &PMC) {
327 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 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 let settling_cycles = 5;
438
439 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 pmc.pmc_mckr.modify(|_, w| w.pres().bits(prescaler));
468
469 wait_for_master_clock_ready(pmc);
470
471 let clock_source: u8 = 2; #[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 let settling_cycles = 5;
502
503 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 }; }
515
516#[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#[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 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 #[cfg(feature = "usb")]
946 match main_clock {
947 #[cfg(not(feature = "atsam4n"))]
950 MainClock::RcOscillator4Mhz => {}
951 MainClock::RcOscillator8Mhz => {}
952 MainClock::RcOscillator12Mhz => {}
953 MainClock::Crystal12Mhz => {
954 #[cfg(feature = "atsam4e")]
961 {
962 let usbdiv = 5;
963 pmc.pmc_usb
964 .modify(|_, w| unsafe { w.usbdiv().bits(usbdiv - 1) });
965 }
966
967 #[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}