Merge pull request #2823 from jamesmunns/james/usb-otg-errata
Add critical sections to avoid USB OTG Errata
This commit is contained in:
commit
ca139b9177
1 changed files with 54 additions and 44 deletions
|
@ -672,45 +672,51 @@ impl<'d, T: Instance> Bus<'d, T> {
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// Configure RX fifo size. All endpoints share the same FIFO area.
|
// ERRATA NOTE: Don't interrupt FIFOs being written to. The interrupt
|
||||||
let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
|
// handler COULD interrupt us here and do FIFO operations, so ensure
|
||||||
trace!("configuring rx fifo size={}", rx_fifo_size_words);
|
// the interrupt does not occur.
|
||||||
|
critical_section::with(|_| {
|
||||||
|
// Configure RX fifo size. All endpoints share the same FIFO area.
|
||||||
|
let rx_fifo_size_words = RX_FIFO_EXTRA_SIZE_WORDS + ep_fifo_size(&self.ep_out);
|
||||||
|
trace!("configuring rx fifo size={}", rx_fifo_size_words);
|
||||||
|
|
||||||
r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
|
r.grxfsiz().modify(|w| w.set_rxfd(rx_fifo_size_words));
|
||||||
|
|
||||||
// Configure TX (USB in direction) fifo size for each endpoint
|
// Configure TX (USB in direction) fifo size for each endpoint
|
||||||
let mut fifo_top = rx_fifo_size_words;
|
let mut fifo_top = rx_fifo_size_words;
|
||||||
for i in 0..T::ENDPOINT_COUNT {
|
for i in 0..T::ENDPOINT_COUNT {
|
||||||
if let Some(ep) = self.ep_in[i] {
|
if let Some(ep) = self.ep_in[i] {
|
||||||
trace!(
|
trace!(
|
||||||
"configuring tx fifo ep={}, offset={}, size={}",
|
"configuring tx fifo ep={}, offset={}, size={}",
|
||||||
i,
|
i,
|
||||||
fifo_top,
|
fifo_top,
|
||||||
ep.fifo_size_words
|
ep.fifo_size_words
|
||||||
);
|
);
|
||||||
|
|
||||||
let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
|
let dieptxf = if i == 0 { r.dieptxf0() } else { r.dieptxf(i - 1) };
|
||||||
|
|
||||||
dieptxf.write(|w| {
|
dieptxf.write(|w| {
|
||||||
w.set_fd(ep.fifo_size_words);
|
w.set_fd(ep.fifo_size_words);
|
||||||
w.set_sa(fifo_top);
|
w.set_sa(fifo_top);
|
||||||
});
|
});
|
||||||
|
|
||||||
fifo_top += ep.fifo_size_words;
|
fifo_top += ep.fifo_size_words;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
fifo_top <= T::FIFO_DEPTH_WORDS,
|
fifo_top <= T::FIFO_DEPTH_WORDS,
|
||||||
"FIFO allocations exceeded maximum capacity"
|
"FIFO allocations exceeded maximum capacity"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Flush fifos
|
// Flush fifos
|
||||||
r.grstctl().write(|w| {
|
r.grstctl().write(|w| {
|
||||||
w.set_rxfflsh(true);
|
w.set_rxfflsh(true);
|
||||||
w.set_txfflsh(true);
|
w.set_txfflsh(true);
|
||||||
w.set_txfnum(0x10);
|
w.set_txfnum(0x10);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let x = r.grstctl().read();
|
let x = r.grstctl().read();
|
||||||
if !x.rxfflsh() && !x.txfflsh() {
|
if !x.rxfflsh() && !x.txfflsh() {
|
||||||
|
@ -1208,27 +1214,31 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup transfer size
|
// ERRATA: Transmit data FIFO is corrupted when a write sequence to the FIFO is interrupted with
|
||||||
r.dieptsiz(index).write(|w| {
|
// accesses to certain OTG_FS registers.
|
||||||
w.set_mcnt(1);
|
//
|
||||||
w.set_pktcnt(1);
|
// Prevent the interrupt (which might poke FIFOs) from executing while copying data to FIFOs.
|
||||||
w.set_xfrsiz(buf.len() as _);
|
|
||||||
});
|
|
||||||
|
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
|
// Setup transfer size
|
||||||
|
r.dieptsiz(index).write(|w| {
|
||||||
|
w.set_mcnt(1);
|
||||||
|
w.set_pktcnt(1);
|
||||||
|
w.set_xfrsiz(buf.len() as _);
|
||||||
|
});
|
||||||
|
|
||||||
// Enable endpoint
|
// Enable endpoint
|
||||||
r.diepctl(index).modify(|w| {
|
r.diepctl(index).modify(|w| {
|
||||||
w.set_cnak(true);
|
w.set_cnak(true);
|
||||||
w.set_epena(true);
|
w.set_epena(true);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Write data to FIFO
|
// Write data to FIFO
|
||||||
for chunk in buf.chunks(4) {
|
for chunk in buf.chunks(4) {
|
||||||
let mut tmp = [0u8; 4];
|
let mut tmp = [0u8; 4];
|
||||||
tmp[0..chunk.len()].copy_from_slice(chunk);
|
tmp[0..chunk.len()].copy_from_slice(chunk);
|
||||||
r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp)));
|
r.fifo(index).write_value(regs::Fifo(u32::from_ne_bytes(tmp)));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
trace!("write done ep={:?}", self.info.addr);
|
trace!("write done ep={:?}", self.info.addr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue