@@ -528,94 +528,96 @@ void SPIClass::transferBytes(const uint8_t * out, uint8_t * in, uint32_t size) {
528528}
529529
530530/* *
531+ * Note:
532+ * in and out need to be aligned to 32Bit
533+ * or you get an Fatal exception (9)
531534 * @param out uint8_t *
532535 * @param in uint8_t *
533536 * @param size uint8_t (max 64)
534537 */
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
539538
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 ;
548542
549- if (!bytesLeft) return ;
550- bytesToTransfer = bytesLeft;
543+ while (SPI1CMD & SPIBUSY) {}
544+ // Set in/out Bits to transfer
551545
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 );
569547
570- if (!bytesLeft) return ;
571- bytesToTransfer = bytesLeft ;
548+ volatile uint32_t *fifoPtr = &SPI1W0 ;
549+ uint8_t dataSize = ((size + 3 ) / 4 ) ;
572550
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++ ;
579557 }
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++ ;
585563 }
586- // All the data was transferred byte-wise, we're done
587- return ;
588564 }
589565
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
598566 SPI1CMD |= SPIBUSY;
599- while (SPI1CMD & SPIBUSY) { /* noop, waiting */ }
567+ while (SPI1CMD & SPIBUSY) {}
600568
601569 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 ) {
606574 *(dataPtr++) = *(fifoPtr++);
607- bytesToTransfer -= 4 ;
608- in += 4 ; // Keep track of the in ptr for any stragglers
575+ dataSize -= 4 ;
576+ in += 4 ;
609577 }
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--) {
614580 *(in++) = *(fifoPtrB++);
615581 }
616582 }
617583}
618584
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+
619621#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPI)
620622SPIClass SPI;
621623#endif
0 commit comments