aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-16 11:41:59 +0000
committerGitHub <[email protected]>2024-04-16 11:41:59 +0000
commitca139b9177aeb4ddb7ec54493d0fd62723edfba3 (patch)
treeb236965284f968a8973649f25b447f43a0e1faca
parente38f1011d6234fbc51fbbbb2d93365517705e3ac (diff)
parent2315a39293488488ced2369a1d23629af57cc0fb (diff)
Merge pull request #2823 from jamesmunns/james/usb-otg-errata
Add critical sections to avoid USB OTG Errata
-rw-r--r--embassy-stm32/src/usb/otg.rs106
1 files changed, 58 insertions, 48 deletions
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index cabc06367..b386c6977 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -672,45 +672,51 @@ impl<'d, T: Instance> Bus<'d, T> {
672 672
673 let r = T::regs(); 673 let r = T::regs();
674 674
675 // Configure RX fifo size. All endpoints share the same FIFO area. 675 // ERRATA NOTE: Don't interrupt FIFOs being written to. The interrupt
676 let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out); 676 // handler COULD interrupt us here and do FIFO operations, so ensure
677 trace!("configuring rx fifo size={}", rx_fifo_size_words); 677 // the interrupt does not occur.
678 678 critical_section::with(|_| {
679 r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words)); 679 // Configure RX fifo size. All endpoints share the same FIFO area.
680 680 let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
681 // Configure TX (USB in direction) fifo size for each endpoint 681 trace!("configuring rx fifo size={}", rx_fifo_size_words);
682 let mut fifo_top = rx_fifo_size_words; 682
683 for i in 0..T::ENDPOINT_COUNT { 683 r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
684 if let Some(ep) = self.ep_in[i] { 684
685 trace!( 685 // Configure TX (USB in direction) fifo size for each endpoint
686 "configuring tx fifo ep={}, offset={}, size={}", 686 let mut fifo_top = rx_fifo_size_words;
687 i, 687 for i in 0..T::ENDPOINT_COUNT {
688 fifo_top, 688 if let Some(ep) = self.ep_in[i] {
689 ep.fifo_size_words 689 trace!(
690 ); 690 "configuring tx fifo ep={}, offset={}, size={}",
691 691 i,
692 let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) }; 692 fifo_top,
693 693 ep.fifo_size_words
694 dieptxf.write(|w| { 694 );
695 w.set_fd(ep.fifo_size_words); 695
696 w.set_sa(fifo_top); 696 let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
697 }); 697
698 dieptxf.write(|w| {
699 w.set_fd(ep.fifo_size_words);
700 w.set_sa(fifo_top);
701 });
698 702
699 fifo_top += ep.fifo_size_words; 703 fifo_top += ep.fifo_size_words;
704 }
700 } 705 }
701 }
702 706
703 assert!( 707 assert!(
704 fifo_top <= T::FIFO_DEPTH_WORDS, 708 fifo_top <= T::FIFO_DEPTH_WORDS,
705 "FIFO allocations exceeded maximum capacity" 709 "FIFO allocations exceeded maximum capacity"
706 ); 710 );
707 711
708 // Flush fifos 712 // Flush fifos
709 r.grstctl().write(|w| { 713 r.grstctl().write(|w| {
710 w.set_rxfflsh(true); 714 w.set_rxfflsh(true);
711 w.set_txfflsh(true); 715 w.set_txfflsh(true);
712 w.set_txfnum(0x10); 716 w.set_txfnum(0x10);
717 });
713 }); 718 });
719
714 loop { 720 loop {
715 let x = r.grstctl().read(); 721 let x = r.grstctl().read();
716 if !x.rxfflsh() && !x.txfflsh() { 722 if !x.rxfflsh() && !x.txfflsh() {
@@ -1208,27 +1214,31 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
1208 .await 1214 .await
1209 } 1215 }
1210 1216
1211 // Setup transfer size 1217 // ERRATA: Transmit data FIFO is corrupted when a write sequence to the FIFO is interrupted with
1212 r.dieptsiz(index).write(|w| { 1218 // accesses to certain OTG_FS registers.
1213 w.set_mcnt(1); 1219 //
1214 w.set_pktcnt(1); 1220 // Prevent the interrupt (which might poke FIFOs) from executing while copying data to FIFOs.
1215 w.set_xfrsiz(buf.len() as _);
1216 });
1217
1218 critical_section::with(|_| { 1221 critical_section::with(|_| {
1222 // Setup transfer size
1223 r.dieptsiz(index).write(|w| {
1224 w.set_mcnt(1);
1225 w.set_pktcnt(1);
1226 w.set_xfrsiz(buf.len() as _);
1227 });
1228
1219 // Enable endpoint 1229 // Enable endpoint
1220 r.diepctl(index).modify(|w| { 1230 r.diepctl(index).modify(|w| {
1221 w.set_cnak(true); 1231 w.set_cnak(true);
1222 w.set_epena(true); 1232 w.set_epena(true);
1223 }); 1233 });
1224 });
1225 1234
1226 // Write data to FIFO 1235 // Write data to FIFO
1227 for chunk in buf.chunks(4) { 1236 for chunk in buf.chunks(4) {
1228 let mut tmp = [0u8; 4]; 1237 let mut tmp = [0u8; 4];
1229 tmp[0..chunk.len()].copy_from_slice(chunk); 1238 tmp[0..chunk.len()].copy_from_slice(chunk);
1230 r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp))); 1239 r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp)));
1231 } 1240 }
1241 });
1232 1242
1233 trace!("write done ep={:?}", self.info.addr); 1243 trace!("write done ep={:?}", self.info.addr);
1234 1244