aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorRick Rogers <[email protected]>2025-07-25 11:34:21 -0400
committerRick Rogers <[email protected]>2025-07-25 11:34:21 -0400
commit33fc82a455df058c5bdef23b68304a3dcb33f069 (patch)
tree63f876b833e5ced8863b0b4825e8ab822190dd13 /embassy-stm32
parent24b2794931e73325ad969d83453d0cf872ac4775 (diff)
parent996974e313fa5ec2c7c2d9dd0998fab244c0a180 (diff)
Merge branch 'main' into h7rs-xspi-fixes
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/src/dac/mod.rs40
-rw-r--r--embassy-stm32/src/i2c/v2.rs278
-rw-r--r--embassy-stm32/src/lptim/timer/mod.rs50
-rw-r--r--embassy-stm32/src/rcc/u5.rs165
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs13
6 files changed, 482 insertions, 65 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 38254ee40..02e75733e 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -129,6 +129,7 @@ defmt = [
129 "embassy-net-driver/defmt", 129 "embassy-net-driver/defmt",
130 "embassy-time?/defmt", 130 "embassy-time?/defmt",
131 "embassy-usb-synopsys-otg/defmt", 131 "embassy-usb-synopsys-otg/defmt",
132 "stm32-metapac/defmt"
132] 133]
133 134
134exti = [] 135exti = []
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 30046849b..d8f1f96f2 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -403,6 +403,46 @@ impl<'d, T: Instance> Dac<'d, T, Async> {
403 Mode::NormalExternalBuffered, 403 Mode::NormalExternalBuffered,
404 ) 404 )
405 } 405 }
406 /// Create a new `Dac` instance with external output pins and unbuffered mode.
407 ///
408 /// This function consumes the underlying DAC peripheral and allows access to both channels.
409 /// The channels are configured for external output with the buffer disabled.
410 ///
411 /// The channels are enabled on creation and begin to drive their output pins.
412 /// Note that some methods, such as `set_trigger()` and `set_mode()`, will
413 /// disable the channel; you must re-enable them with `enable()`.
414 ///
415 /// By default, triggering is disabled, but it can be enabled using the `set_trigger()`
416 /// method on the underlying channels.
417 ///
418 /// # Arguments
419 ///
420 /// * `peri` - The DAC peripheral instance.
421 /// * `dma_ch1` - The DMA channel for DAC channel 1.
422 /// * `dma_ch2` - The DMA channel for DAC channel 2.
423 /// * `pin_ch1` - The GPIO pin for DAC channel 1 output.
424 /// * `pin_ch2` - The GPIO pin for DAC channel 2 output.
425 ///
426 /// # Returns
427 ///
428 /// A new `Dac` instance in unbuffered mode.
429 pub fn new_unbuffered(
430 peri: Peri<'d, T>,
431 dma_ch1: Peri<'d, impl Dma<T, Ch1>>,
432 dma_ch2: Peri<'d, impl Dma<T, Ch2>>,
433 pin_ch1: Peri<'d, impl DacPin<T, Ch1> + crate::gpio::Pin>,
434 pin_ch2: Peri<'d, impl DacPin<T, Ch2> + crate::gpio::Pin>,
435 ) -> Self {
436 pin_ch1.set_as_analog();
437 pin_ch2.set_as_analog();
438 Self::new_inner(
439 peri,
440 new_dma!(dma_ch1),
441 new_dma!(dma_ch2),
442 #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))]
443 Mode::NormalExternalUnbuffered,
444 )
445 }
406 446
407 /// Create a new `Dac` instance where the external output pins are not used, 447 /// Create a new `Dac` instance where the external output pins are not used,
408 /// so the DAC can only be used to generate internal signals but the GPIO 448 /// so the DAC can only be used to generate internal signals but the GPIO
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 35dc91c86..e24cce5c6 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -36,11 +36,46 @@ impl Address {
36 } 36 }
37} 37}
38 38
39enum ReceiveResult {
40 DataAvailable,
41 StopReceived,
42 NewStart,
43}
44
45fn debug_print_interrupts(isr: stm32_metapac::i2c::regs::Isr) {
46 if isr.tcr() {
47 trace!("interrupt: tcr");
48 }
49 if isr.tc() {
50 trace!("interrupt: tc");
51 }
52 if isr.addr() {
53 trace!("interrupt: addr");
54 }
55 if isr.stopf() {
56 trace!("interrupt: stopf");
57 }
58 if isr.nackf() {
59 trace!("interrupt: nackf");
60 }
61 if isr.berr() {
62 trace!("interrupt: berr");
63 }
64 if isr.arlo() {
65 trace!("interrupt: arlo");
66 }
67 if isr.ovr() {
68 trace!("interrupt: ovr");
69 }
70}
71
39pub(crate) unsafe fn on_interrupt<T: Instance>() { 72pub(crate) unsafe fn on_interrupt<T: Instance>() {
40 let regs = T::info().regs; 73 let regs = T::info().regs;
41 let isr = regs.isr().read(); 74 let isr = regs.isr().read();
42 75
43 if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() { 76 if isr.tcr() || isr.tc() || isr.addr() || isr.stopf() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() {
77 debug_print_interrupts(isr);
78
44 T::state().waker.wake(); 79 T::state().waker.wake();
45 } 80 }
46 81
@@ -193,49 +228,132 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
193 228
194 fn flush_txdr(&self) { 229 fn flush_txdr(&self) {
195 if self.info.regs.isr().read().txis() { 230 if self.info.regs.isr().read().txis() {
196 self.info.regs.txdr().write(|w| w.set_txdata(0)); 231 trace!("Flush TXDATA with zeroes");
232 self.info.regs.txdr().modify(|w| w.set_txdata(0));
197 } 233 }
198 if !self.info.regs.isr().read().txe() { 234 if !self.info.regs.isr().read().txe() {
235 trace!("Flush TXDR");
199 self.info.regs.isr().modify(|w| w.set_txe(true)) 236 self.info.regs.isr().modify(|w| w.set_txe(true))
200 } 237 }
201 } 238 }
202 239
203 fn wait_txe(&self, timeout: Timeout) -> Result<(), Error> { 240 fn error_occurred(&self, isr: &i2c::regs::Isr, timeout: Timeout) -> Result<(), Error> {
241 if isr.nackf() {
242 trace!("NACK triggered.");
243 self.info.regs.icr().modify(|reg| reg.set_nackcf(true));
244 // NACK should be followed by STOP
245 if let Ok(()) = self.wait_stop(timeout) {
246 trace!("Got STOP after NACK, clearing flag.");
247 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
248 }
249 self.flush_txdr();
250 return Err(Error::Nack);
251 } else if isr.berr() {
252 trace!("BERR triggered.");
253 self.info.regs.icr().modify(|reg| reg.set_berrcf(true));
254 self.flush_txdr();
255 return Err(Error::Bus);
256 } else if isr.arlo() {
257 trace!("ARLO triggered.");
258 self.info.regs.icr().modify(|reg| reg.set_arlocf(true));
259 self.flush_txdr();
260 return Err(Error::Arbitration);
261 } else if isr.ovr() {
262 trace!("OVR triggered.");
263 self.info.regs.icr().modify(|reg| reg.set_ovrcf(true));
264 return Err(Error::Overrun);
265 }
266 return Ok(());
267 }
268
269 fn wait_txis(&self, timeout: Timeout) -> Result<(), Error> {
270 let mut first_loop = true;
271
204 loop { 272 loop {
205 let isr = self.info.regs.isr().read(); 273 let isr = self.info.regs.isr().read();
206 if isr.txe() { 274 self.error_occurred(&isr, timeout)?;
275 if isr.txis() {
276 trace!("TXIS");
207 return Ok(()); 277 return Ok(());
208 } else if isr.berr() {
209 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
210 return Err(Error::Bus);
211 } else if isr.arlo() {
212 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
213 return Err(Error::Arbitration);
214 } else if isr.nackf() {
215 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
216 self.flush_txdr();
217 return Err(Error::Nack);
218 } 278 }
219 279
280 {
281 if first_loop {
282 trace!("Waiting for TXIS...");
283 first_loop = false;
284 }
285 }
220 timeout.check()?; 286 timeout.check()?;
221 } 287 }
222 } 288 }
223 289
224 fn wait_rxne(&self, timeout: Timeout) -> Result<(), Error> { 290 fn wait_stop_or_err(&self, timeout: Timeout) -> Result<(), Error> {
291 loop {
292 let isr = self.info.regs.isr().read();
293 self.error_occurred(&isr, timeout)?;
294 if isr.stopf() {
295 trace!("STOP triggered.");
296 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
297 return Ok(());
298 }
299 timeout.check()?;
300 }
301 }
302 fn wait_stop(&self, timeout: Timeout) -> Result<(), Error> {
225 loop { 303 loop {
226 let isr = self.info.regs.isr().read(); 304 let isr = self.info.regs.isr().read();
227 if isr.rxne() { 305 if isr.stopf() {
306 trace!("STOP triggered.");
307 self.info.regs.icr().modify(|reg| reg.set_stopcf(true));
228 return Ok(()); 308 return Ok(());
229 } else if isr.berr() { 309 }
230 self.info.regs.icr().write(|reg| reg.set_berrcf(true)); 310 timeout.check()?;
231 return Err(Error::Bus); 311 }
232 } else if isr.arlo() { 312 }
233 self.info.regs.icr().write(|reg| reg.set_arlocf(true)); 313
234 return Err(Error::Arbitration); 314 fn wait_af(&self, timeout: Timeout) -> Result<(), Error> {
235 } else if isr.nackf() { 315 loop {
236 self.info.regs.icr().write(|reg| reg.set_nackcf(true)); 316 let isr = self.info.regs.isr().read();
237 self.flush_txdr(); 317 if isr.nackf() {
238 return Err(Error::Nack); 318 trace!("AF triggered.");
319 self.info.regs.icr().modify(|reg| reg.set_nackcf(true));
320 return Ok(());
321 }
322 timeout.check()?;
323 }
324 }
325
326 fn wait_rxne(&self, timeout: Timeout) -> Result<ReceiveResult, Error> {
327 let mut first_loop = true;
328
329 loop {
330 let isr = self.info.regs.isr().read();
331 self.error_occurred(&isr, timeout)?;
332 if isr.stopf() {
333 trace!("STOP when waiting for RXNE.");
334 if self.info.regs.isr().read().rxne() {
335 trace!("Data received with STOP.");
336 return Ok(ReceiveResult::DataAvailable);
337 }
338 trace!("STOP triggered without data.");
339 return Ok(ReceiveResult::StopReceived);
340 } else if isr.rxne() {
341 trace!("RXNE.");
342 return Ok(ReceiveResult::DataAvailable);
343 } else if isr.addr() {
344 // Another addr event received, which means START was sent again
345 // which happens when accessing memory registers (common i2c interface design)
346 // e.g. master sends: START, write 1 byte (register index), START, read N bytes (until NACK)
347 // Possible to receive this flag at the same time as rxne, so check rxne first
348 trace!("START when waiting for RXNE. Ending receive loop.");
349 // Return without clearing ADDR so `listen` can catch it
350 return Ok(ReceiveResult::NewStart);
351 }
352 {
353 if first_loop {
354 trace!("Waiting for RXNE...");
355 first_loop = false;
356 }
239 } 357 }
240 358
241 timeout.check()?; 359 timeout.check()?;
@@ -245,20 +363,10 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
245 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> { 363 fn wait_tc(&self, timeout: Timeout) -> Result<(), Error> {
246 loop { 364 loop {
247 let isr = self.info.regs.isr().read(); 365 let isr = self.info.regs.isr().read();
366 self.error_occurred(&isr, timeout)?;
248 if isr.tc() { 367 if isr.tc() {
249 return Ok(()); 368 return Ok(());
250 } else if isr.berr() {
251 self.info.regs.icr().write(|reg| reg.set_berrcf(true));
252 return Err(Error::Bus);
253 } else if isr.arlo() {
254 self.info.regs.icr().write(|reg| reg.set_arlocf(true));
255 return Err(Error::Arbitration);
256 } else if isr.nackf() {
257 self.info.regs.icr().write(|reg| reg.set_nackcf(true));
258 self.flush_txdr();
259 return Err(Error::Nack);
260 } 369 }
261
262 timeout.check()?; 370 timeout.check()?;
263 } 371 }
264 } 372 }
@@ -344,7 +452,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
344 // Wait until we are allowed to send data 452 // Wait until we are allowed to send data
345 // (START has been ACKed or last byte when 453 // (START has been ACKed or last byte when
346 // through) 454 // through)
347 if let Err(err) = self.wait_txe(timeout) { 455 if let Err(err) = self.wait_txis(timeout) {
348 if send_stop { 456 if send_stop {
349 self.master_stop(); 457 self.master_stop();
350 } 458 }
@@ -459,7 +567,7 @@ impl<'d, M: Mode, IM: MasterMode> I2c<'d, M, IM> {
459 // Wait until we are allowed to send data 567 // Wait until we are allowed to send data
460 // (START has been ACKed or last byte when 568 // (START has been ACKed or last byte when
461 // through) 569 // through)
462 if let Err(err) = self.wait_txe(timeout) { 570 if let Err(err) = self.wait_txis(timeout) {
463 self.master_stop(); 571 self.master_stop();
464 return Err(err); 572 return Err(err);
465 } 573 }
@@ -884,10 +992,11 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
884 // clear the address flag, will stop the clock stretching. 992 // clear the address flag, will stop the clock stretching.
885 // this should only be done after the dma transfer has been set up. 993 // this should only be done after the dma transfer has been set up.
886 info.regs.icr().modify(|reg| reg.set_addrcf(true)); 994 info.regs.icr().modify(|reg| reg.set_addrcf(true));
995 trace!("ADDRCF cleared (ADDR interrupt enabled, clock stretching ended)");
887 } 996 }
888 997
889 // A blocking read operation 998 // A blocking read operation
890 fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<(), Error> { 999 fn slave_read_internal(&self, read: &mut [u8], timeout: Timeout) -> Result<usize, Error> {
891 let completed_chunks = read.len() / 255; 1000 let completed_chunks = read.len() / 255;
892 let total_chunks = if completed_chunks * 255 == read.len() { 1001 let total_chunks = if completed_chunks * 255 == read.len() {
893 completed_chunks 1002 completed_chunks
@@ -895,20 +1004,46 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
895 completed_chunks + 1 1004 completed_chunks + 1
896 }; 1005 };
897 let last_chunk_idx = total_chunks.saturating_sub(1); 1006 let last_chunk_idx = total_chunks.saturating_sub(1);
1007 let total_len = read.len();
1008 let mut remaining_len = total_len;
1009
898 for (number, chunk) in read.chunks_mut(255).enumerate() { 1010 for (number, chunk) in read.chunks_mut(255).enumerate() {
899 if number != 0 { 1011 trace!(
1012 "--- Slave RX transmission start - chunk: {}, expected (max) size: {}",
1013 number,
1014 chunk.len()
1015 );
1016 if number == 0 {
1017 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1018 } else {
900 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1019 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
901 } 1020 }
902 1021
1022 let mut index = 0;
1023
903 for byte in chunk { 1024 for byte in chunk {
904 // Wait until we have received something 1025 // Wait until we have received something
905 self.wait_rxne(timeout)?; 1026 match self.wait_rxne(timeout) {
906 1027 Ok(ReceiveResult::StopReceived) | Ok(ReceiveResult::NewStart) => {
907 *byte = self.info.regs.rxdr().read().rxdata(); 1028 trace!("--- Slave RX transmission end (early)");
1029 return Ok(total_len - remaining_len); // Return N bytes read
1030 }
1031 Ok(ReceiveResult::DataAvailable) => {
1032 *byte = self.info.regs.rxdr().read().rxdata();
1033 remaining_len = remaining_len.saturating_sub(1);
1034 {
1035 trace!("Slave RX data {}: {:#04x}", index, byte);
1036 index = index + 1;
1037 }
1038 }
1039 Err(e) => return Err(e),
1040 };
908 } 1041 }
909 } 1042 }
1043 self.wait_stop_or_err(timeout)?;
910 1044
911 Ok(()) 1045 trace!("--- Slave RX transmission end");
1046 Ok(total_len - remaining_len) // Return N bytes read
912 } 1047 }
913 1048
914 // A blocking write operation 1049 // A blocking write operation
@@ -922,19 +1057,36 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
922 let last_chunk_idx = total_chunks.saturating_sub(1); 1057 let last_chunk_idx = total_chunks.saturating_sub(1);
923 1058
924 for (number, chunk) in write.chunks(255).enumerate() { 1059 for (number, chunk) in write.chunks(255).enumerate() {
925 if number != 0 { 1060 trace!(
1061 "--- Slave TX transmission start - chunk: {}, size: {}",
1062 number,
1063 chunk.len()
1064 );
1065 if number == 0 {
1066 Self::slave_start(self.info, chunk.len(), number != last_chunk_idx);
1067 } else {
926 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?; 1068 Self::reload(self.info, chunk.len(), number != last_chunk_idx, timeout)?;
927 } 1069 }
928 1070
1071 let mut index = 0;
1072
929 for byte in chunk { 1073 for byte in chunk {
930 // Wait until we are allowed to send data 1074 // Wait until we are allowed to send data
931 // (START has been ACKed or last byte when 1075 // (START has been ACKed or last byte when through)
932 // through) 1076 self.wait_txis(timeout)?;
933 self.wait_txe(timeout)?;
934 1077
1078 {
1079 trace!("Slave TX data {}: {:#04x}", index, byte);
1080 index = index + 1;
1081 }
935 self.info.regs.txdr().write(|w| w.set_txdata(*byte)); 1082 self.info.regs.txdr().write(|w| w.set_txdata(*byte));
936 } 1083 }
937 } 1084 }
1085 self.wait_af(timeout)?;
1086 self.flush_txdr();
1087 self.wait_stop_or_err(timeout)?;
1088
1089 trace!("--- Slave TX transmission end");
938 Ok(()) 1090 Ok(())
939 } 1091 }
940 1092
@@ -945,6 +1097,7 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
945 let state = self.state; 1097 let state = self.state;
946 self.info.regs.cr1().modify(|reg| { 1098 self.info.regs.cr1().modify(|reg| {
947 reg.set_addrie(true); 1099 reg.set_addrie(true);
1100 trace!("Enable ADDRIE");
948 }); 1101 });
949 1102
950 poll_fn(|cx| { 1103 poll_fn(|cx| {
@@ -953,17 +1106,24 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
953 if !isr.addr() { 1106 if !isr.addr() {
954 Poll::Pending 1107 Poll::Pending
955 } else { 1108 } else {
1109 trace!("ADDR triggered (address match)");
956 // we do not clear the address flag here as it will be cleared by the dma read/write 1110 // we do not clear the address flag here as it will be cleared by the dma read/write
957 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it 1111 // if we clear it here the clock stretching will stop and the master will read in data before the slave is ready to send it
958 match isr.dir() { 1112 match isr.dir() {
959 i2c::vals::Dir::WRITE => Poll::Ready(Ok(SlaveCommand { 1113 i2c::vals::Dir::WRITE => {
960 kind: SlaveCommandKind::Write, 1114 trace!("DIR: write");
961 address: self.determine_matched_address()?, 1115 Poll::Ready(Ok(SlaveCommand {
962 })), 1116 kind: SlaveCommandKind::Write,
963 i2c::vals::Dir::READ => Poll::Ready(Ok(SlaveCommand { 1117 address: self.determine_matched_address()?,
964 kind: SlaveCommandKind::Read, 1118 }))
965 address: self.determine_matched_address()?, 1119 }
966 })), 1120 i2c::vals::Dir::READ => {
1121 trace!("DIR: read");
1122 Poll::Ready(Ok(SlaveCommand {
1123 kind: SlaveCommandKind::Read,
1124 address: self.determine_matched_address()?,
1125 }))
1126 }
967 } 1127 }
968 } 1128 }
969 }) 1129 })
@@ -971,7 +1131,9 @@ impl<'d, M: Mode> I2c<'d, M, MultiMaster> {
971 } 1131 }
972 1132
973 /// Respond to a write command. 1133 /// Respond to a write command.
974 pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<(), Error> { 1134 ///
1135 /// Returns total number of bytes received.
1136 pub fn blocking_respond_to_write(&self, read: &mut [u8]) -> Result<usize, Error> {
975 let timeout = self.timeout(); 1137 let timeout = self.timeout();
976 self.slave_read_internal(read, timeout) 1138 self.slave_read_internal(read, timeout)
977 } 1139 }
@@ -1025,7 +1187,7 @@ impl<'d> I2c<'d, Async, MultiMaster> {
1025 w.set_rxdmaen(false); 1187 w.set_rxdmaen(false);
1026 w.set_stopie(false); 1188 w.set_stopie(false);
1027 w.set_tcie(false); 1189 w.set_tcie(false);
1028 }) 1190 });
1029 }); 1191 });
1030 1192
1031 let total_received = poll_fn(|cx| { 1193 let total_received = poll_fn(|cx| {
diff --git a/embassy-stm32/src/lptim/timer/mod.rs b/embassy-stm32/src/lptim/timer/mod.rs
index a629be62b..648da5940 100644
--- a/embassy-stm32/src/lptim/timer/mod.rs
+++ b/embassy-stm32/src/lptim/timer/mod.rs
@@ -115,6 +115,31 @@ impl<'d, T: Instance> Timer<'d, T> {
115 .ccmr(0) 115 .ccmr(0)
116 .modify(|w| w.set_ccsel(channel.index(), direction.into())); 116 .modify(|w| w.set_ccsel(channel.index(), direction.into()));
117 } 117 }
118
119 /// Enable the timer interrupt.
120 pub fn enable_interrupt(&self) {
121 T::regs().dier().modify(|w| w.set_arrmie(true));
122 }
123
124 /// Disable the timer interrupt.
125 pub fn disable_interrupt(&self) {
126 T::regs().dier().modify(|w| w.set_arrmie(false));
127 }
128
129 /// Check if the timer interrupt is enabled.
130 pub fn is_interrupt_enabled(&self) -> bool {
131 T::regs().dier().read().arrmie()
132 }
133
134 /// Check if the timer interrupt is pending.
135 pub fn is_interrupt_pending(&self) -> bool {
136 T::regs().isr().read().arrm()
137 }
138
139 /// Clear the timer interrupt.
140 pub fn clear_interrupt(&self) {
141 T::regs().icr().write(|w| w.set_arrmcf(true));
142 }
118} 143}
119 144
120#[cfg(not(any(lptim_v2a, lptim_v2b)))] 145#[cfg(not(any(lptim_v2a, lptim_v2b)))]
@@ -128,4 +153,29 @@ impl<'d, T: Instance> Timer<'d, T> {
128 pub fn get_compare_value(&self) -> u16 { 153 pub fn get_compare_value(&self) -> u16 {
129 T::regs().cmp().read().cmp() 154 T::regs().cmp().read().cmp()
130 } 155 }
156
157 /// Enable the timer interrupt.
158 pub fn enable_interrupt(&self) {
159 T::regs().ier().modify(|w| w.set_arrmie(true));
160 }
161
162 /// Disable the timer interrupt.
163 pub fn disable_interrupt(&self) {
164 T::regs().ier().modify(|w| w.set_arrmie(false));
165 }
166
167 /// Check if the timer interrupt is enabled.
168 pub fn is_interrupt_enabled(&self) -> bool {
169 T::regs().ier().read().arrmie()
170 }
171
172 /// Check if the timer interrupt is pending.
173 pub fn is_interrupt_pending(&self) -> bool {
174 T::regs().isr().read().arrm()
175 }
176
177 /// Clear the timer interrupt.
178 pub fn clear_interrupt(&self) {
179 T::regs().icr().write(|w| w.set_arrmcf(true));
180 }
131} 181}
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 97eb2eb6d..06895a99a 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -5,7 +5,7 @@ pub use crate::pac::rcc::vals::{
5 Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, 5 Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
6 Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, 6 Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk,
7}; 7};
8use crate::pac::rcc::vals::{Hseext, Msirgsel, Pllmboost, Pllrge}; 8use crate::pac::rcc::vals::{Hseext, Msipllfast, Msipllsel, Msirgsel, Pllmboost, Pllrge};
9#[cfg(all(peri_usb_otg_hs))] 9#[cfg(all(peri_usb_otg_hs))]
10pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; 10pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG};
11use crate::pac::{FLASH, PWR, RCC}; 11use crate::pac::{FLASH, PWR, RCC};
@@ -64,6 +64,46 @@ pub struct Pll {
64 pub divr: Option<PllDiv>, 64 pub divr: Option<PllDiv>,
65} 65}
66 66
67#[derive(Clone, Copy, PartialEq)]
68pub enum MsiAutoCalibration {
69 /// MSI auto-calibration is disabled
70 Disabled,
71 /// MSIS is given priority for auto-calibration
72 MSIS,
73 /// MSIK is given priority for auto-calibration
74 MSIK,
75 /// MSIS with fast mode (always on)
76 MsisFast,
77 /// MSIK with fast mode (always on)
78 MsikFast,
79}
80
81impl MsiAutoCalibration {
82 const fn default() -> Self {
83 MsiAutoCalibration::Disabled
84 }
85
86 fn base_mode(&self) -> Self {
87 match self {
88 MsiAutoCalibration::Disabled => MsiAutoCalibration::Disabled,
89 MsiAutoCalibration::MSIS => MsiAutoCalibration::MSIS,
90 MsiAutoCalibration::MSIK => MsiAutoCalibration::MSIK,
91 MsiAutoCalibration::MsisFast => MsiAutoCalibration::MSIS,
92 MsiAutoCalibration::MsikFast => MsiAutoCalibration::MSIK,
93 }
94 }
95
96 fn is_fast(&self) -> bool {
97 matches!(self, MsiAutoCalibration::MsisFast | MsiAutoCalibration::MsikFast)
98 }
99}
100
101impl Default for MsiAutoCalibration {
102 fn default() -> Self {
103 Self::default()
104 }
105}
106
67#[derive(Clone, Copy)] 107#[derive(Clone, Copy)]
68pub struct Config { 108pub struct Config {
69 // base clock sources 109 // base clock sources
@@ -95,6 +135,7 @@ pub struct Config {
95 135
96 /// Per-peripheral kernel clock selection muxes 136 /// Per-peripheral kernel clock selection muxes
97 pub mux: super::mux::ClockMux, 137 pub mux: super::mux::ClockMux,
138 pub auto_calibration: MsiAutoCalibration,
98} 139}
99 140
100impl Config { 141impl Config {
@@ -116,6 +157,7 @@ impl Config {
116 voltage_range: VoltageScale::RANGE1, 157 voltage_range: VoltageScale::RANGE1,
117 ls: crate::rcc::LsConfig::new(), 158 ls: crate::rcc::LsConfig::new(),
118 mux: super::mux::ClockMux::default(), 159 mux: super::mux::ClockMux::default(),
160 auto_calibration: MsiAutoCalibration::default(),
119 } 161 }
120 } 162 }
121} 163}
@@ -131,7 +173,42 @@ pub(crate) unsafe fn init(config: Config) {
131 PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); 173 PWR.vosr().modify(|w| w.set_vos(config.voltage_range));
132 while !PWR.vosr().read().vosrdy() {} 174 while !PWR.vosr().read().vosrdy() {}
133 175
134 let msis = config.msis.map(|range| { 176 let lse_calibration_freq = if config.auto_calibration != MsiAutoCalibration::Disabled {
177 // LSE must be configured and peripherals clocked for MSI auto-calibration
178 let lse_config = config
179 .ls
180 .lse
181 .clone()
182 .expect("LSE must be configured for MSI auto-calibration");
183 assert!(lse_config.peripherals_clocked);
184
185 // Expect less than +/- 5% deviation for LSE frequency
186 if (31_100..=34_400).contains(&lse_config.frequency.0) {
187 // Check that the calibration is applied to an active clock
188 match (
189 config.auto_calibration.base_mode(),
190 config.msis.is_some(),
191 config.msik.is_some(),
192 ) {
193 (MsiAutoCalibration::MSIS, true, _) => {
194 // MSIS is active and using LSE for auto-calibration
195 Some(lse_config.frequency)
196 }
197 (MsiAutoCalibration::MSIK, _, true) => {
198 // MSIK is active and using LSE for auto-calibration
199 Some(lse_config.frequency)
200 }
201 // improper configuration
202 _ => panic!("MSIx auto-calibration is enabled for a source that has not been configured."),
203 }
204 } else {
205 panic!("LSE frequency more than 5% off from 32.768 kHz, cannot use for MSI auto-calibration");
206 }
207 } else {
208 None
209 };
210
211 let mut msis = config.msis.map(|range| {
135 // Check MSI output per RM0456 § 11.4.10 212 // Check MSI output per RM0456 § 11.4.10
136 match config.voltage_range { 213 match config.voltage_range {
137 VoltageScale::RANGE4 => { 214 VoltageScale::RANGE4 => {
@@ -156,11 +233,21 @@ pub(crate) unsafe fn init(config: Config) {
156 w.set_msipllen(false); 233 w.set_msipllen(false);
157 w.set_msison(true); 234 w.set_msison(true);
158 }); 235 });
236 let msis = if let (Some(freq), MsiAutoCalibration::MSIS) =
237 (lse_calibration_freq, config.auto_calibration.base_mode())
238 {
239 // Enable the MSIS auto-calibration feature
240 RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIS));
241 RCC.cr().modify(|w| w.set_msipllen(true));
242 calculate_calibrated_msi_frequency(range, freq)
243 } else {
244 msirange_to_hertz(range)
245 };
159 while !RCC.cr().read().msisrdy() {} 246 while !RCC.cr().read().msisrdy() {}
160 msirange_to_hertz(range) 247 msis
161 }); 248 });
162 249
163 let msik = config.msik.map(|range| { 250 let mut msik = config.msik.map(|range| {
164 // Check MSI output per RM0456 § 11.4.10 251 // Check MSI output per RM0456 § 11.4.10
165 match config.voltage_range { 252 match config.voltage_range {
166 VoltageScale::RANGE4 => { 253 VoltageScale::RANGE4 => {
@@ -184,10 +271,44 @@ pub(crate) unsafe fn init(config: Config) {
184 RCC.cr().modify(|w| { 271 RCC.cr().modify(|w| {
185 w.set_msikon(true); 272 w.set_msikon(true);
186 }); 273 });
274 let msik = if let (Some(freq), MsiAutoCalibration::MSIK) =
275 (lse_calibration_freq, config.auto_calibration.base_mode())
276 {
277 // Enable the MSIK auto-calibration feature
278 RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK));
279 RCC.cr().modify(|w| w.set_msipllen(true));
280 calculate_calibrated_msi_frequency(range, freq)
281 } else {
282 msirange_to_hertz(range)
283 };
187 while !RCC.cr().read().msikrdy() {} 284 while !RCC.cr().read().msikrdy() {}
188 msirange_to_hertz(range) 285 msik
189 }); 286 });
190 287
288 if let Some(lse_freq) = lse_calibration_freq {
289 // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source.
290 if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) {
291 if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) {
292 // Clock source is shared, both will be auto calibrated, recalculate other frequency
293 match config.auto_calibration.base_mode() {
294 MsiAutoCalibration::MSIS => {
295 msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq));
296 }
297 MsiAutoCalibration::MSIK => {
298 msis = Some(calculate_calibrated_msi_frequency(msis_range, lse_freq));
299 }
300 _ => {}
301 }
302 }
303 }
304 // Check if Fast mode should be used
305 if config.auto_calibration.is_fast() {
306 RCC.cr().modify(|w| {
307 w.set_msipllfast(Msipllfast::FAST);
308 });
309 }
310 }
311
191 let hsi = config.hsi.then(|| { 312 let hsi = config.hsi.then(|| {
192 RCC.cr().modify(|w| w.set_hsion(true)); 313 RCC.cr().modify(|w| w.set_hsion(true));
193 while !RCC.cr().read().hsirdy() {} 314 while !RCC.cr().read().hsirdy() {}
@@ -514,3 +635,37 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput, voltag
514 635
515 PllOutput { p, q, r } 636 PllOutput { p, q, r }
516} 637}
638
639/// Fraction structure for MSI auto-calibration
640/// Represents the multiplier as numerator/denominator that LSE frequency is multiplied by
641#[derive(Debug, Clone, Copy)]
642struct MsiFraction {
643 numerator: u32,
644 denominator: u32,
645}
646
647impl MsiFraction {
648 const fn new(numerator: u32, denominator: u32) -> Self {
649 Self { numerator, denominator }
650 }
651
652 /// Calculate the calibrated frequency given an LSE frequency
653 fn calculate_frequency(&self, lse_freq: Hertz) -> Hertz {
654 Hertz(lse_freq.0 * self.numerator / self.denominator)
655 }
656}
657
658fn get_msi_calibration_fraction(range: Msirange) -> MsiFraction {
659 // Exploiting the MSIx internals to make calculations compact
660 let denominator = (range as u32 & 0x03) + 1;
661 // Base multipliers are deduced from Table 82: MSI oscillator characteristics in data sheet
662 let numerator = [1465, 122, 94, 12][range as usize >> 2];
663
664 MsiFraction::new(numerator, denominator)
665}
666
667/// Calculate the calibrated MSI frequency for a given range and LSE frequency
668fn calculate_calibrated_msi_frequency(range: Msirange, lse_freq: Hertz) -> Hertz {
669 let fraction = get_msi_calibration_fraction(range);
670 fraction.calculate_frequency(lse_freq)
671}
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index a450705a2..b00cc18ad 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -77,6 +77,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
77 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); 77 this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
78 this.inner.set_output_compare_preload(channel, true); 78 this.inner.set_output_compare_preload(channel, true);
79 }); 79 });
80 this.inner.set_autoreload_preload(true);
80 81
81 this 82 this
82 } 83 }
@@ -110,7 +111,11 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
110 /// 111 ///
111 /// This value depends on the configured frequency and the timer's clock rate from RCC. 112 /// This value depends on the configured frequency and the timer's clock rate from RCC.
112 pub fn get_max_duty(&self) -> u16 { 113 pub fn get_max_duty(&self) -> u16 {
113 self.inner.get_max_compare_value() as u16 + 1 114 if self.inner.get_counting_mode().is_center_aligned() {
115 self.inner.get_max_compare_value() as u16
116 } else {
117 self.inner.get_max_compare_value() as u16 + 1
118 }
114 } 119 }
115 120
116 /// Set the duty for a given channel. 121 /// Set the duty for a given channel.
@@ -160,7 +165,11 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<
160 } 165 }
161 166
162 fn get_max_duty(&self) -> Self::Duty { 167 fn get_max_duty(&self) -> Self::Duty {
163 self.inner.get_max_compare_value() as u16 + 1 168 if self.inner.get_counting_mode().is_center_aligned() {
169 self.inner.get_max_compare_value() as u16
170 } else {
171 self.inner.get_max_compare_value() as u16 + 1
172 }
164 } 173 }
165 174
166 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { 175 fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {