@@ -94,27 +94,17 @@ where
94
94
Twim ( twim)
95
95
}
96
96
97
- /// Write to an I2C slave.
98
- ///
99
- /// The buffer must have a length of at most 255 bytes on the nRF52832
100
- /// and at most 65535 bytes on the nRF52840.
101
- pub fn write ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
97
+ /// Set TX buffer, checking that it is in RAM and has suitable length.
98
+ unsafe fn set_tx_buffer ( & mut self , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
102
99
slice_in_ram_or ( buffer, Error :: DMABufferNotInDataMemory ) ?;
103
100
101
+ if buffer. len ( ) == 0 {
102
+ return Err ( Error :: TxBufferZeroLength ) ;
103
+ }
104
104
if buffer. len ( ) > EASY_DMA_SIZE {
105
105
return Err ( Error :: TxBufferTooLong ) ;
106
106
}
107
107
108
- // Conservative compiler fence to prevent optimizations that do not
109
- // take in to account actions by DMA. The fence has been placed here,
110
- // before any DMA action has started.
111
- compiler_fence ( SeqCst ) ;
112
-
113
- self . 0
114
- . address
115
- . write ( |w| unsafe { w. address ( ) . bits ( address) } ) ;
116
-
117
- // Set up the DMA write.
118
108
self . 0 . txd . ptr . write ( |w|
119
109
// We're giving the register a pointer to the stack. Since we're
120
110
// waiting for the I2C transaction to end before this stack pointer
@@ -132,6 +122,61 @@ where
132
122
// values.
133
123
unsafe { w. maxcnt ( ) . bits ( buffer. len ( ) as _ ) } ) ;
134
124
125
+ Ok ( ( ) )
126
+ }
127
+
128
+ /// Set RX buffer, checking that it has suitable length.
129
+ unsafe fn set_rx_buffer ( & mut self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
130
+ // NOTE: RAM slice check is not necessary, as a mutable
131
+ // slice can only be built from data located in RAM.
132
+
133
+ if buffer. len ( ) == 0 {
134
+ return Err ( Error :: RxBufferZeroLength ) ;
135
+ }
136
+ if buffer. len ( ) > EASY_DMA_SIZE {
137
+ return Err ( Error :: RxBufferTooLong ) ;
138
+ }
139
+
140
+ self . 0 . rxd . ptr . write ( |w|
141
+ // We're giving the register a pointer to the stack. Since we're
142
+ // waiting for the I2C transaction to end before this stack pointer
143
+ // becomes invalid, there's nothing wrong here.
144
+ //
145
+ // The PTR field is a full 32 bits wide and accepts the full range
146
+ // of values.
147
+ unsafe { w. ptr ( ) . bits ( buffer. as_mut_ptr ( ) as u32 ) } ) ;
148
+ self . 0 . rxd . maxcnt . write ( |w|
149
+ // We're giving it the length of the buffer, so no danger of
150
+ // accessing invalid memory. We have verified that the length of the
151
+ // buffer fits in an `u8`, so the cast to the type of maxcnt
152
+ // is also fine.
153
+ //
154
+ // Note that that nrf52840 maxcnt is a wider
155
+ // type than a u8, so we use a `_` cast rather than a `u8` cast.
156
+ // The MAXCNT field is thus at least 8 bits wide and accepts the
157
+ // full range of values that fit in a `u8`.
158
+ unsafe { w. maxcnt ( ) . bits ( buffer. len ( ) as _ ) } ) ;
159
+
160
+ Ok ( ( ) )
161
+ }
162
+
163
+ /// Write to an I2C slave.
164
+ ///
165
+ /// The buffer must have a length of at most 255 bytes on the nRF52832
166
+ /// and at most 65535 bytes on the nRF52840.
167
+ pub fn write ( & mut self , address : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
168
+ // Conservative compiler fence to prevent optimizations that do not
169
+ // take in to account actions by DMA. The fence has been placed here,
170
+ // before any DMA action has started.
171
+ compiler_fence ( SeqCst ) ;
172
+
173
+ self . 0
174
+ . address
175
+ . write ( |w| unsafe { w. address ( ) . bits ( address) } ) ;
176
+
177
+ // Set up the DMA write.
178
+ unsafe { self . set_tx_buffer ( buffer) ? } ;
179
+
135
180
// Clear address NACK.
136
181
self . 0 . errorsrc . write ( |w| w. anack ( ) . bit ( true ) ) ;
137
182
@@ -176,13 +221,6 @@ where
176
221
/// The buffer must have a length of at most 255 bytes on the nRF52832
177
222
/// and at most 65535 bytes on the nRF52840.
178
223
pub fn read ( & mut self , address : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
179
- // NOTE: RAM slice check is not necessary, as a mutable slice can only be
180
- // built from data located in RAM.
181
-
182
- if buffer. len ( ) > EASY_DMA_SIZE {
183
- return Err ( Error :: RxBufferTooLong ) ;
184
- }
185
-
186
224
// Conservative compiler fence to prevent optimizations that do not
187
225
// take in to account actions by DMA. The fence has been placed here,
188
226
// before any DMA action has started.
@@ -193,25 +231,7 @@ where
193
231
. write ( |w| unsafe { w. address ( ) . bits ( address) } ) ;
194
232
195
233
// Set up the DMA read.
196
- self . 0 . rxd . ptr . write ( |w|
197
- // We're giving the register a pointer to the stack. Since we're
198
- // waiting for the I2C transaction to end before this stack pointer
199
- // becomes invalid, there's nothing wrong here.
200
- //
201
- // The PTR field is a full 32 bits wide and accepts the full range
202
- // of values.
203
- unsafe { w. ptr ( ) . bits ( buffer. as_mut_ptr ( ) as u32 ) } ) ;
204
- self . 0 . rxd . maxcnt . write ( |w|
205
- // We're giving it the length of the buffer, so no danger of
206
- // accessing invalid memory. We have verified that the length of the
207
- // buffer fits in an `u8`, so the cast to the type of maxcnt
208
- // is also fine.
209
- //
210
- // Note that that nrf52840 maxcnt is a wider
211
- // type than a u8, so we use a `_` cast rather than a `u8` cast.
212
- // The MAXCNT field is thus at least 8 bits wide and accepts the
213
- // full range of values that fit in a `u8`.
214
- unsafe { w. maxcnt ( ) . bits ( buffer. len ( ) as _ ) } ) ;
234
+ unsafe { self . set_rx_buffer ( buffer) ? } ;
215
235
216
236
// Clear address NACK.
217
237
self . 0 . errorsrc . write ( |w| w. anack ( ) . bit ( true ) ) ;
@@ -263,18 +283,6 @@ where
263
283
wr_buffer : & [ u8 ] ,
264
284
rd_buffer : & mut [ u8 ] ,
265
285
) -> Result < ( ) , Error > {
266
- // NOTE: RAM slice check for `rd_buffer` is not necessary, as a mutable
267
- // slice can only be built from data located in RAM.
268
- slice_in_ram_or ( wr_buffer, Error :: DMABufferNotInDataMemory ) ?;
269
-
270
- if wr_buffer. len ( ) > EASY_DMA_SIZE {
271
- return Err ( Error :: TxBufferTooLong ) ;
272
- }
273
-
274
- if rd_buffer. len ( ) > EASY_DMA_SIZE {
275
- return Err ( Error :: RxBufferTooLong ) ;
276
- }
277
-
278
286
// Conservative compiler fence to prevent optimizations that do not
279
287
// take in to account actions by DMA. The fence has been placed here,
280
288
// before any DMA action has started.
@@ -284,44 +292,11 @@ where
284
292
. address
285
293
. write ( |w| unsafe { w. address ( ) . bits ( address) } ) ;
286
294
287
- // Set up the DMA write.
288
- self . 0 . txd . ptr . write ( |w|
289
- // We're giving the register a pointer to the stack. Since we're
290
- // waiting for the I2C transaction to end before this stack pointer
291
- // becomes invalid, there's nothing wrong here.
292
- //
293
- // The PTR field is a full 32 bits wide and accepts the full range
294
- // of values.
295
- unsafe { w. ptr ( ) . bits ( wr_buffer. as_ptr ( ) as u32 ) } ) ;
296
- self . 0 . txd . maxcnt . write ( |w|
297
- // We're giving it the length of the buffer, so no danger of
298
- // accessing invalid memory. We have verified that the length of the
299
- // buffer fits in an `u8`, so the cast to `u8` is also fine.
300
- //
301
- // The MAXCNT field is 8 bits wide and accepts the full range of
302
- // values.
303
- unsafe { w. maxcnt ( ) . bits ( wr_buffer. len ( ) as _ ) } ) ;
304
-
305
- // Set up the DMA read.
306
- self . 0 . rxd . ptr . write ( |w|
307
- // We're giving the register a pointer to the stack. Since we're
308
- // waiting for the I2C transaction to end before this stack pointer
309
- // becomes invalid, there's nothing wrong here.
310
- //
311
- // The PTR field is a full 32 bits wide and accepts the full range
312
- // of values.
313
- unsafe { w. ptr ( ) . bits ( rd_buffer. as_mut_ptr ( ) as u32 ) } ) ;
314
- self . 0 . rxd . maxcnt . write ( |w|
315
- // We're giving it the length of the buffer, so no danger of
316
- // accessing invalid memory. We have verified that the length of the
317
- // buffer fits in an `u8`, so the cast to the type of maxcnt
318
- // is also fine.
319
- //
320
- // Note that that nrf52840 maxcnt is a wider
321
- // type than a u8, so we use a `_` cast rather than a `u8` cast.
322
- // The MAXCNT field is thus at least 8 bits wide and accepts the
323
- // full range of values that fit in a `u8`.
324
- unsafe { w. maxcnt ( ) . bits ( rd_buffer. len ( ) as _ ) } ) ;
295
+ // Set up DMA buffers.
296
+ unsafe {
297
+ self . set_tx_buffer ( wr_buffer) ?;
298
+ self . set_rx_buffer ( rd_buffer) ?;
299
+ }
325
300
326
301
// Clear address NACK.
327
302
self . 0 . errorsrc . write ( |w| w. anack ( ) . bit ( true ) ) ;
@@ -395,10 +370,6 @@ where
395
370
tx_buffer : & [ u8 ] ,
396
371
rx_buffer : & mut [ u8 ] ,
397
372
) -> Result < ( ) , Error > {
398
- if rx_buffer. len ( ) > EASY_DMA_SIZE {
399
- return Err ( Error :: RxBufferTooLong ) ;
400
- }
401
-
402
373
// Conservative compiler fence to prevent optimizations that do not
403
374
// take in to account actions by DMA. The fence has been placed here,
404
375
// before any DMA action has started.
@@ -409,25 +380,7 @@ where
409
380
. write ( |w| unsafe { w. address ( ) . bits ( address) } ) ;
410
381
411
382
// Set up the DMA read.
412
- self . 0 . rxd . ptr . write ( |w|
413
- // We're giving the register a pointer to the stack. Since we're
414
- // waiting for the I2C transaction to end before this stack pointer
415
- // becomes invalid, there's nothing wrong here.
416
- //
417
- // The PTR field is a full 32 bits wide and accepts the full range
418
- // of values.
419
- unsafe { w. ptr ( ) . bits ( rx_buffer. as_mut_ptr ( ) as u32 ) } ) ;
420
- self . 0 . rxd . maxcnt . write ( |w|
421
- // We're giving it the length of the buffer, so no danger of
422
- // accessing invalid memory. We have verified that the length of the
423
- // buffer fits in an `u8`, so the cast to the type of maxcnt
424
- // is also fine.
425
- //
426
- // Note that that nrf52840 maxcnt is a wider
427
- // type than a u8, so we use a `_` cast rather than a `u8` cast.
428
- // The MAXCNT field is thus at least 8 bits wide and accepts the
429
- // full range of values that fit in a `u8`.
430
- unsafe { w. maxcnt ( ) . bits ( rx_buffer. len ( ) as _ ) } ) ;
383
+ unsafe { self . set_rx_buffer ( rx_buffer) ? } ;
431
384
432
385
// Chunk write data.
433
386
let wr_buffer = & mut [ 0 ; FORCE_COPY_BUFFER_SIZE ] [ ..] ;
@@ -436,23 +389,7 @@ where
436
389
wr_buffer[ ..chunk. len ( ) ] . copy_from_slice ( chunk) ;
437
390
438
391
// Set up the DMA write.
439
- self . 0 . txd . ptr . write ( |w|
440
- // We're giving the register a pointer to the stack. Since we're
441
- // waiting for the I2C transaction to end before this stack pointer
442
- // becomes invalid, there's nothing wrong here.
443
- //
444
- // The PTR field is a full 32 bits wide and accepts the full range
445
- // of values.
446
- unsafe { w. ptr ( ) . bits ( wr_buffer. as_ptr ( ) as u32 ) } ) ;
447
-
448
- self . 0 . txd . maxcnt . write ( |w|
449
- // We're giving it the length of the buffer, so no danger of
450
- // accessing invalid memory. We have verified that the length of the
451
- // buffer fits in an `u8`, so the cast to `u8` is also fine.
452
- //
453
- // The MAXCNT field is 8 bits wide and accepts the full range of
454
- // values.
455
- unsafe { w. maxcnt ( ) . bits ( wr_buffer. len ( ) as _ ) } ) ;
392
+ unsafe { self . set_tx_buffer ( wr_buffer) ? } ;
456
393
457
394
// Start write operation.
458
395
self . 0 . tasks_starttx . write ( |w|
@@ -572,6 +509,8 @@ pub struct Pins {
572
509
pub enum Error {
573
510
TxBufferTooLong ,
574
511
RxBufferTooLong ,
512
+ TxBufferZeroLength ,
513
+ RxBufferZeroLength ,
575
514
Transmit ,
576
515
Receive ,
577
516
DMABufferNotInDataMemory ,
0 commit comments