Skip to content

Commit 8018a26

Browse files
committed
Merge pull request #2299 from cmaglie/ide-1.5.x-spi-updates
Missing SPI Transaction API methods on Due (SAM3X)
2 parents 2e3e539 + 6a5b82f commit 8018a26

File tree

2 files changed

+97
-294
lines changed

2 files changed

+97
-294
lines changed

hardware/arduino/sam/libraries/SPI/SPI.cpp

+67-15
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ void SPIClass::init() {
6262
#define interruptsStatus() __interruptsStatus()
6363
static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused));
6464
static inline unsigned char __interruptsStatus(void) {
65-
unsigned int primask, faultmask;
66-
asm volatile ("mrs %0, primask" : "=r" (primask));
67-
if (primask) return 0;
68-
asm volatile ("mrs %0, faultmask" : "=r" (faultmask));
69-
if (faultmask) return 0;
70-
return 1;
65+
unsigned int primask, faultmask;
66+
asm volatile ("mrs %0, primask" : "=r" (primask));
67+
if (primask) return 0;
68+
asm volatile ("mrs %0, faultmask" : "=r" (faultmask));
69+
if (faultmask) return 0;
70+
return 1;
7171
}
7272
#endif
7373

@@ -182,18 +182,70 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
182182
d |= SPI_TDR_LASTXFER;
183183

184184
// SPI_Write(spi, _channel, _data);
185-
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
186-
;
187-
spi->SPI_TDR = d;
188-
189-
// return SPI_Read(spi);
190-
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
191-
;
192-
d = spi->SPI_RDR;
185+
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
186+
;
187+
spi->SPI_TDR = d;
188+
189+
// return SPI_Read(spi);
190+
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
191+
;
192+
d = spi->SPI_RDR;
193193
// Reverse bit order
194194
if (bitOrder[ch] == LSBFIRST)
195195
d = __REV(__RBIT(d));
196-
return d & 0xFF;
196+
return d & 0xFF;
197+
}
198+
199+
void SPIClass::transfer(byte _pin, void *_buf, size_t _count, SPITransferMode _mode) {
200+
if (_count == 0)
201+
return;
202+
203+
uint8_t *buffer = (uint8_t *)_buf;
204+
if (_count == 1) {
205+
*buffer = transfer(_pin, *buffer, _mode);
206+
return;
207+
}
208+
209+
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
210+
bool reverse = (bitOrder[ch] == LSBFIRST);
211+
212+
// Send the first byte
213+
uint32_t d = *buffer;
214+
if (reverse)
215+
d = __REV(__RBIT(d));
216+
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
217+
;
218+
spi->SPI_TDR = d | SPI_PCS(ch);
219+
220+
while (_count > 1) {
221+
// Prepare next byte
222+
d = *(buffer+1);
223+
if (reverse)
224+
d = __REV(__RBIT(d));
225+
if (_count == 2 && _mode == SPI_LAST)
226+
d |= SPI_TDR_LASTXFER;
227+
228+
// Read transferred byte and send next one straight away
229+
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
230+
;
231+
uint8_t r = spi->SPI_RDR;
232+
spi->SPI_TDR = d | SPI_PCS(ch);
233+
234+
// Save read byte
235+
if (reverse)
236+
r = __REV(__RBIT(r));
237+
*buffer = r;
238+
buffer++;
239+
_count--;
240+
}
241+
242+
// Receive the last transferred byte
243+
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
244+
;
245+
uint8_t r = spi->SPI_RDR;
246+
if (reverse)
247+
r = __REV(__RBIT(r));
248+
*buffer = r;
197249
}
198250

199251
void SPIClass::attachInterrupt(void) {

0 commit comments

Comments
 (0)