@@ -528,94 +528,96 @@ void SPIClass::transferBytes(const uint8_t * out, uint8_t * in, uint32_t size) {
528
528
}
529
529
530
530
/* *
531
+ * Note:
532
+ * in and out need to be aligned to 32Bit
533
+ * or you get an Fatal exception (9)
531
534
* @param out uint8_t *
532
535
* @param in uint8_t *
533
536
* @param size uint8_t (max 64)
534
537
*/
535
- void SPIClass::transferBytes_ (const uint8_t * out, uint8_t * in, uint8_t size) {
536
- while (SPI1CMD & SPIBUSY) {} // Make sure we're IDLE on the SPI
537
-
538
- int bytesToTransfer = size; // How much to read/write from the FIFO in bytes
539
538
540
- if (out && !in) {
541
- int bytesLeft = size;
542
-
543
- // Only transmitting, get out 32b aligned
544
- while (bytesLeft && ((uint32_t )out & 3 )) {
545
- SPI.transfer (*(out++));
546
- bytesLeft--;
547
- }
539
+ void SPIClass::transferBytesAligned_ (const uint8_t * out, uint8_t * in, uint8_t size) {
540
+ if (!size)
541
+ return ;
548
542
549
- if (!bytesLeft) return ;
550
- bytesToTransfer = bytesLeft;
543
+ while (SPI1CMD & SPIBUSY) {}
544
+ // Set in/out Bits to transfer
551
545
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 ;
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
- }
546
+ setDataBits (size * 8 );
569
547
570
- if (!bytesLeft) return ;
571
- bytesToTransfer = bytesLeft ;
548
+ volatile uint32_t *fifoPtr = &SPI1W0 ;
549
+ uint8_t dataSize = ((size + 3 ) / 4 ) ;
572
550
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 ;
551
+ if (out) {
552
+ uint32_t *dataPtr = ( uint32_t *) out;
553
+ while (dataSize--) {
554
+ *fifoPtr = *dataPtr;
555
+ dataPtr++ ;
556
+ fifoPtr++ ;
579
557
}
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-- ;
558
+ } else {
559
+ // no out data only read fill with dummy data!
560
+ while (dataSize-- ) {
561
+ *fifoPtr = 0xFFFFFFFF ;
562
+ fifoPtr++ ;
585
563
}
586
- // All the data was transferred byte-wise, we're done
587
- return ;
588
564
}
589
565
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
598
566
SPI1CMD |= SPIBUSY;
599
- while (SPI1CMD & SPIBUSY) { /* noop, waiting */ }
567
+ while (SPI1CMD & SPIBUSY) {}
600
568
601
569
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 ) {
570
+ uint32_t *dataPtr = ( uint32_t *) in;
571
+ fifoPtr = &SPI1W0 ;
572
+ dataSize = size ;
573
+ while (dataSize >= 4 ) {
606
574
*(dataPtr++) = *(fifoPtr++);
607
- bytesToTransfer -= 4 ;
608
- in += 4 ; // Keep track of the in ptr for any stragglers
575
+ dataSize -= 4 ;
576
+ in += 4 ;
609
577
}
610
-
611
- // Bytewise read out the remainder
612
- volatile uint8_t *fifoPtrB = (uint8_t *)fifoPtr;
613
- while (bytesToTransfer--) {
578
+ volatile uint8_t *fifoPtrB = (volatile uint8_t *)fifoPtr;
579
+ while (dataSize--) {
614
580
*(in++) = *(fifoPtrB++);
615
581
}
616
582
}
617
583
}
618
584
585
+
586
+ void SPIClass::transferBytes_ (const uint8_t * out, uint8_t * in, uint8_t size) {
587
+ if (!((uint32_t )out & 3 ) && !((uint32_t )in & 3 )) {
588
+ // Input and output are both 32b aligned or NULL
589
+ transferBytesAligned_ (out, in, size);
590
+ } else if (!out && ((uint32_t )in & 3 )) {
591
+ // Input only and misaligned, do bytewise until in aligned
592
+ while (size && ((uint32_t )in & 3 )) {
593
+ *(in++) = transfer (0xff );
594
+ size--;
595
+ }
596
+ transferBytesAligned_ (out, in, size);
597
+ } else if (!in && ((uint32_t )out & 3 )) {
598
+ // Output only and misaligned, bytewise xmit until aligned
599
+ while (size && ((uint32_t )out & 3 )) {
600
+ transfer (*(out++));
601
+ size--;
602
+ }
603
+ transferBytesAligned_ (out, in, size);
604
+ } else {
605
+ // HW FIFO has 64b limit, so just align in RAM and then send to FIFO aligned
606
+ uint8_t outAligned[64 ]; // Stack vars will be 32b aligned
607
+ uint8_t inAligned[64 ]; // Stack vars will be 32b aligned
608
+ if (out) {
609
+ memcpy (outAligned, out, size);
610
+ } else {
611
+ memset (outAligned, 0xff , size); // 0xff = no xmit data
612
+ }
613
+ transferBytesAligned_ (outAligned, inAligned, size);
614
+ if (in) {
615
+ memcpy (in, inAligned, size);
616
+ }
617
+ }
618
+ }
619
+
620
+
619
621
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPI)
620
622
SPIClass SPI;
621
623
#endif
0 commit comments