@@ -135,9 +135,8 @@ SPIClass::SPIClass(uint32 spi_num) {
135135 _settings[2 ].spiDmaDev = DMA2;
136136 _settings[2 ].spiTxDmaChannel = DMA_CH2;
137137 _settings[2 ].spiRxDmaChannel = DMA_CH1;
138- #endif
139-
140- // pinMode(BOARD_SPI_DEFAULT_SS,OUTPUT);
138+ #endif
139+
141140}
142141
143142/*
@@ -260,9 +259,6 @@ void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
260259 #ifdef SPI_DEBUG
261260 Serial.println (" SPIClass::beginTransaction" );
262261 #endif
263- // _SSPin=pin;
264- // pinMode(_SSPin,OUTPUT);
265- // digitalWrite(_SSPin,LOW);
266262 setBitOrder (settings.bitOrder );
267263 setDataMode (settings.dataMode );
268264 setDataSize (settings.dataSize );
@@ -316,14 +312,23 @@ uint16 SPIClass::read(void)
316312
317313void SPIClass::read (uint8 *buf, uint32 len)
318314{
315+ if ( len == 0 ) return ;
316+ spi_rx_reg (_currentSetting->spi_d ); // clear the RX buffer in case a byte is waiting on it.
319317 spi_reg_map * regs = _currentSetting->spi_d ->regs ;
320- uint8 b = (regs->DR ); // clear the RX buffer in case a byte is waiting on it.
321- // start sequence
322- while ( (len--)>0 ) {
323- regs->DR = 0x00FF ; // " write the data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
324- while ( (regs->SR & SPI_SR_RXNE)==0 ) ; // wait till data is available in the Rx register
325- *buf++ = (uint8)(regs->DR ); // read and store the received byte
326- }
318+ // start sequence: write byte 0
319+ regs->DR = 0x00FF ; // write the first byte
320+ // main loop
321+ while ( (--len) ) {
322+ while ( !(regs->SR & SPI_SR_TXE) ); // wait for TXE flag
323+ noInterrupts (); // go atomic level - avoid interrupts to surely get the previously received data
324+ regs->DR = 0x00FF ; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag.
325+ while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the DR register
326+ *buf++ = (uint8)(regs->DR ); // read and store the received byte. This clears the RXNE flag.
327+ interrupts (); // let systick do its job
328+ }
329+ // read remaining last byte
330+ while ( !(regs->SR & SPI_SR_RXNE) ); // wait till data is available in the Rx register
331+ *buf++ = (uint8)(regs->DR ); // read and store the received byte
327332}
328333
329334void SPIClass::write (uint16 data)
@@ -344,32 +349,37 @@ void SPIClass::write(uint16 data, uint32 n)
344349 spi_reg_map * regs = _currentSetting->spi_d ->regs ;
345350 while ( (n--)>0 ) {
346351 regs->DR = data; // write the data to be transmitted into the SPI_DR register (this clears the TXE flag)
347- while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty
352+ while ( (regs->SR & SPI_SR_TXE)==0 ) ; // wait till Tx empty
348353 }
349354 while ( (regs->SR & SPI_SR_BSY) != 0 ); // wait until BSY=0 before returning
350355}
351356
352- void SPIClass::write (const void *data, uint32 length)
357+ void SPIClass::write (void *data, uint32 length)
353358{
354- spi_tx (_currentSetting->spi_d , data, length); // data can be array of bytes or words
355- while (spi_is_tx_empty (_currentSetting->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
356- while (spi_is_busy (_currentSetting->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
357- // taken from SdSpiSTM32F1.cpp - Victor's lib, and adapted to support device selection
358- uint16 b = spi_rx_reg (_currentSetting->spi_d ); // dummy read, needed, don't remove!
359+ spi_dev * spi_d = _currentSetting->spi_d ;
360+ spi_tx (spi_d, (void *)data, length); // data can be array of bytes or words
361+ while (spi_is_tx_empty (spi_d) == 0 ); // "5. Wait until TXE=1 ..."
362+ while (spi_is_busy (spi_d) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
359363}
360364
361- uint8 SPIClass::transfer (uint8 byte) const {
362- spi_tx_reg (_currentSetting->spi_d , byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
363- while (spi_is_tx_empty (_currentSetting->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
364- while (spi_is_busy (_currentSetting->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
365- return (uint8)spi_rx_reg (_currentSetting->spi_d ); // "... and read the last received data."
365+ uint8 SPIClass::transfer (uint8 byte) const
366+ {
367+ spi_dev * spi_d = _currentSetting->spi_d ;
368+ spi_rx_reg (spi_d); // read any previous data
369+ spi_tx_reg (spi_d, byte); // Write the data item to be transmitted into the SPI_DR register
370+ while (spi_is_tx_empty (spi_d) == 0 ); // "5. Wait until TXE=1 ..."
371+ while (spi_is_busy (spi_d) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
372+ return (uint8)spi_rx_reg (spi_d); // "... and read the last received data."
366373}
367374
368- uint16_t SPIClass::transfer16 (uint16_t wr_data) const {
369- spi_tx_reg (_currentSetting->spi_d , wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
370- while (spi_is_tx_empty (_currentSetting->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
371- while (spi_is_busy (_currentSetting->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
372- return (uint16)spi_rx_reg (_currentSetting->spi_d ); // "... and read the last received data."
375+ uint16_t SPIClass::transfer16 (uint16_t wr_data) const
376+ {
377+ spi_dev * spi_d = _currentSetting->spi_d ;
378+ spi_rx_reg (spi_d); // read any previous data
379+ spi_tx_reg (spi_d, wr_data); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)."
380+ while (spi_is_tx_empty (spi_d) == 0 ); // "5. Wait until TXE=1 ..."
381+ while (spi_is_busy (spi_d) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
382+ return (uint16)spi_rx_reg (spi_d); // "... and read the last received data."
373383}
374384
375385/* Roger Clark and Victor Perez, 2015
@@ -382,21 +392,19 @@ uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length
382392{
383393 if (length == 0 ) return 0 ;
384394 uint8 b = 0 ;
385- spi_rx_reg (_currentSetting->spi_d ); // Clear the RX buffer in case a byte is waiting on it.
386395// dma1_ch3_Active=true;
387396 dma_init (_currentSetting->spiDmaDev );
388397// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event);
389398
390399 // RX
391- spi_rx_dma_enable (_currentSetting->spi_d );
392400 dma_xfer_size dma_bit_size = (_currentSetting->dataSize ==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
393401 dma_setup_transfer (_currentSetting->spiDmaDev , _currentSetting->spiRxDmaChannel , &_currentSetting->spi_d ->regs ->DR , dma_bit_size,
394402 receiveBuf, dma_bit_size, (DMA_MINC_MODE));// receive buffer DMA
395403 dma_set_num_transfers (_currentSetting->spiDmaDev , _currentSetting->spiRxDmaChannel , length);
404+ dma_enable (_currentSetting->spiDmaDev , _currentSetting->spiRxDmaChannel );// enable receive
396405
397406 // TX
398407 uint32 flags = (DMA_MINC_MODE | DMA_FROM_MEM);
399- spi_tx_dma_enable (_currentSetting->spi_d );
400408 if ( transmitBuf==0 ) {
401409 static uint8_t ff = 0XFF ;
402410 transmitBuf = &ff;
@@ -405,23 +413,25 @@ uint8 SPIClass::dmaTransfer(void * transmitBuf, void * receiveBuf, uint16 length
405413 dma_setup_transfer (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel , &_currentSetting->spi_d ->regs ->DR , dma_bit_size,
406414 transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
407415 dma_set_num_transfers (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel , length);
408-
409- dma_enable (_currentSetting->spiDmaDev , _currentSetting->spiRxDmaChannel );// enable receive
410416 dma_clear_isr_bits (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );
411417 dma_enable (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );// enable transmit
418+
419+ spi_rx_reg (_currentSetting->spi_d ); // Clear the RX buffer in case a byte is waiting on it.
420+ spi_rx_dma_enable (_currentSetting->spi_d );
421+ spi_tx_dma_enable (_currentSetting->spi_d ); // must be the last enable to avoid DMA error flag
412422
413423 uint32_t m = millis ();
414424 while ((dma_get_isr_bits (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel ) & DMA_ISR_TCIF1)==0 ) {// Avoid interrupts and just loop waiting for the flag to be set.
425+ // delayMicroseconds(10);
415426 if ((millis () - m) > DMA_TIMEOUT) { b = 2 ; break ; }
416427 }
417428
418429 while (spi_is_tx_empty (_currentSetting->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
419430 while (spi_is_busy (_currentSetting->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
420- dma_disable (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );
421- dma_disable (_currentSetting->spiDmaDev , _currentSetting->spiRxDmaChannel );
422- spi_rx_dma_disable (_currentSetting->spi_d ); // And disable generation of DMA request from the SPI port so other peripherals can use the channels
423431 spi_tx_dma_disable (_currentSetting->spi_d );
424- uint16 x = spi_rx_reg (_currentSetting->spi_d ); // dummy read, needed, don't remove!
432+ spi_rx_dma_disable (_currentSetting->spi_d ); // And disable generation of DMA request from the SPI port so other peripherals can use the channels
433+ dma_disable (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );
434+ dma_disable (_currentSetting->spiDmaDev , _currentSetting->spiRxDmaChannel );
425435 return b;
426436}
427437
@@ -438,25 +448,25 @@ uint8 SPIClass::dmaSend(void * transmitBuf, uint16 length, bool minc)
438448 uint8 b = 0 ;
439449 dma_init (_currentSetting->spiDmaDev );
440450 // TX
441- spi_tx_dma_enable (_currentSetting->spi_d );
442451 dma_xfer_size dma_bit_size = (_currentSetting->dataSize ==DATA_SIZE_16BIT) ? DMA_SIZE_16BITS : DMA_SIZE_8BITS;
443452 dma_setup_transfer (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel , &_currentSetting->spi_d ->regs ->DR , dma_bit_size,
444453 transmitBuf, dma_bit_size, flags);// Transmit buffer DMA
445454 dma_set_num_transfers (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel , length);
446455 dma_clear_isr_bits (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );
447456 dma_enable (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );// enable transmit
457+ spi_tx_dma_enable (_currentSetting->spi_d );
448458
449459 uint32_t m = millis ();
450460 while ((dma_get_isr_bits (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel ) & DMA_ISR_TCIF1)==0 ) {// Avoid interrupts and just loop waiting for the flag to be set.
461+ // delayMicroseconds(10);
451462 if ((millis () - m) > DMA_TIMEOUT) { b = 2 ; break ; }
452463 }
453464
454465 while (spi_is_tx_empty (_currentSetting->spi_d ) == 0 ); // "5. Wait until TXE=1 ..."
455466 while (spi_is_busy (_currentSetting->spi_d ) != 0 ); // "... and then wait until BSY=0 before disabling the SPI."
456- dma_disable (_currentSetting->spiDmaDev , _currentSetting->spiTxDmaChannel );
457467 spi_tx_dma_disable (_currentSetting->spi_d );
458- uint16 x = spi_rx_reg (_currentSetting->spi_d ); // dummy read, needed, don't remove!
459- return b;
468+ dma_disable (_currentSetting->spiDmaDev , _currentSetting-> spiTxDmaChannel );
469+ return b;
460470}
461471
462472void SPIClass::attachInterrupt (void ) {
@@ -492,18 +502,13 @@ uint8 SPIClass::nssPin(void) {
492502 */
493503
494504uint8 SPIClass::send (uint8 data) {
495- uint8 buf[] = { data} ;
496- return this -> send (buf, 1 ) ;
505+ this -> write ( data) ;
506+ return 1 ;
497507}
498508
499509uint8 SPIClass::send (uint8 *buf, uint32 len) {
500- uint32 txed = 0 ;
501- uint8 ret = 0 ;
502- while (txed < len) {
503- this ->write (buf[txed++]);
504- ret = this ->read ();
505- }
506- return ret;
510+ this ->write (buf, len);
511+ return len;
507512}
508513
509514uint8 SPIClass::recv (void ) {
0 commit comments