From c49b5b2d352f99e2b673c5a23cddf5c2ef5424fc Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Sun, 21 Apr 2019 21:42:21 -0700 Subject: [PATCH] *: add initial implementation for efm32gg11b820 This adds timers 4, 5, and 6; adds the routing definitions for the efm32gg11b820; and adds support for timers with different register widths. --- Cargo.toml | 11 ++- src/cmu.rs | 22 ++++- src/gpio.rs | 48 ++++++++++ src/lib.rs | 2 + src/routing.rs | 2 + src/routing/efm32gg11.rs | 202 +++++++++++++++++++++++++++++++++++++++ src/timer.rs | 79 ++++++++++++--- 7 files changed, 349 insertions(+), 17 deletions(-) create mode 100644 src/routing/efm32gg11.rs diff --git a/Cargo.toml b/Cargo.toml index c02b89b..97fd108 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,7 @@ repository = "https://github.com/chrysn/efm32gg-hal" [dependencies] cortex-m = "0.7.0" - -# version is a wild guess. dependency on unproven features should only be -# present if own unproven feature is active (but how do i do that?). -embedded-hal = { version = "0.2.0", features = ["unproven"] } +embedded-hal = { version = "0.2.3", features = ["unproven"] } # for efm32gg, it's probably convenient to depend on the biggest available # svd2rust-generated crate (the chips will let us; FWICT all EFM32GG are the @@ -28,6 +25,7 @@ embedded-hal = { version = "0.2.0", features = ["unproven"] } # even smoother. efm32gg990 = { version = "0.1.2", optional = true } +efm32gg11b820 = { version = "0.9.0", optional = true } efr32xg1 = { version = "0.2.0", optional = true } [features] @@ -40,6 +38,7 @@ unproven = [] _routing_per_function = [] chip-efm32gg = [ "efm32gg990", "_has_timer2", "_has_timer3" ] +chip-efm32gg11b820 = [ "efm32gg11b820", "_has_timer2", "_has_timer3", "_has_timer4", "_has_timer5", "_has_timer6", "_routing_per_function", "_has_channel3" ] chip-efr32xg1 = [ "efr32xg1", "_routing_per_function" ] # Marker features pulled in by the individual chip features. Enabling them @@ -47,3 +46,7 @@ chip-efr32xg1 = [ "efr32xg1", "_routing_per_function" ] # that are not available). _has_timer2 = [] _has_timer3 = [] +_has_timer4 = [] +_has_timer5 = [] +_has_timer6 = [] +_has_channel3 = [] diff --git a/src/cmu.rs b/src/cmu.rs index 7b8c6bf..aa6775c 100644 --- a/src/cmu.rs +++ b/src/cmu.rs @@ -52,6 +52,12 @@ pub struct Clocks { pub timer2: TIMER2Clk, #[cfg(feature = "_has_timer3")] pub timer3: TIMER3Clk, + #[cfg(feature = "_has_timer4")] + pub timer4: TIMER4Clk, + #[cfg(feature = "_has_timer5")] + pub timer5: TIMER5Clk, + #[cfg(feature = "_has_timer6")] + pub timer6: TIMER6Clk, } pub struct I2C0Clk { @@ -96,6 +102,12 @@ timerclk!(TIMER1Clk, timer1); timerclk!(TIMER2Clk, timer2); #[cfg(feature = "_has_timer3")] timerclk!(TIMER3Clk, timer3); +#[cfg(feature = "_has_timer4")] +timerclk!(TIMER4Clk, timer4); +#[cfg(feature = "_has_timer5")] +timerclk!(TIMER5Clk, timer5); +#[cfg(feature = "_has_timer6")] +timerclk!(TIMER6Clk, timer6); pub struct GPIOClk { _private: (), @@ -108,7 +120,7 @@ impl GPIOClk { let cmu = &*registers::CMU::ptr(); #[cfg(feature = "chip-efm32gg")] cmu.hfperclken0.modify(|_, w| w.gpio().bit(true)); - #[cfg(feature = "chip-efr32xg1")] + #[cfg(any(feature = "chip-efr32xg1", feature = "chip-efm32gg11b820"))] cmu.hfbusclken0.modify(|_, w| w.gpio().bit(true)); } } @@ -126,6 +138,12 @@ impl Cmu { timer2: TIMER2Clk { _private: () }, #[cfg(feature = "_has_timer3")] timer3: TIMER3Clk { _private: () }, + #[cfg(feature = "_has_timer4")] + timer4: TIMER4Clk { _private: () }, + #[cfg(feature = "_has_timer5")] + timer5: TIMER5Clk { _private: () }, + #[cfg(feature = "_has_timer6")] + timer6: TIMER6Clk { _private: () }, } } } @@ -142,7 +160,7 @@ impl FrozenClock for HFCoreClk { { Hertz(14_000_000) } - #[cfg(feature = "chip-efr32xg1")] + #[cfg(any(feature = "chip-efr32xg1", feature = "chip-efm32gg11b820"))] { Hertz(19_000_000) } diff --git a/src/gpio.rs b/src/gpio.rs index 0f71f56..37dc94f 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -269,4 +269,52 @@ gpio!([ PF13: (pf13, 13, pf_din, pf_dout, mode13, pf_modeh), PF14: (pf14, 14, pf_din, pf_dout, mode14, pf_modeh), PF15: (pf15, 15, pf_din, pf_dout, mode15, pf_modeh), + PG0: (pg0, 0, pg_din, pg_dout, mode0, pg_model), + PG1: (pg1, 1, pg_din, pg_dout, mode1, pg_model), + PG2: (pg2, 2, pg_din, pg_dout, mode2, pg_model), + PG3: (pg3, 3, pg_din, pg_dout, mode3, pg_model), + PG4: (pg4, 4, pg_din, pg_dout, mode4, pg_model), + PG5: (pg5, 5, pg_din, pg_dout, mode5, pg_model), + PG6: (pg6, 6, pg_din, pg_dout, mode6, pg_model), + PG7: (pg7, 7, pg_din, pg_dout, mode7, pg_model), + PG8: (pg8, 8, pg_din, pg_dout, mode8, pg_modeh), + PG9: (pg9, 9, pg_din, pg_dout, mode9, pg_modeh), + PG10: (pg10, 10, pg_din, pg_dout, mode10, pg_modeh), + PG11: (pg11, 11, pg_din, pg_dout, mode11, pg_modeh), + PG12: (pg12, 12, pg_din, pg_dout, mode12, pg_modeh), + PG13: (pg13, 13, pg_din, pg_dout, mode13, pg_modeh), + PG14: (pg14, 14, pg_din, pg_dout, mode14, pg_modeh), + PG15: (pg15, 15, pg_din, pg_dout, mode15, pg_modeh), + PH0: (ph0, 0, ph_din, ph_dout, mode0, ph_model), + PH1: (ph1, 1, ph_din, ph_dout, mode1, ph_model), + PH2: (ph2, 2, ph_din, ph_dout, mode2, ph_model), + PH3: (ph3, 3, ph_din, ph_dout, mode3, ph_model), + PH4: (ph4, 4, ph_din, ph_dout, mode4, ph_model), + PH5: (ph5, 5, ph_din, ph_dout, mode5, ph_model), + PH6: (ph6, 6, ph_din, ph_dout, mode6, ph_model), + PH7: (ph7, 7, ph_din, ph_dout, mode7, ph_model), + PH8: (ph8, 8, ph_din, ph_dout, mode8, ph_modeh), + PH9: (ph9, 9, ph_din, ph_dout, mode9, ph_modeh), + PH10: (ph10, 10, ph_din, ph_dout, mode10, ph_modeh), + PH11: (ph11, 11, ph_din, ph_dout, mode11, ph_modeh), + PH12: (ph12, 12, ph_din, ph_dout, mode12, ph_modeh), + PH13: (ph13, 13, ph_din, ph_dout, mode13, ph_modeh), + PH14: (ph14, 14, ph_din, ph_dout, mode14, ph_modeh), + PH15: (ph15, 15, ph_din, ph_dout, mode15, ph_modeh), + PI0: (pi0, 0, pi_din, pi_dout, mode0, pi_model), + PI1: (pi1, 1, pi_din, pi_dout, mode1, pi_model), + PI2: (pi2, 2, pi_din, pi_dout, mode2, pi_model), + PI3: (pi3, 3, pi_din, pi_dout, mode3, pi_model), + PI4: (pi4, 4, pi_din, pi_dout, mode4, pi_model), + PI5: (pi5, 5, pi_din, pi_dout, mode5, pi_model), + PI6: (pi6, 6, pi_din, pi_dout, mode6, pi_model), + PI7: (pi7, 7, pi_din, pi_dout, mode7, pi_model), + PI8: (pi8, 8, pi_din, pi_dout, mode8, pi_modeh), + PI9: (pi9, 9, pi_din, pi_dout, mode9, pi_modeh), + PI10: (pi10, 10, pi_din, pi_dout, mode10, pi_modeh), + PI11: (pi11, 11, pi_din, pi_dout, mode11, pi_modeh), + PI12: (pi12, 12, pi_din, pi_dout, mode12, pi_modeh), + PI13: (pi13, 13, pi_din, pi_dout, mode13, pi_modeh), + PI14: (pi14, 14, pi_din, pi_dout, mode14, pi_modeh), + PI15: (pi15, 15, pi_din, pi_dout, mode15, pi_modeh), ]); diff --git a/src/lib.rs b/src/lib.rs index 55a2184..1b082bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ extern crate cortex_m; extern crate embedded_hal; +#[cfg(feature = "chip-efm32gg11b820")] +extern crate efm32gg11b820 as registers; #[cfg(feature = "chip-efm32gg")] extern crate efm32gg990 as registers; #[cfg(feature = "chip-efr32xg1")] diff --git a/src/routing.rs b/src/routing.rs index 6eec82a..eb732ea 100644 --- a/src/routing.rs +++ b/src/routing.rs @@ -18,5 +18,7 @@ mod per_peripheral; #[cfg(feature = "chip-efm32gg")] mod efm32gg; +#[cfg(feature = "chip-efm32gg11b820")] +mod efm32gg11; #[cfg(feature = "chip-efr32xg1")] mod efr32xg1; diff --git a/src/routing/efm32gg11.rs b/src/routing/efm32gg11.rs new file mode 100644 index 0000000..571f94b --- /dev/null +++ b/src/routing/efm32gg11.rs @@ -0,0 +1,202 @@ +use super::per_function::timerchannel_pin; +use crate::timer::{ + Channel0, Channel1, Channel2, Channel3, Timer0, Timer1, Timer2, Timer3, Timer4, Timer5, Timer6, +}; + +timerchannel_pin!(Timer0, Channel0, PA0, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PF6, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PD1, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PB6, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PF0, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PC4, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PA8, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer0, Channel0, PA1, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer0, Channel1, PA1, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PF7, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PD2, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PC0, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PF1, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PC5, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PA9, loc6, cc1loc, cc1pen); +timerchannel_pin!(Timer0, Channel1, PA0, loc7, cc1loc, cc1pen); + +timerchannel_pin!(Timer0, Channel2, PA2, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PF8, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PD3, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PC1, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PF2, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PA7, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PA10, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer0, Channel2, PA13, loc7, cc2loc, cc2pen); + +timerchannel_pin!(Timer1, Channel0, PC13, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PE10, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PB0, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PB7, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PD6, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PF2, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PF13, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer1, Channel0, PI6, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer1, Channel1, PC14, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PE11, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PB1, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PB8, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PD7, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PF3, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PF14, loc6, cc1loc, cc1pen); +timerchannel_pin!(Timer1, Channel1, PI7, loc7, cc1loc, cc1pen); + +timerchannel_pin!(Timer1, Channel2, PC15, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PE12, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PB2, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PB11, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PC13, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PF4, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PF15, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer1, Channel2, PI8, loc7, cc2loc, cc2pen); + +timerchannel_pin!(Timer1, Channel3, PC12, loc0, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PE13, loc1, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PB3, loc2, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PB12, loc3, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PC14, loc4, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PF12, loc5, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PF5, loc6, cc3loc, cc3pen); +timerchannel_pin!(Timer1, Channel3, PI9, loc7, cc3loc, cc3pen); + +timerchannel_pin!(Timer2, Channel0, PA8, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PA12, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PC8, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PF2, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PB6, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PC2, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PG8, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer2, Channel0, PG5, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer2, Channel1, PA9, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PA13, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PC9, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PE12, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PC0, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PC3, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PG9, loc6, cc1loc, cc1pen); +timerchannel_pin!(Timer2, Channel1, PG6, loc7, cc1loc, cc1pen); + +timerchannel_pin!(Timer2, Channel2, PA10, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PA14, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PC10, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PE13, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PC1, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PC4, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PG10, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer2, Channel2, PG7, loc7, cc2loc, cc2pen); + +timerchannel_pin!(Timer3, Channel0, PE14, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PE0, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PE3, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PE5, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PA0, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PA3, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PA6, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer3, Channel0, PD15, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer3, Channel1, PE15, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PE1, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PE4, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PE6, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PA1, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PA4, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PD13, loc6, cc1loc, cc1pen); +timerchannel_pin!(Timer3, Channel1, PB15, loc7, cc1loc, cc1pen); + +timerchannel_pin!(Timer3, Channel2, PA15, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PE2, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PE5, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PE7, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PA2, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PA5, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PD14, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer3, Channel2, PB0, loc7, cc2loc, cc2pen); + +timerchannel_pin!(Timer4, Channel0, PF3, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PF13, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PF5, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PF6, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PI8, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PF9, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PD11, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer4, Channel0, PE9, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer4, Channel1, PF4, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PF14, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PI6, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PI9, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PF7, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PD9, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PD12, loc6, cc1loc, cc1pen); +timerchannel_pin!(Timer4, Channel1, PE10, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer4, Channel2, PF12, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PF15, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PI7, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PI10, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PF8, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PD10, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PE8, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer4, Channel2, PE11, loc7, cc2loc, cc2pen); + +timerchannel_pin!(Timer5, Channel0, PE4, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PE7, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PH13, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PI0, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PC8, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PC11, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PC14, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer5, Channel0, PF12, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer5, Channel1, PE5, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PH11, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PH14, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PI1, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PC9, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PC12, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PF10, loc6, cc1loc, cc1pen); +timerchannel_pin!(Timer5, Channel1, PF13, loc7, cc1loc, cc1pen); + +timerchannel_pin!(Timer5, Channel2, PE6, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PH12, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PH15, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PI2, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PC10, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PC13, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PF11, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer5, Channel2, PF14, loc7, cc2loc, cc2pen); + +timerchannel_pin!(Timer6, Channel0, PG0, loc0, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PG6, loc1, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PG12, loc2, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PH2, loc3, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PH8, loc4, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PB13, loc5, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PD1, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel0, PD4, loc7, cc0loc, cc0pen); + +timerchannel_pin!(Timer6, Channel1, PG1, loc0, cc1loc, cc1pen); +timerchannel_pin!(Timer6, Channel1, PG7, loc1, cc1loc, cc1pen); +timerchannel_pin!(Timer6, Channel1, PG13, loc2, cc1loc, cc1pen); +timerchannel_pin!(Timer6, Channel1, PH3, loc3, cc1loc, cc1pen); +timerchannel_pin!(Timer6, Channel1, PH9, loc4, cc1loc, cc1pen); +timerchannel_pin!(Timer6, Channel1, PB14, loc5, cc1loc, cc1pen); +timerchannel_pin!(Timer6, Channel1, PD2, loc6, cc0loc, cc0pen); +timerchannel_pin!(Timer6, Channel1, PD5, loc7, cc1loc, cc1pen); + +timerchannel_pin!(Timer6, Channel2, PG2, loc0, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PG8, loc1, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PG14, loc2, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PH4, loc3, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PH10, loc4, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PD0, loc5, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PD3, loc6, cc2loc, cc2pen); +timerchannel_pin!(Timer6, Channel2, PD6, loc7, cc2loc, cc2pen); diff --git a/src/timer.rs b/src/timer.rs index c91b0a7..00d55ce 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -15,6 +15,9 @@ pub struct Channel0 {} pub struct Channel1 {} /// Marker type for timer channels, signifying they're a CC channel 2 of whichever timer pub struct Channel2 {} +#[cfg(feature = "_has_channel3")] +/// Marker type for timer channels, signifying they're a CC channel 3 of whichever timer +pub struct Channel3 {} /// Individual channel of a timer, accessible through a timer's .split() method. pub struct TimerChannel { @@ -61,6 +64,11 @@ pub struct RoutedTimerChannel { pub(crate) channel: TimerChannel, } +#[cfg(any(feature = "chip-efm32gg", feature = "chip-efr32xg1"))] +type TimerCount = u16; +#[cfg(feature = "chip-efm32gg11b820")] +type TimerCount = u32; + macro_rules! timer { ($TIMERn: ident, $TIMERnClk: ident, $TimerN: ident, $timerN: ident, $channel: tt) => { mod $timerN { @@ -89,7 +97,7 @@ macro_rules! timer { /// Configure the top value for this timer. /// /// As this limits the duty cycle, it can be read back using the PWM method get_max_duty(). - pub fn set_top(&mut self, top: u16) { + pub fn set_top(&mut self, top: TimerCount) { self.register .top .modify(|_, w| unsafe { w.top().bits(top) }); @@ -130,6 +138,10 @@ macro_rules! timer { channel2: TimerChannel { _phantom: PhantomData, }, + #[cfg(feature = "_has_channel3")] + channel3: TimerChannel { + _phantom: PhantomData, + }, } } } @@ -140,6 +152,8 @@ macro_rules! timer { pub channel0: TimerChannel<$TimerN, Channel0>, pub channel1: TimerChannel<$TimerN, Channel1>, pub channel2: TimerChannel<$TimerN, Channel2>, + #[cfg(feature = "_has_channel3")] + pub channel3: TimerChannel<$TimerN, Channel3>, } // Needs to be actually repeated over the channels because the channel structs can't, for example, @@ -148,6 +162,8 @@ macro_rules! timer { timerchannel!($TIMERn, $TimerN, $timerN, Channel0, cc0_ctrl, cc0_ccv, cc0_ccvb, cc0); timerchannel!($TIMERn, $TimerN, $timerN, Channel1, cc1_ctrl, cc1_ccv, cc1_ccvb, cc1); timerchannel!($TIMERn, $TimerN, $timerN, Channel2, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2); + #[cfg(feature = "_has_channel3")] + timerchannel!($TIMERn, $TimerN, $timerN, Channel3, cc3_ctrl, cc3_ccv, cc3_ccvb, cc3); } pub use $timerN::$TimerN; @@ -177,16 +193,16 @@ macro_rules! timerchannel { }); } fn get_mode(&self) -> ChannelMode { - use registers::$timerN::$ccX_ctrl::MODER; - match unsafe { &*Self::register() }.$ccX_ctrl.read().mode() { - MODER::OFF => ChannelMode::Off, - MODER::INPUTCAPTURE => ChannelMode::InputCapture, - MODER::OUTPUTCOMPARE => ChannelMode::OutputCompare, - MODER::PWM => ChannelMode::Pwm, + use registers::$timerN::$ccX_ctrl::MODE_A; + match unsafe { &*Self::register() }.$ccX_ctrl.read().mode().variant() { + MODE_A::OFF => ChannelMode::Off, + MODE_A::INPUTCAPTURE => ChannelMode::InputCapture, + MODE_A::OUTPUTCOMPARE => ChannelMode::OutputCompare, + MODE_A::PWM => ChannelMode::Pwm, } } - fn set_compare_buffered(&mut self, compare: u16) { + fn set_compare_buffered(&mut self, compare: TimerCount) { // Unsafe: OK because it's a CC0 register (see .register()) // Unsafe around bits: OK because any u16 value is permissible there unsafe { &mut *Self::register() } @@ -194,7 +210,7 @@ macro_rules! timerchannel { .modify(|_, w| unsafe { w.ccvb().bits(compare) }); } - fn set_compare_unbuffered(&mut self, compare: u16) { + fn set_compare_unbuffered(&mut self, compare: TimerCount) { // Unsafe: OK because it's a CC0 register (see .register()) // Unsafe around bits: OK because any u16 value is permissible there unsafe { &mut *Self::register() } @@ -202,7 +218,7 @@ macro_rules! timerchannel { .modify(|_, w| unsafe { w.ccv().bits(compare) }); } - fn get_compare_buffered(&self) -> u16 { + fn get_compare_buffered(&self) -> TimerCount { // Unsafe: OK because it's a CC0 register (see .register()) unsafe { &mut *Self::register() } .$ccX_ccvb @@ -216,7 +232,7 @@ macro_rules! timerchannel { /// /// This is a very conservative interface, and expected to be replaced once the author figures /// out how to expose the various possible use cases in a safe way. - pub fn prepare_interrupts(mut self, compare: u16) { + pub fn prepare_interrupts(mut self, compare: TimerCount) { self.set_compare_buffered(compare); self.set_mode(ChannelMode::OutputCompare); self.interrupt_enable(); @@ -272,7 +288,10 @@ macro_rules! timerchannel { } impl

embedded_hal::PwmPin for RoutedTimerChannel<$TimerN, $ChannelX, P> { + #[cfg(any(feature = "chip-efm32gg", feature = "chip-efr32xg1"))] type Duty = u16; // FIXME check the extreme behaviors + #[cfg(feature = "chip-efm32gg11b820")] + type Duty = u32; fn enable(&mut self) { self.channel.set_mode(ChannelMode::Pwm); @@ -329,6 +348,8 @@ timer!( (Channel0, cc0_ctrl, cc0_ccv, cc0_ccvb, cc0), (Channel1, cc1_ctrl, cc1_ccv, cc1_ccvb, cc1), (Channel2, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2), + #[cfg(feature = "_has_channel3")] + (Channel3, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2), ] ); #[cfg(feature = "_has_timer2")] @@ -355,3 +376,39 @@ timer!( (Channel2, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2), ] ); +#[cfg(feature = "_has_timer4")] +timer!( + TIMER4, + TIMER4Clk, + Timer4, + timer4, + [ + (Channel0, cc0_ctrl, cc0_ccv, cc0_ccvb, cc0), + (Channel1, cc1_ctrl, cc1_ccv, cc1_ccvb, cc1), + (Channel2, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2), + ] +); +#[cfg(feature = "_has_timer5")] +timer!( + TIMER5, + TIMER5Clk, + Timer5, + timer5, + [ + (Channel0, cc0_ctrl, cc0_ccv, cc0_ccvb, cc0), + (Channel1, cc1_ctrl, cc1_ccv, cc1_ccvb, cc1), + (Channel2, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2), + ] +); +#[cfg(feature = "_has_timer6")] +timer!( + TIMER6, + TIMER6Clk, + Timer6, + timer6, + [ + (Channel0, cc0_ctrl, cc0_ccv, cc0_ccvb, cc0), + (Channel1, cc1_ctrl, cc1_ccv, cc1_ccvb, cc1), + (Channel2, cc2_ctrl, cc2_ccv, cc2_ccvb, cc2), + ] +);