Skip to content

Commit 1780f84

Browse files
authored
Merge pull request embassy-rs#3878 from showier-drastic/i2c-v2-add-nack
stm32: i2c-v2: Add error handling
2 parents 1fa874e + 1c1aea6 commit 1780f84

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

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

@@ -460,18 +466,41 @@ impl<'d> I2c<'d, Async> {
460466

461467
let on_drop = OnDrop::new(|| {
462468
let regs = self.info.regs;
469+
let isr = regs.isr().read();
463470
regs.cr1().modify(|w| {
464-
if last_slice {
471+
if last_slice || isr.nackf() || isr.arlo() || isr.berr() || isr.ovr() {
465472
w.set_txdmaen(false);
466473
}
467474
w.set_tcie(false);
468-
})
475+
w.set_nackie(false);
476+
w.set_errie(false);
477+
});
478+
regs.icr().write(|w| {
479+
w.set_nackcf(true);
480+
w.set_berrcf(true);
481+
w.set_arlocf(true);
482+
w.set_ovrcf(true);
483+
});
469484
});
470485

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

474489
let isr = self.info.regs.isr().read();
490+
491+
if isr.nackf() {
492+
return Poll::Ready(Err(Error::Nack));
493+
}
494+
if isr.arlo() {
495+
return Poll::Ready(Err(Error::Arbitration));
496+
}
497+
if isr.berr() {
498+
return Poll::Ready(Err(Error::Bus));
499+
}
500+
if isr.ovr() {
501+
return Poll::Ready(Err(Error::Overrun));
502+
}
503+
475504
if remaining_len == total_len {
476505
if first_slice {
477506
Self::master_write(
@@ -534,6 +563,8 @@ impl<'d> I2c<'d, Async> {
534563
regs.cr1().modify(|w| {
535564
w.set_rxdmaen(true);
536565
w.set_tcie(true);
566+
w.set_nackie(true);
567+
w.set_errie(true);
537568
});
538569
let src = regs.rxdr().as_ptr() as *mut u8;
539570

@@ -547,13 +578,35 @@ impl<'d> I2c<'d, Async> {
547578
regs.cr1().modify(|w| {
548579
w.set_rxdmaen(false);
549580
w.set_tcie(false);
550-
})
581+
w.set_nackie(false);
582+
w.set_errie(false);
583+
});
584+
regs.icr().write(|w| {
585+
w.set_nackcf(true);
586+
w.set_berrcf(true);
587+
w.set_arlocf(true);
588+
w.set_ovrcf(true);
589+
});
551590
});
552591

553592
poll_fn(|cx| {
554593
self.state.waker.register(cx.waker());
555594

556595
let isr = self.info.regs.isr().read();
596+
597+
if isr.nackf() {
598+
return Poll::Ready(Err(Error::Nack));
599+
}
600+
if isr.arlo() {
601+
return Poll::Ready(Err(Error::Arbitration));
602+
}
603+
if isr.berr() {
604+
return Poll::Ready(Err(Error::Bus));
605+
}
606+
if isr.ovr() {
607+
return Poll::Ready(Err(Error::Overrun));
608+
}
609+
557610
if remaining_len == total_len {
558611
Self::master_read(
559612
self.info,

0 commit comments

Comments
 (0)