@@ -509,9 +509,6 @@ void SPIClass::writePattern(const uint8_t * data, uint8_t size, uint32_t repeat)
509
509
}
510
510
511
511
/* *
512
- * Note:
513
- * in and out need to be aligned to 32Bit
514
- * or you get an Fatal exception (9)
515
512
* @param out uint8_t *
516
513
* @param in uint8_t *
517
514
* @param size uint32_t
@@ -531,48 +528,90 @@ void SPIClass::transferBytes(const uint8_t * out, uint8_t * in, uint32_t size) {
531
528
}
532
529
533
530
/* *
534
- * Note:
535
- * in and out need to be aligned to 32Bit
536
- * or you get an Fatal exception (9)
537
531
* @param out uint8_t *
538
532
* @param in uint8_t *
539
533
* @param size uint8_t (max 64)
540
534
*/
541
535
void SPIClass::transferBytes_ (const uint8_t * out, uint8_t * in, uint8_t size) {
542
- while (SPI1CMD & SPIBUSY) {}
543
- // Set in/out Bits to transfer
536
+ while (SPI1CMD & SPIBUSY) {} // Make sure we're IDLE on the SPI
544
537
545
- setDataBits (size * 8 );
538
+ int bytesToTransfer = size; // How much to read/write from the FIFO in bytes
546
539
547
- volatile uint32_t * fifoPtr = &SPI1W0;
548
- uint8_t dataSize = ((size + 3 ) / 4 ) ;
540
+ if (out && !in) {
541
+ int bytesLeft = size ;
549
542
550
- if (out) {
551
- uint32_t * dataPtr = (uint32_t *) out;
552
- while (dataSize--) {
553
- *fifoPtr = *dataPtr;
554
- dataPtr++;
555
- fifoPtr++;
543
+ // Only transmitting, get out 32b aligned
544
+ while (bytesLeft && ((uint32_t )out & 3 )) {
545
+ SPI.transfer (*(out++));
546
+ bytesLeft--;
556
547
}
557
- } else {
558
- // no out data only read fill with dummy data!
559
- while (dataSize--) {
560
- *fifoPtr = 0xFFFFFFFF ;
561
- fifoPtr++;
548
+
549
+ if (!bytesLeft) return ;
550
+ bytesToTransfer = bytesLeft;
551
+
552
+ // Now do 32b writes until we have 0 or fewer bytes left
553
+ // Note we can read and store past the end of string because it will not be sent (setDataBits)
554
+ uint32_t *dataPtr = (uint32_t *)out;
555
+ volatile uint32_t *fifoPtr = &SPI1W0;
556
+ while (bytesLeft > 0 ) {
557
+ *(fifoPtr++) = *(dataPtr++);
558
+ bytesLeft -= 4 ;
562
559
}
560
+ // Remainder will be sent out of loaded FIFO below
561
+ } else if (in && !out) {
562
+ int bytesLeft = size;
563
+
564
+ // Only receiving, get in 32b aligned
565
+ while (bytesLeft && ((uint32_t )in & 3 )) {
566
+ *(in++) = SPI.transfer (0xff );
567
+ bytesLeft--;
568
+ }
569
+
570
+ if (!bytesLeft) return ;
571
+ bytesToTransfer = bytesLeft;
572
+
573
+ // Now send 32b writes of all 0xff, actual read will be done below
574
+ // Note we can write add'l 0xffs and they won't be sent thanks to setDataBits below
575
+ volatile uint32_t *fifoPtr = &SPI1W0;
576
+ while (bytesLeft > 0 ) {
577
+ *(fifoPtr++) = 0xffffffff ;
578
+ bytesLeft -= 4 ;
579
+ }
580
+ } else if (in && out && (((uint32_t )in & 3 ) || ((uint32_t )out & 3 ))) {
581
+ // Bidirectional and we have one or both pointers misaligned
582
+ while (size) {
583
+ *(in++) = SPI.transfer (*(out++));
584
+ size--;
585
+ }
586
+ // All the data was transferred byte-wise, we're done
587
+ return ;
563
588
}
564
589
590
+ // At this point we've got aligned (or null) in and out and the FIFO is filled
591
+ // with whatever data we're going to transmit as aligned
592
+
593
+ // Set in/out bits to transfer
594
+ while (SPI1CMD & SPIBUSY) {} // Paranoia, make sure SPI is idle
595
+ setDataBits (bytesToTransfer * 8 );
596
+
597
+ // Start the transfer and wait for done
565
598
SPI1CMD |= SPIBUSY;
566
- while (SPI1CMD & SPIBUSY) {}
599
+ while (SPI1CMD & SPIBUSY) { /* noop, waiting */ }
600
+
601
+ if (in) {
602
+ // Bulk read out by 4 until we have 0..3 left
603
+ uint32_t *dataPtr = (uint32_t *)in;
604
+ volatile uint32_t *fifoPtr = &SPI1W0;
605
+ while (bytesToTransfer >= 4 ) {
606
+ *(dataPtr++) = *(fifoPtr++);
607
+ bytesToTransfer -= 4 ;
608
+ in += 4 ; // Keep track of the in ptr for any stragglers
609
+ }
567
610
568
- if (in) {
569
- uint32_t * dataPtr = (uint32_t *) in;
570
- fifoPtr = &SPI1W0;
571
- dataSize = ((size + 3 ) / 4 );
572
- while (dataSize--) {
573
- *dataPtr = *fifoPtr;
574
- dataPtr++;
575
- fifoPtr++;
611
+ // Bytewise read out the remainder
612
+ volatile uint8_t *fifoPtrB = (uint8_t *)fifoPtr;
613
+ while (bytesToTransfer--) {
614
+ *(in++) = *(fifoPtrB++);
576
615
}
577
616
}
578
617
}
0 commit comments