Skip to content

Commit 1c1aea6

Browse files
stm32: i2c-v2: Add error handling
Currently when error occurres, we have to wait for timeout, which is less than ideal. Enable related interrupts, and return Err when error occurres.
1 parent 712143b commit 1c1aea6

File tree

1 file changed

+60
-7
lines changed
  • embassy-stm32/src/i2c

1 file changed

+60
-7
lines changed

embassy-stm32/src/i2c/v2.rs

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ pub(crate) unsafe fn on_interrupt<T: Instance>() {
1313
let regs = T::info().regs;
1414
let isr = regs.isr().read();
1515

16-
if isr.tcr() || isr.tc() {
16+
if isr.tcr() || isr.tc() || isr.nackf() || isr.berr() || isr.arlo() || isr.ovr() {
1717
T::state().waker.wake();
1818
}
19-
// The flag can only be cleared by writting to nbytes, we won't do that here, so disable
20-
// the interrupt
2119
critical_section::with(|_| {
22-
regs.cr1().modify(|w| w.set_tcie(false));
20+
regs.cr1().modify(|w| {
21+
// The flag can only be cleared by writting to nbytes, we won't do that here
22+
w.set_tcie(false);
23+
// Error flags are to be read in the routines, so we also don't clear them here
24+
w.set_nackie(false);
25+
w.set_errie(false);
26+
});
2327
});
2428
}
2529

@@ -449,6 +453,8 @@ impl<'d> I2c<'d, Async> {
449453
if first_slice {
450454
w.set_tcie(true);
451455
}
456+
w.set_nackie(true);
457+
w.set_errie(true);
452458
});
453459
let dst = regs.txdr().as_ptr() as *mut u8;
454460

@@ -459,18 +465,41 @@ impl<'d> I2c<'d, Async> {
459465

460466
let on_drop = OnDrop::new(|| {
461467
let regs = self.info.regs;
468+
let isr = regs.isr().read();
462469
regs.cr1().modify(|w| {
463-
if last_slice {
470+
if last_slice || isr.nackf() || isr.arlo() || isr.berr() || isr.ovr() {
464471
w.set_txdmaen(false);
465472
}
466473
w.set_tcie(false);
467-
})
474+
w.set_nackie(false);
475+
w.set_errie(false);
476+
});
477+
regs.icr().write(|w| {
478+
w.set_nackcf(true);
479+
w.set_berrcf(true);
480+
w.set_arlocf(true);
481+
w.set_ovrcf(true);
482+
});
468483
});
469484

470485
poll_fn(|cx| {
471486
self.state.waker.register(cx.waker());
472487

473488
let isr = self.info.regs.isr().read();
489+
490+
if isr.nackf() {
491+
return Poll::Ready(Err(Error::Nack));
492+
}
493+
if isr.arlo() {
494+
return Poll::Ready(Err(Error::Arbitration));
495+
}
496+
if isr.berr() {
497+
return Poll::Ready(Err(Error::Bus));
498+
}
499+
if isr.ovr() {
500+
return Poll::Ready(Err(Error::Overrun));
501+
}
502+
474503
if remaining_len == total_len {
475504
if first_slice {
476505
Self::master_write(
@@ -531,6 +560,8 @@ impl<'d> I2c<'d, Async> {
531560
regs.cr1().modify(|w| {
532561
w.set_rxdmaen(true);
533562
w.set_tcie(true);
563+
w.set_nackie(true);
564+
w.set_errie(true);
534565
});
535566
let src = regs.rxdr().as_ptr() as *mut u8;
536567

@@ -544,13 +575,35 @@ impl<'d> I2c<'d, Async> {
544575
regs.cr1().modify(|w| {
545576
w.set_rxdmaen(false);
546577
w.set_tcie(false);
547-
})
578+
w.set_nackie(false);
579+
w.set_errie(false);
580+
});
581+
regs.icr().write(|w| {
582+
w.set_nackcf(true);
583+
w.set_berrcf(true);
584+
w.set_arlocf(true);
585+
w.set_ovrcf(true);
586+
});
548587
});
549588

550589
poll_fn(|cx| {
551590
self.state.waker.register(cx.waker());
552591

553592
let isr = self.info.regs.isr().read();
593+
594+
if isr.nackf() {
595+
return Poll::Ready(Err(Error::Nack));
596+
}
597+
if isr.arlo() {
598+
return Poll::Ready(Err(Error::Arbitration));
599+
}
600+
if isr.berr() {
601+
return Poll::Ready(Err(Error::Bus));
602+
}
603+
if isr.ovr() {
604+
return Poll::Ready(Err(Error::Overrun));
605+
}
606+
554607
if remaining_len == total_len {
555608
Self::master_read(
556609
self.info,

0 commit comments

Comments
 (0)