Skip to content

Commit 3291f6e

Browse files
Merge pull request #166 from kalkyl/twim_anack
Fix Twim hangs on address NACK
2 parents b53b4a2 + 906de4b commit 3291f6e

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

nrf-hal-common/src/twim.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,18 @@ 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

136141
// Stop write operation
@@ -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
}
@@ -297,23 +315,47 @@ where
297315
// full range of values that fit in a `u8`.
298316
unsafe { w.maxcnt().bits(rd_buffer.len() as _) });
299317

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

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

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

313356
self.0.events_lasttx.write(|w| w); // reset event
314357
self.0.events_lastrx.write(|w| w); // reset event
315358
self.0.events_stopped.write(|w| w); // reset event
316-
self.0.shorts.write(|w| w);
317359

318360
// Conservative compiler fence to prevent optimizations that do not
319361
// take in to account actions by DMA. The fence has been placed here,
@@ -527,6 +569,7 @@ pub enum Error {
527569
Transmit,
528570
Receive,
529571
DMABufferNotInDataMemory,
572+
AddressNack,
530573
}
531574

532575
/// Implemented by all TWIM instances

0 commit comments

Comments
 (0)