aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-08-29 19:41:03 -0500
committerxoviat <[email protected]>2023-08-29 19:41:03 -0500
commit989c98f316df3cde4512066e3682debb47d48161 (patch)
tree21530faa844e8760a04ece28d6fad56fb9f69408
parentfdb2c4946aeef968704c358fb52d5fea69e80dcc (diff)
stm32/rtc: autocompute prescalers
-rw-r--r--embassy-stm32/src/rcc/f4.rs1
-rw-r--r--embassy-stm32/src/rcc/mod.rs6
-rw-r--r--embassy-stm32/src/rtc/mod.rs72
-rw-r--r--embassy-stm32/src/rtc/v2.rs6
-rw-r--r--embassy-stm32/src/rtc/v3.rs6
5 files changed, 41 insertions, 50 deletions
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index 10d3322aa..c2c78a45e 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -499,6 +499,7 @@ pub(crate) unsafe fn init(config: Config) {
499 pllsai: None, 499 pllsai: None,
500 500
501 rtc: rtc, 501 rtc: rtc,
502 rtc_hse: None,
502 }); 503 });
503} 504}
504 505
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 9f1b3b663..1ead60b18 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -78,8 +78,12 @@ pub struct Clocks {
78 pub adc: Option<Hertz>, 78 pub adc: Option<Hertz>,
79 79
80 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 80 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
81 /// Set only if the lsi or lse is configured 81 /// Set only if the lsi or lse is configured, indicates stop is supported
82 pub rtc: Option<Hertz>, 82 pub rtc: Option<Hertz>,
83
84 #[cfg(any(rcc_f4, rcc_f410))]
85 /// Set if the hse is configured, indicates stop is not supported
86 pub rtc_hse: Option<Hertz>,
83} 87}
84 88
85#[cfg(feature = "low-power")] 89#[cfg(feature = "low-power")]
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 796fd7d96..3704e4464 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -12,6 +12,7 @@ use embassy_sync::blocking_mutex::Mutex;
12pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 12pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
13use crate::rcc::bd::BackupDomain; 13use crate::rcc::bd::BackupDomain;
14pub use crate::rcc::RtcClockSource; 14pub use crate::rcc::RtcClockSource;
15use crate::time::Hertz;
15 16
16/// refer to AN4759 to compare features of RTC2 and RTC3 17/// refer to AN4759 to compare features of RTC2 and RTC3
17#[cfg_attr(any(rtc_v1), path = "v1.rs")] 18#[cfg_attr(any(rtc_v1), path = "v1.rs")]
@@ -84,47 +85,23 @@ impl core::ops::Sub for RtcInstant {
84 85
85/// RTC Abstraction 86/// RTC Abstraction
86pub struct Rtc { 87pub struct Rtc {
87 rtc_config: RtcConfig,
88 #[cfg(feature = "low-power")] 88 #[cfg(feature = "low-power")]
89 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, 89 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>,
90} 90}
91 91
92#[derive(Copy, Clone, PartialEq)] 92#[derive(Copy, Clone, PartialEq)]
93pub struct RtcConfig { 93pub struct RtcConfig {
94 /// Asynchronous prescaler factor 94 /// The subsecond counter frequency; default is 256
95 /// This is the asynchronous division factor: 95 ///
96 /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) 96 /// A high counter frequency may impact stop power consumption
97 /// ck_apre drives the subsecond register 97 pub frequency: Hertz,
98 async_prescaler: u8,
99 /// Synchronous prescaler factor
100 /// This is the synchronous division factor:
101 /// ck_spre frequency = ck_apre frequency/(PREDIV_S+1)
102 /// ck_spre must be 1Hz
103 sync_prescaler: u16,
104} 98}
105 99
106impl Default for RtcConfig { 100impl Default for RtcConfig {
107 /// LSI with prescalers assuming 32.768 kHz. 101 /// LSI with prescalers assuming 32.768 kHz.
108 /// Raw sub-seconds in 1/256. 102 /// Raw sub-seconds in 1/256.
109 fn default() -> Self { 103 fn default() -> Self {
110 RtcConfig { 104 RtcConfig { frequency: Hertz(256) }
111 async_prescaler: 127,
112 sync_prescaler: 255,
113 }
114 }
115}
116
117impl RtcConfig {
118 /// Set the asynchronous prescaler of RTC config
119 pub fn async_prescaler(mut self, prescaler: u8) -> Self {
120 self.async_prescaler = prescaler;
121 self
122 }
123
124 /// Set the synchronous prescaler of RTC config
125 pub fn sync_prescaler(mut self, prescaler: u16) -> Self {
126 self.sync_prescaler = prescaler;
127 self
128 } 105 }
129} 106}
130 107
@@ -147,23 +124,36 @@ impl Default for RtcCalibrationCyclePeriod {
147 124
148impl Rtc { 125impl Rtc {
149 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 126 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
150 RTC::enable_peripheral_clk(); 127 use crate::rcc::get_freqs;
151 128
152 #[cfg(not(feature = "low-power"))] 129 RTC::enable_peripheral_clk();
153 let mut rtc_struct = Self { rtc_config }; 130 BackupDomain::enable_rtc();
154 131
155 #[cfg(feature = "low-power")] 132 let mut this = Self {
156 let mut rtc_struct = Self { 133 #[cfg(feature = "low-power")]
157 rtc_config,
158 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 134 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
159 }; 135 };
160 136
161 BackupDomain::enable_rtc(); 137 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
138 let freqs = unsafe { get_freqs() };
139
140 // Load the clock frequency from the rcc mod, if supported
141 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
142 let frequency = match freqs.rtc {
143 Some(hertz) => hertz,
144 None => freqs.rtc_hse.unwrap(),
145 };
162 146
163 rtc_struct.configure(rtc_config); 147 // Assume the default value, if not supported
164 rtc_struct.rtc_config = rtc_config; 148 #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))]
149 let frequency = Hertz(32_768);
165 150
166 rtc_struct 151 let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8;
152 let sync_psc = (rtc_config.frequency.0 - 1) as u16;
153
154 this.configure(async_psc, sync_psc);
155
156 this
167 } 157 }
168 158
169 /// Set the datetime to a new value. 159 /// Set the datetime to a new value.
@@ -228,10 +218,6 @@ impl Rtc {
228 }) 218 })
229 } 219 }
230 220
231 pub fn get_config(&self) -> RtcConfig {
232 self.rtc_config
233 }
234
235 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; 221 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT;
236 222
237 /// Read content of the backup register. 223 /// Read content of the backup register.
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index 49f66e957..63d9f09e7 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -154,7 +154,7 @@ impl super::Rtc {
154 154
155 /// Applies the RTC config 155 /// Applies the RTC config
156 /// It this changes the RTC clock source the time will be reset 156 /// It this changes the RTC clock source the time will be reset
157 pub(super) fn configure(&mut self, rtc_config: RtcConfig) { 157 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
158 self.write(true, |rtc| { 158 self.write(true, |rtc| {
159 rtc.cr().modify(|w| { 159 rtc.cr().modify(|w| {
160 #[cfg(rtc_v2f2)] 160 #[cfg(rtc_v2f2)]
@@ -166,8 +166,8 @@ impl super::Rtc {
166 }); 166 });
167 167
168 rtc.prer().modify(|w| { 168 rtc.prer().modify(|w| {
169 w.set_prediv_s(rtc_config.sync_prescaler); 169 w.set_prediv_s(sync_psc);
170 w.set_prediv_a(rtc_config.async_prescaler); 170 w.set_prediv_a(async_psc);
171 }); 171 });
172 }); 172 });
173 } 173 }
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index 12952b15a..c03b1071d 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -8,7 +8,7 @@ use crate::rtc::sealed::Instance;
8impl super::Rtc { 8impl super::Rtc {
9 /// Applies the RTC config 9 /// Applies the RTC config
10 /// It this changes the RTC clock source the time will be reset 10 /// It this changes the RTC clock source the time will be reset
11 pub(super) fn configure(&mut self, rtc_config: RtcConfig) { 11 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
12 self.write(true, |rtc| { 12 self.write(true, |rtc| {
13 rtc.cr().modify(|w| { 13 rtc.cr().modify(|w| {
14 w.set_fmt(Fmt::TWENTYFOURHOUR); 14 w.set_fmt(Fmt::TWENTYFOURHOUR);
@@ -17,8 +17,8 @@ impl super::Rtc {
17 }); 17 });
18 18
19 rtc.prer().modify(|w| { 19 rtc.prer().modify(|w| {
20 w.set_prediv_s(rtc_config.sync_prescaler); 20 w.set_prediv_s(sync_psc);
21 w.set_prediv_a(rtc_config.async_prescaler); 21 w.set_prediv_a(async_psc);
22 }); 22 });
23 23
24 // TODO: configuration for output pins 24 // TODO: configuration for output pins