aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Kröger <[email protected]>2024-03-08 15:01:55 +0100
committerTimo Kröger <[email protected]>2024-03-12 08:14:42 +0100
commitc1efcbba2dc472948b294b474a9a1970f88cd96a (patch)
tree6f5c15bf84a47fa13f2ed95f0d23534834e86aaa
parentb7972048a1642679392b2a1dfc976881205fd23b (diff)
[UCPD] Receive hard resets
-rw-r--r--embassy-stm32/src/ucpd.rs42
1 files changed, 35 insertions, 7 deletions
diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs
index 071bfd1b1..64969beb8 100644
--- a/embassy-stm32/src/ucpd.rs
+++ b/embassy-stm32/src/ucpd.rs
@@ -181,8 +181,8 @@ impl<'d, T: Instance> Ucpd<'d, T> {
181 r.tx_ordsetr().write(|w| w.set_txordset(0b10001_11000_11000_11000)); 181 r.tx_ordsetr().write(|w| w.set_txordset(0b10001_11000_11000_11000));
182 182
183 r.cfgr1().modify(|w| { 183 r.cfgr1().modify(|w| {
184 // TODO: Currently only SOP messages are supported. 184 // TODO: Currently only hard reset and SOP messages can be received.
185 w.set_rxordseten(0x1); 185 w.set_rxordseten(0b1001);
186 186
187 // Enable DMA 187 // Enable DMA
188 w.set_txdmaen(true); 188 w.set_txdmaen(true);
@@ -195,6 +195,9 @@ impl<'d, T: Instance> Ucpd<'d, T> {
195 w.set_phyrxen(true); 195 w.set_phyrxen(true);
196 }); 196 });
197 197
198 // Enable hard reset receive interrupt.
199 r.imr().modify(|w| w.set_rxhrstdetie(true));
200
198 into_ref!(rx_dma, tx_dma); 201 into_ref!(rx_dma, tx_dma);
199 let rx_dma_req = rx_dma.request(); 202 let rx_dma_req = rx_dma.request();
200 let tx_dma_req = tx_dma.request(); 203 let tx_dma_req = tx_dma.request();
@@ -217,6 +220,9 @@ pub enum RxError {
217 220
218 /// Provided buffer was too small for the received message. 221 /// Provided buffer was too small for the received message.
219 Overrun, 222 Overrun,
223
224 /// Hard Reset received before or during reception.
225 HardReset,
220} 226}
221 227
222/// Transmit Error. 228/// Transmit Error.
@@ -225,6 +231,9 @@ pub enum RxError {
225pub enum TxError { 231pub enum TxError {
226 /// Concurrent receive in progress or excessive noise on the line. 232 /// Concurrent receive in progress or excessive noise on the line.
227 Discarded, 233 Discarded,
234
235 /// Hard Reset received before or during transmission.
236 HardReset,
228} 237}
229 238
230/// Power Delivery (PD) PHY. 239/// Power Delivery (PD) PHY.
@@ -252,7 +261,9 @@ impl<'d, T: Instance> PdPhy<'d, T> {
252 // Check if a message is already being received. If yes, wait until its 261 // Check if a message is already being received. If yes, wait until its
253 // done, ignore errors and try to receive the next message. 262 // done, ignore errors and try to receive the next message.
254 if r.sr().read().rxorddet() { 263 if r.sr().read().rxorddet() {
255 let _ = self.wait_rx_done().await; 264 if let Err(RxError::HardReset) = self.wait_rx_done().await {
265 return Err(RxError::HardReset);
266 }
256 r.rxdr().read(); // Clear the RX buffer. 267 r.rxdr().read(); // Clear the RX buffer.
257 } 268 }
258 269
@@ -290,7 +301,12 @@ impl<'d, T: Instance> PdPhy<'d, T> {
290 poll_fn(|cx| { 301 poll_fn(|cx| {
291 let r = T::REGS; 302 let r = T::REGS;
292 let sr = r.sr().read(); 303 let sr = r.sr().read();
293 if sr.rxmsgend() { 304 if sr.rxhrstdet() {
305 // Clean and re-enable hard reset receive interrupt.
306 r.icr().write(|w| w.set_rxhrstdetcf(true));
307 r.imr().modify(|w| w.set_rxhrstdetie(true));
308 Poll::Ready(Err(RxError::HardReset))
309 } else if sr.rxmsgend() {
294 let ret = if sr.rxovr() { 310 let ret = if sr.rxovr() {
295 Err(RxError::Overrun) 311 Err(RxError::Overrun)
296 } else if sr.rxerr() { 312 } else if sr.rxerr() {
@@ -326,7 +342,9 @@ impl<'d, T: Instance> PdPhy<'d, T> {
326 // might still be running because there is no way to abort an ongoing 342 // might still be running because there is no way to abort an ongoing
327 // message transmission. Wait for it to finish but ignore errors. 343 // message transmission. Wait for it to finish but ignore errors.
328 if r.cr().read().txsend() { 344 if r.cr().read().txsend() {
329 let _ = self.wait_tx_done().await; 345 if let Err(TxError::HardReset) = self.wait_tx_done().await {
346 return Err(TxError::HardReset);
347 }
330 } 348 }
331 349
332 // Clear the TX interrupt flags. 350 // Clear the TX interrupt flags.
@@ -360,9 +378,15 @@ impl<'d, T: Instance> PdPhy<'d, T> {
360 let _on_drop = OnDrop::new(|| self.enable_tx_interrupts(false)); 378 let _on_drop = OnDrop::new(|| self.enable_tx_interrupts(false));
361 poll_fn(|cx| { 379 poll_fn(|cx| {
362 let r = T::REGS; 380 let r = T::REGS;
363 if r.sr().read().txmsgdisc() { 381 let sr = r.sr().read();
382 if sr.rxhrstdet() {
383 // Clean and re-enable hard reset receive interrupt.
384 r.icr().write(|w| w.set_rxhrstdetcf(true));
385 r.imr().modify(|w| w.set_rxhrstdetie(true));
386 Poll::Ready(Err(TxError::HardReset))
387 } else if sr.txmsgdisc() {
364 Poll::Ready(Err(TxError::Discarded)) 388 Poll::Ready(Err(TxError::Discarded))
365 } else if r.sr().read().txmsgsent() { 389 } else if sr.txmsgsent() {
366 Poll::Ready(Ok(())) 390 Poll::Ready(Ok(()))
367 } else { 391 } else {
368 T::waker().register(cx.waker()); 392 T::waker().register(cx.waker());
@@ -398,6 +422,10 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
398 }); 422 });
399 } 423 }
400 424
425 if sr.rxhrstdet() {
426 r.imr().modify(|w| w.set_rxhrstdetie(false));
427 }
428
401 if sr.rxmsgend() { 429 if sr.rxmsgend() {
402 r.imr().modify(|w| w.set_rxmsgendie(false)); 430 r.imr().modify(|w| w.set_rxmsgendie(false));
403 } 431 }