Skip to content

Commit 906de4b

Browse files
author
Henrik Alsér
committed
Fix Twim hangs on address NACK
1 parent bc4f549 commit 906de4b

File tree

1 file changed

+53
-10
lines changed

1 file changed

+53
-10
lines changed

nrf-hal-common/src/twim.rs

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,21 @@ where
124124
// values.
125125
unsafe { w.maxcnt().bits(buffer.len() as _) });
126126

127+
// Clear address NACK
128+
self.0.errorsrc.write(|w| w.anack().bit(true));
129+
127130
// Start write operation
128131
self.0.tasks_starttx.write(|w|
129132
// `1` is a valid value to write to task registers.
130133
unsafe { w.bits(1) });
131134

132135
// Wait until write operation is about to end
133-
while self.0.events_lasttx.read().bits() == 0 {}
136+
while self.0.events_lasttx.read().bits() == 0
137+
&& self.0.errorsrc.read().anack().is_not_received()
138+
{}
134139
self.0.events_lasttx.write(|w| w); // reset event
135140

136-
// Stop read operation
141+
// Stop write operation
137142
self.0.tasks_stop.write(|w|
138143
// `1` is a valid value to write to task registers.
139144
unsafe { w.bits(1) });
@@ -147,6 +152,10 @@ where
147152
// after all possible DMA actions have completed
148153
compiler_fence(SeqCst);
149154

155+
if self.0.errorsrc.read().anack().is_received() {
156+
return Err(Error::AddressNack);
157+
}
158+
150159
if self.0.txd.amount.read().bits() != buffer.len() as u32 {
151160
return Err(Error::Transmit);
152161
}
@@ -196,13 +205,18 @@ where
196205
// full range of values that fit in a `u8`.
197206
unsafe { w.maxcnt().bits(buffer.len() as _) });
198207

208+
// Clear address NACK
209+
self.0.errorsrc.write(|w| w.anack().bit(true));
210+
199211
// Start read operation
200212
self.0.tasks_startrx.write(|w|
201213
// `1` is a valid value to write to task registers.
202214
unsafe { w.bits(1) });
203215

204216
// Wait until read operation is about to end
205-
while self.0.events_lastrx.read().bits() == 0 {}
217+
while self.0.events_lastrx.read().bits() == 0
218+
&& self.0.errorsrc.read().anack().is_not_received()
219+
{}
206220
self.0.events_lastrx.write(|w| w); // reset event
207221

208222
// Stop read operation
@@ -219,6 +233,10 @@ where
219233
// after all possible DMA actions have completed
220234
compiler_fence(SeqCst);
221235

236+
if self.0.errorsrc.read().anack().is_received() {
237+
return Err(Error::AddressNack);
238+
}
239+
222240
if self.0.rxd.amount.read().bits() != buffer.len() as u32 {
223241
return Err(Error::Receive);
224242
}
@@ -296,23 +314,47 @@ where
296314
// full range of values that fit in a `u8`.
297315
unsafe { w.maxcnt().bits(rd_buffer.len() as _) });
298316

299-
// Immediately start RX after TX, then stop
300-
self.0
301-
.shorts
302-
.modify(|_r, w| w.lasttx_startrx().enabled().lastrx_stop().enabled());
317+
// Clear address NACK
318+
self.0.errorsrc.write(|w| w.anack().bit(true));
303319

304320
// Start write operation
305-
self.0.tasks_starttx.write(|w|
321+
// `1` is a valid value to write to task registers.
322+
self.0.tasks_starttx.write(|w| unsafe { w.bits(1) });
323+
324+
// Wait until write operation is about to end
325+
while self.0.events_lasttx.read().bits() == 0
326+
&& self.0.errorsrc.read().anack().is_not_received()
327+
{}
328+
self.0.events_lasttx.write(|w| w); // reset event
329+
330+
// Stop operation if address is NACK
331+
if self.0.errorsrc.read().anack().is_received() {
306332
// `1` is a valid value to write to task registers.
307-
unsafe { w.bits(1) });
333+
self.0.tasks_stop.write(|w| unsafe { w.bits(1) });
334+
// Wait until operation is stopped
335+
while self.0.events_stopped.read().bits() == 0 {}
336+
self.0.events_stopped.write(|w| w); // reset event
337+
return Err(Error::AddressNack);
338+
}
339+
340+
// Start read operation
341+
// `1` is a valid value to write to task registers.
342+
self.0.tasks_startrx.write(|w| unsafe { w.bits(1) });
343+
344+
// Wait until read operation is about to end
345+
while self.0.events_lastrx.read().bits() == 0 {}
346+
self.0.events_lastrx.write(|w| w); // reset event
347+
348+
// Stop read operation
349+
// `1` is a valid value to write to task registers.
350+
self.0.tasks_stop.write(|w| unsafe { w.bits(1) });
308351

309352
// Wait until total operation has ended
310353
while self.0.events_stopped.read().bits() == 0 {}
311354

312355
self.0.events_lasttx.write(|w| w); // reset event
313356
self.0.events_lastrx.write(|w| w); // reset event
314357
self.0.events_stopped.write(|w| w); // reset event
315-
self.0.shorts.write(|w| w);
316358

317359
// Conservative compiler fence to prevent optimizations that do not
318360
// take in to account actions by DMA. The fence has been placed here,
@@ -397,6 +439,7 @@ pub enum Error {
397439
Transmit,
398440
Receive,
399441
DMABufferNotInDataMemory,
442+
AddressNack,
400443
}
401444

402445
/// Implemented by all TWIM instances

0 commit comments

Comments
 (0)