aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaleb Jamison <[email protected]>2023-05-08 09:43:58 -0400
committerCaleb Jamison <[email protected]>2023-05-08 09:45:54 -0400
commit59132514cfd04709bffb119642baf9d0dcf4733a (patch)
tree5dfa337833e955e4ba232bf6cda62799bd4a7c4b
parent1a96eae22c38afbd0c1c15d1d5dcc43bc639369b (diff)
Add missing functions, Cleanup, Gpout example
-rw-r--r--embassy-rp/src/clocks.rs259
-rw-r--r--examples/rp/src/bin/gpout.rs21
2 files changed, 227 insertions, 53 deletions
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 4ae967aae..5d3444442 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -2,7 +2,8 @@ use pac::clocks::vals::*;
2 2
3use crate::{pac, reset}; 3use crate::{pac, reset};
4 4
5static mut EXTERNAL_HZ: u32 = 0; 5// TODO fix terrible use of global here
6static mut XIN_HZ: u32 = 0;
6 7
7pub struct ClockConfig { 8pub struct ClockConfig {
8 rosc_config: Option<RoscConfig>, 9 rosc_config: Option<RoscConfig>,
@@ -49,7 +50,7 @@ impl ClockConfig {
49 ref_clk_config: (RefClkSrc::Xosc, 1), 50 ref_clk_config: (RefClkSrc::Xosc, 1),
50 sys_clk_config: (SysClkSrc::Aux(ClkSysCtrlAuxsrc::CLKSRC_PLL_SYS), 1), 51 sys_clk_config: (SysClkSrc::Aux(ClkSysCtrlAuxsrc::CLKSRC_PLL_SYS), 1),
51 peri_clk_src: Some(ClkPeriCtrlAuxsrc::CLK_SYS), 52 peri_clk_src: Some(ClkPeriCtrlAuxsrc::CLK_SYS),
52 usb_clk_config: Some((ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS, 1)), 53 usb_clk_config: Some((ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB, 1)),
53 adc_clk_config: Some((ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB, 1)), 54 adc_clk_config: Some((ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB, 1)),
54 rtc_clk_config: Some((ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB, 1024)), 55 rtc_clk_config: Some((ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB, 1024)),
55 } 56 }
@@ -164,7 +165,7 @@ pub(crate) unsafe fn init(config: ClockConfig) {
164 } 165 }
165 166
166 if let Some(config) = config.xosc_config { 167 if let Some(config) = config.xosc_config {
167 EXTERNAL_HZ = config.hz; 168 XIN_HZ = config.hz;
168 169
169 pac::WATCHDOG.tick().write(|w| { 170 pac::WATCHDOG.tick().write(|w| {
170 w.set_cycles((config.hz / 1_000_000) as u16); 171 w.set_cycles((config.hz / 1_000_000) as u16);
@@ -343,37 +344,21 @@ pub fn estimate_rosc_freq() -> u32 {
343 base / div 344 base / div
344} 345}
345 346
346pub(crate) fn clk_sys_freq() -> u32 { 347pub fn xosc_freq() -> u32 {
347 let c = pac::CLOCKS; 348 unsafe { XIN_HZ }
348 let ctrl = unsafe { c.clk_sys_ctrl().read() }; 349}
349
350 let base = match ctrl.src() {
351 ClkSysCtrlSrc::CLK_REF => clk_ref_freq(),
352 ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX => {
353 match ctrl.auxsrc() {
354 ClkSysCtrlAuxsrc::CLKSRC_PLL_SYS => clk_sys_pll_freq(),
355 ClkSysCtrlAuxsrc::CLKSRC_PLL_USB => clk_usb_pll_freq(),
356 ClkSysCtrlAuxsrc::ROSC_CLKSRC => estimate_rosc_freq(),
357 ClkSysCtrlAuxsrc::XOSC_CLKSRC => unsafe { EXTERNAL_HZ },
358 // TODO not sure how to handle clkin sources
359 _ => todo!(),
360 }
361 }
362 _ => unreachable!(),
363 };
364
365 let div = unsafe { c.clk_sys_div().read() };
366 let int = if div.int() == 0 { 65536 } else { div.int() };
367 // TODO handle fractional clock div
368 let _frac = div.frac();
369 350
370 base / int 351pub fn gpin0_freq() -> u32 {
352 todo!()
353}
354pub fn gpin1_freq() -> u32 {
355 todo!()
371} 356}
372 357
373pub(crate) fn clk_sys_pll_freq() -> u32 { 358pub fn pll_sys_freq() -> u32 {
374 let p = pac::PLL_SYS; 359 let p = pac::PLL_SYS;
375 360
376 let input_freq = unsafe { EXTERNAL_HZ }; 361 let input_freq = xosc_freq();
377 let cs = unsafe { p.cs().read() }; 362 let cs = unsafe { p.cs().read() };
378 363
379 let refdiv = cs.refdiv() as u32; 364 let refdiv = cs.refdiv() as u32;
@@ -386,10 +371,10 @@ pub(crate) fn clk_sys_pll_freq() -> u32 {
386 (((input_freq / refdiv) * fbdiv) / postdiv1) / postdiv2 371 (((input_freq / refdiv) * fbdiv) / postdiv1) / postdiv2
387} 372}
388 373
389pub(crate) fn clk_usb_pll_freq() -> u32 { 374pub fn pll_usb_freq() -> u32 {
390 let p = pac::PLL_USB; 375 let p = pac::PLL_USB;
391 376
392 let input_freq = unsafe { EXTERNAL_HZ }; 377 let input_freq = xosc_freq();
393 let cs = unsafe { p.cs().read() }; 378 let cs = unsafe { p.cs().read() };
394 379
395 let refdiv = cs.refdiv() as u32; 380 let refdiv = cs.refdiv() as u32;
@@ -402,18 +387,30 @@ pub(crate) fn clk_usb_pll_freq() -> u32 {
402 (((input_freq / refdiv) * fbdiv) / postdiv1) / postdiv2 387 (((input_freq / refdiv) * fbdiv) / postdiv1) / postdiv2
403} 388}
404 389
405pub(crate) fn clk_peri_freq() -> u32 { 390pub fn clk_sys_freq() -> u32 {
406 let c = pac::CLOCKS; 391 let c = pac::CLOCKS;
407 let src = unsafe { c.clk_peri_ctrl().read().auxsrc() }; 392 let ctrl = unsafe { c.clk_sys_ctrl().read() };
408 393
409 match src { 394 let base = match ctrl.src() {
410 ClkPeriCtrlAuxsrc::CLK_SYS => clk_sys_freq(), 395 ClkSysCtrlSrc::CLK_REF => clk_ref_freq(),
411 ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS => clk_sys_pll_freq(), 396 ClkSysCtrlSrc::CLKSRC_CLK_SYS_AUX => match ctrl.auxsrc() {
412 ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH => estimate_rosc_freq(), 397 ClkSysCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
413 ClkPeriCtrlAuxsrc::XOSC_CLKSRC => unsafe { EXTERNAL_HZ }, 398 ClkSysCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
414 // TODO not sure how to handle clkin sources 399 ClkSysCtrlAuxsrc::ROSC_CLKSRC => estimate_rosc_freq(),
415 _ => todo!(), 400 ClkSysCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
416 } 401 ClkSysCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
402 ClkSysCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
403 _ => unreachable!(),
404 },
405 _ => unreachable!(),
406 };
407
408 let div = unsafe { c.clk_sys_div().read() };
409 let int = if div.int() == 0 { 65536 } else { div.int() };
410 // TODO handle fractional clock div
411 let _frac = div.frac();
412
413 base / int
417} 414}
418 415
419pub fn clk_ref_freq() -> u32 { 416pub fn clk_ref_freq() -> u32 {
@@ -422,30 +419,90 @@ pub fn clk_ref_freq() -> u32 {
422 419
423 let base = match ctrl.src() { 420 let base = match ctrl.src() {
424 ClkRefCtrlSrc::ROSC_CLKSRC_PH => estimate_rosc_freq(), 421 ClkRefCtrlSrc::ROSC_CLKSRC_PH => estimate_rosc_freq(),
425 ClkRefCtrlSrc::XOSC_CLKSRC => unsafe { EXTERNAL_HZ }, 422 ClkRefCtrlSrc::XOSC_CLKSRC => xosc_freq(),
426 ClkRefCtrlSrc::CLKSRC_CLK_REF_AUX => todo!(), 423 ClkRefCtrlSrc::CLKSRC_CLK_REF_AUX => match ctrl.auxsrc() {
424 ClkRefCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
425 ClkRefCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
426 ClkRefCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
427 _ => unreachable!(),
428 },
427 _ => unreachable!(), 429 _ => unreachable!(),
428 }; 430 };
429 431
430 let mut div = unsafe { c.clk_ref_div().read().int() } as u32; 432 let div = unsafe { c.clk_ref_div().read() };
431 if div == 0 { 433 let int = if div.int() == 0 { 4 } else { div.int() as u32 };
432 div = 4; 434
435 base / int
436}
437
438pub fn clk_peri_freq() -> u32 {
439 let c = pac::CLOCKS;
440 let src = unsafe { c.clk_peri_ctrl().read().auxsrc() };
441
442 match src {
443 ClkPeriCtrlAuxsrc::CLK_SYS => clk_sys_freq(),
444 ClkPeriCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
445 ClkPeriCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
446 ClkPeriCtrlAuxsrc::ROSC_CLKSRC_PH => estimate_rosc_freq(),
447 ClkPeriCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
448 ClkPeriCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
449 ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
450 _ => unreachable!(),
433 } 451 }
452}
434 453
435 base / div 454pub fn clk_usb_freq() -> u32 {
455 let c = pac::CLOCKS;
456 let ctrl = unsafe { c.clk_usb_ctrl().read() };
457
458 let base = match ctrl.auxsrc() {
459 ClkUsbCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
460 ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
461 ClkUsbCtrlAuxsrc::ROSC_CLKSRC_PH => estimate_rosc_freq(),
462 ClkUsbCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
463 ClkUsbCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
464 ClkUsbCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
465 _ => unreachable!(),
466 };
467
468 let div = unsafe { c.clk_ref_div().read() };
469 let int = if div.int() == 0 { 4 } else { div.int() as u32 };
470
471 base / int
436} 472}
437 473
438pub(crate) fn clk_rtc_freq() -> u32 { 474pub fn clk_adc_freq() -> u32 {
475 let c = pac::CLOCKS;
476 let ctrl = unsafe { c.clk_adc_ctrl().read() };
477
478 let base = match ctrl.auxsrc() {
479 ClkAdcCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
480 ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
481 ClkAdcCtrlAuxsrc::ROSC_CLKSRC_PH => estimate_rosc_freq(),
482 ClkAdcCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
483 ClkAdcCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
484 ClkAdcCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
485 _ => unreachable!(),
486 };
487
488 let div = unsafe { c.clk_adc_div().read() };
489 let int = if div.int() == 0 { 4 } else { div.int() as u32 };
490
491 base / int
492}
493
494pub fn clk_rtc_freq() -> u32 {
439 let c = pac::CLOCKS; 495 let c = pac::CLOCKS;
440 let src = unsafe { c.clk_rtc_ctrl().read().auxsrc() }; 496 let src = unsafe { c.clk_rtc_ctrl().read().auxsrc() };
441 497
442 let base = match src { 498 let base = match src {
443 ClkRtcCtrlAuxsrc::XOSC_CLKSRC => unsafe { EXTERNAL_HZ }, 499 ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
500 ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
444 ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH => estimate_rosc_freq(), 501 ClkRtcCtrlAuxsrc::ROSC_CLKSRC_PH => estimate_rosc_freq(),
445 ClkRtcCtrlAuxsrc::CLKSRC_PLL_USB => clk_usb_pll_freq(), 502 ClkRtcCtrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
446 ClkRtcCtrlAuxsrc::CLKSRC_PLL_SYS => clk_sys_pll_freq(), 503 ClkRtcCtrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
447 // TODO not sure how to handle clkin sources 504 ClkRtcCtrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
448 _ => todo!(), 505 _ => unreachable!(),
449 }; 506 };
450 507
451 let div = unsafe { c.clk_rtc_div().read() }; 508 let div = unsafe { c.clk_rtc_div().read() };
@@ -456,6 +513,60 @@ pub(crate) fn clk_rtc_freq() -> u32 {
456 base / int 513 base / int
457} 514}
458 515
516pub fn clk_gpout0_freq() -> u32 {
517 let c = pac::CLOCKS;
518 let src = unsafe { c.clk_gpout0_ctrl().read().auxsrc() };
519
520 let base = match src {
521 ClkGpout0ctrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
522 ClkGpout0ctrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
523 ClkGpout0ctrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
524 ClkGpout0ctrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
525 ClkGpout0ctrlAuxsrc::ROSC_CLKSRC => estimate_rosc_freq(),
526 ClkGpout0ctrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
527 ClkGpout0ctrlAuxsrc::CLK_SYS => clk_sys_freq(),
528 ClkGpout0ctrlAuxsrc::CLK_USB => clk_usb_freq(),
529 ClkGpout0ctrlAuxsrc::CLK_ADC => clk_adc_freq(),
530 ClkGpout0ctrlAuxsrc::CLK_RTC => clk_rtc_freq(),
531 ClkGpout0ctrlAuxsrc::CLK_REF => clk_ref_freq(),
532 _ => unreachable!(),
533 };
534
535 let div = unsafe { c.clk_gpout0_div().read() };
536 let int = if div.int() == 0 { 65536 } else { div.int() };
537 // TODO handle fractional clock div
538 let _frac = div.frac();
539
540 base / int
541}
542
543pub fn clk_gpout1_freq() -> u32 {
544 let c = pac::CLOCKS;
545 let src = unsafe { c.clk_gpout1_ctrl().read().auxsrc() };
546
547 let base = match src {
548 ClkGpout1ctrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
549 ClkGpout1ctrlAuxsrc::CLKSRC_GPIN0 => gpin0_freq(),
550 ClkGpout1ctrlAuxsrc::CLKSRC_GPIN1 => gpin1_freq(),
551 ClkGpout1ctrlAuxsrc::CLKSRC_PLL_USB => pll_usb_freq(),
552 ClkGpout1ctrlAuxsrc::ROSC_CLKSRC => estimate_rosc_freq(),
553 ClkGpout1ctrlAuxsrc::XOSC_CLKSRC => xosc_freq(),
554 ClkGpout1ctrlAuxsrc::CLK_SYS => clk_sys_freq(),
555 ClkGpout1ctrlAuxsrc::CLK_USB => clk_usb_freq(),
556 ClkGpout1ctrlAuxsrc::CLK_ADC => clk_adc_freq(),
557 ClkGpout1ctrlAuxsrc::CLK_RTC => clk_rtc_freq(),
558 ClkGpout1ctrlAuxsrc::CLK_REF => clk_ref_freq(),
559 _ => unreachable!(),
560 };
561
562 let div = unsafe { c.clk_gpout1_div().read() };
563 let int = if div.int() == 0 { 65536 } else { div.int() };
564 // TODO handle fractional clock div
565 let _frac = div.frac();
566
567 base / int
568}
569
459unsafe fn start_xosc(crystal_hz: u32) { 570unsafe fn start_xosc(crystal_hz: u32) {
460 pac::XOSC 571 pac::XOSC
461 .ctrl() 572 .ctrl()
@@ -526,6 +637,48 @@ unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) {
526 p.pwr().modify(|w| w.set_postdivpd(false)); 637 p.pwr().modify(|w| w.set_postdivpd(false));
527} 638}
528 639
640pub struct Gpout0 {
641 _pin: crate::peripherals::PIN_21,
642}
643
644impl Gpout0 {
645 pub fn new(pin: crate::peripherals::PIN_21) -> Self {
646 unsafe {
647 let p = pac::IO_BANK0.gpio(21).ctrl();
648 p.write(|w| w.set_funcsel(pac::io::vals::Gpio21ctrlFuncsel::CLOCKS_GPOUT_0.0))
649 }
650 Self { _pin: pin }
651 }
652
653 pub fn set_div(&self, int: u32, frac: u8) {
654 unsafe {
655 let c = pac::CLOCKS;
656 c.clk_gpout0_div().write(|w| {
657 w.set_int(int);
658 w.set_frac(frac);
659 });
660 }
661 }
662
663 pub fn set_src(&self, src: ClkGpout0ctrlAuxsrc) {
664 unsafe {
665 let c = pac::CLOCKS;
666 c.clk_gpout0_ctrl().modify(|w| {
667 w.set_auxsrc(src);
668 });
669 }
670 }
671
672 pub fn enable(&self) {
673 unsafe {
674 let c = pac::CLOCKS;
675 c.clk_gpout0_ctrl().modify(|w| {
676 w.set_enable(true);
677 });
678 }
679 }
680}
681
529/// Random number generator based on the ROSC RANDOMBIT register. 682/// Random number generator based on the ROSC RANDOMBIT register.
530/// 683///
531/// This will not produce random values if the ROSC is stopped or run at some 684/// This will not produce random values if the ROSC is stopped or run at some
diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs
new file mode 100644
index 000000000..0503212e8
--- /dev/null
+++ b/examples/rp/src/bin/gpout.rs
@@ -0,0 +1,21 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_rp::{clocks, pac};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_rp::init(Default::default());
13 //let mut led = Output::new(p.PIN_25, Level::Low);
14
15 let gpout0 = clocks::Gpout0::new(p.PIN_21);
16 gpout0.set_src(pac::clocks::vals::ClkGpout0ctrlAuxsrc::CLK_SYS);
17 gpout0.set_div(1000, 0);
18 gpout0.enable();
19
20 info!("Pin 21 should be toggling at {} hz", clocks::clk_gpout0_freq());
21}