From 3cc12b1e08968aa6f35395d6a3bb265e197e91d5 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 27 Jul 2018 16:44:02 +0200 Subject: [PATCH] arduino API's SPI::transfer(void*, size) (optimized) (#4925) * SPI::transfer(void*, size) (optimized) * spi: transfer(): fix checking size * spi: transferBytes_: 32bits miso transfer * spi: transferBytes_: fix declaration * spi: transferBytes: add comments, reduce diff --- libraries/SPI/SPI.cpp | 38 +++++++++++++++++++++++++++++++++----- libraries/SPI/SPI.h | 1 + 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index 68be7d6c0..0f1786a4d 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -323,6 +323,25 @@ uint16_t SPIClass::transfer16(uint16_t data) { return out.val; } +void SPIClass::transfer(void *buf, uint16_t count) { + uint8_t *cbuf = reinterpret_cast(buf); + + // cbuf may not be 32bits-aligned + for (; (((unsigned long)cbuf) & 3) && count; cbuf++, count--) + *cbuf = transfer(*cbuf); + + // cbuf is now aligned + // count may not be a multiple of 4 + uint16_t count4 = count & ~3; + transferBytes(cbuf, cbuf, count4); + + // finish the last <4 bytes + cbuf += count4; + count -= count4; + for (; count; cbuf++, count--) + *cbuf = transfer(*cbuf); +} + void SPIClass::write(uint8_t data) { while(SPI1CMD & SPIBUSY) {} // reset to 8Bit mode @@ -511,6 +530,14 @@ void SPIClass::transferBytes(const uint8_t * out, uint8_t * in, uint32_t size) { } } +/** + * Note: + * in and out need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param out uint8_t * + * @param in uint8_t * + * @param size uint8_t (max 64) + */ void SPIClass::transferBytes_(const uint8_t * out, uint8_t * in, uint8_t size) { while(SPI1CMD & SPIBUSY) {} // Set in/out Bits to transfer @@ -539,12 +566,13 @@ void SPIClass::transferBytes_(const uint8_t * out, uint8_t * in, uint8_t size) { while(SPI1CMD & SPIBUSY) {} if(in) { - volatile uint8_t * fifoPtr8 = (volatile uint8_t *) &SPI1W0; - dataSize = size; + uint32_t * dataPtr = (uint32_t*) in; + fifoPtr = &SPI1W0; + dataSize = ((size + 3) / 4); while(dataSize--) { - *in = *fifoPtr8; - in++; - fifoPtr8++; + *dataPtr = *fifoPtr; + dataPtr++; + fifoPtr++; } } } diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 7d1fe1559..84b619f67 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -64,6 +64,7 @@ public: void beginTransaction(SPISettings settings); uint8_t transfer(uint8_t data); uint16_t transfer16(uint16_t data); + void transfer(void *buf, uint16_t count); void write(uint8_t data); void write16(uint16_t data); void write16(uint16_t data, bool msb);