@@ -236,7 +236,7 @@ macro_rules! spi {
236
236
} )
237
237
}
238
238
#[ inline]
239
- fn nb_read_no_err( & mut self ) -> nb:: Result <u8 , ( ) > {
239
+ fn nb_read_no_err< W : FrameSize > ( & mut self ) -> nb:: Result <W , ( ) > {
240
240
if self . spi. sr. read( ) . rxne( ) . bit_is_set( ) {
241
241
Ok ( self . read_unchecked( ) )
242
242
} else {
@@ -295,20 +295,35 @@ macro_rules! spi {
295
295
fn read( & mut self , words: & mut [ u8 ] ) -> Result <( ) , Self :: Error > {
296
296
if words. len( ) == 0 { return Ok ( ( ) ) }
297
297
298
+ // FIFO threshold to 16 bits
299
+ self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
300
+
298
301
// prefill write fifo so that the clock doen't stop while fetch the read byte
299
- let prefill = self . fifo_cap( ) as usize ;
302
+ let prefill = self . fifo_cap( ) as usize / 2 ;
300
303
for _ in 0 ..prefill {
301
- nb:: block!( self . nb_write( 0u8 ) ) ?;
304
+ nb:: block!( self . nb_write( 0u16 ) ) ?;
302
305
}
303
306
304
307
let len = words. len( ) ;
305
- for r in words[ ..len-prefill] . iter_mut( ) {
306
- // TODO: 16 bit frames, bidirectional pins
308
+ let half_len = len / 2 ;
309
+ let pair_left = len % 2 ;
310
+
311
+ for r in words. chunks_exact_mut( 2 ) . take( half_len-prefill) {
312
+ nb:: block!( self . nb_write( 0u16 ) ) ?;
313
+ let r_two: u16 = unsafe {
314
+ nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( )
315
+ } ;
316
+ // safety: chunks have exact length of 2
317
+ unsafe { * r. as_mut_ptr( ) . cast( ) = r_two. to_le_bytes( ) ; }
318
+ }
319
+
320
+ // FIFO threshold to 8 bits
321
+ self . spi. cr2. modify( |_, w| w. frxth( ) . set_bit( ) ) ;
322
+ if pair_left == 1 {
307
323
nb:: block!( self . nb_write( 0u8 ) ) ?;
308
- // errors have been checked by the write above
309
- * r = unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ;
310
324
}
311
- Ok ( for r in words[ len-prefill..] . iter_mut( ) {
325
+
326
+ Ok ( for r in words[ len - prefill - pair_left..] . iter_mut( ) {
312
327
* r = nb:: block!( self . nb_read( ) ) ?;
313
328
} )
314
329
}
@@ -331,26 +346,50 @@ macro_rules! spi {
331
346
return self . read( read)
332
347
}
333
348
334
- let prefill = self . fifo_cap( ) ;
335
- let mut write_iter = write. into_iter( ) ;
349
+ let common_len = core:: cmp:: min( read. len( ) , write. len( ) ) ;
350
+ let half_len = common_len / 2 ;
351
+ let pair_left = common_len % 2 ;
352
+
353
+ // write two bytes at once
354
+ let prefill = self . fifo_cap( ) / 2 ;
355
+ let mut write_iter = write. chunks_exact( 2 ) . map( |two|
356
+ // safety: chunks_exact guarantees that chunks have 2 elements
357
+ // second byte in send queue goes to the top of the 16-bit data register for
358
+ // packing
359
+ u16 :: from_le_bytes( unsafe { * two. as_ptr( ) . cast( ) } )
360
+ ) ;
336
361
337
362
// same prefill as in read, this time with actual data
338
363
let mut prefilled = 0 ;
339
364
for b in write_iter. by_ref( ) . take( prefill as usize ) {
340
- nb:: block!( self . nb_write( * b) ) ?;
341
- prefilled += 1
365
+ nb:: block!( self . nb_write( b) ) ?;
366
+ prefilled += 2
342
367
}
343
368
344
- let common_len = core:: cmp:: min( read. len( ) , write. len( ) ) ;
369
+ // FIFO threshold to 16 bits
370
+ self . spi. cr2. modify( |_, w| w. frxth( ) . clear_bit( ) ) ;
345
371
// write ahead of reading
346
- let zipped = read. iter_mut ( ) . zip( write_iter) . take( common_len - prefilled) ;
372
+ let zipped = read. chunks_exact_mut ( 2 ) . zip( write_iter) . take( half_len - prefilled/ 2 ) ;
347
373
for ( r, w) in zipped {
348
- nb:: block!( self . nb_write( * w) ) ?;
349
- * r = unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ;
374
+
375
+ nb:: block!( self . nb_write( w) ) ?;
376
+ let r_two: u16 = unsafe {
377
+ nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( )
378
+ } ;
379
+ // same as above, length is checked by chunks_exact
380
+ unsafe { * r. as_mut_ptr( ) . cast( ) = r_two. to_le_bytes( ) ; }
381
+ }
382
+
383
+ // FIFO threshold to 8 bits
384
+ self . spi. cr2. modify( |_, w| w. frxth( ) . set_bit( ) ) ;
385
+
386
+ if pair_left == 1 {
387
+ let write_idx = common_len - 1 ;
388
+ nb:: block!( self . nb_write( write[ write_idx] ) ) ?;
350
389
}
351
390
352
391
// read words left in the fifo
353
- for r in read[ common_len-prefilled..common_len] . iter_mut( ) {
392
+ for r in read[ common_len-prefilled-pair_left ..common_len] . iter_mut( ) {
354
393
* r = nb:: block!( self . nb_read( ) ) ?
355
394
}
356
395
@@ -373,13 +412,17 @@ macro_rules! spi {
373
412
nb:: block!( self . nb_write( w. get( ) ) ) ?;
374
413
}
375
414
376
- for ( r, w) in write_iter. zip( read_iter. by_ref( ) ) {
415
+ // write iter always finishes first
416
+ // we don't want to consume an element from read_iter for nothing
417
+ for ( w, r) in write_iter. zip( read_iter. by_ref( ) ) {
377
418
nb:: block!( self . nb_write( w. get( ) ) ) ?;
378
419
r. set( unsafe { nb:: block!( self . nb_read_no_err( ) ) . unwrap_unchecked( ) } ) ;
379
420
}
421
+
380
422
381
423
Ok ( for r in read_iter {
382
- r. set( nb:: block!( self . nb_read( ) ) ?) ;
424
+ let read = nb:: block!( self . nb_read( ) ) ?;
425
+ r. set( read) ;
383
426
} )
384
427
}
385
428
fn flush( & mut self ) -> Result <( ) , Self :: Error > {
0 commit comments