From 07ba8f279a1b96b3a6047575ad2a45c3d6579a43 Mon Sep 17 00:00:00 2001 From: Roger Clark Date: Sun, 26 Jul 2015 04:58:12 +1000 Subject: [PATCH] Updaded SPI with update from VictorPV --- STM32F1/libraries/SPI/src/SPI.cpp | 103 ++++++++++++++++++------------ STM32F1/libraries/SPI/src/SPI.h | 32 +++++++--- 2 files changed, 84 insertions(+), 51 deletions(-) diff --git a/STM32F1/libraries/SPI/src/SPI.cpp b/STM32F1/libraries/SPI/src/SPI.cpp index bb45682..33cf62f 100644 --- a/STM32F1/libraries/SPI/src/SPI.cpp +++ b/STM32F1/libraries/SPI/src/SPI.cpp @@ -119,11 +119,20 @@ SPIClass::SPIClass(uint32 spi_num) { // clock divider setup is a bit of hack, and needs to be improved at a later date. _settings[0].spi_d = SPI1; _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock); + _settings[0].spiDmaDev = DMA1; + _settings[0].spiTxDmaChannel = DMA_CH3; + _settings[0].spiRxDmaChannel = DMA_CH2; _settings[1].spi_d = SPI2; _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock); + _settings[1].spiDmaDev = DMA1; + _settings[1].spiTxDmaChannel = DMA_CH5; + _settings[1].spiRxDmaChannel = DMA_CH4; #if BOARD_NR_SPI >= 3 _settings[2].spi_d = SPI3; _settings[2].clockDivider = determine_baud_rate(_settings[2].spi_d, _settings[2].clock); + _settings[2].spiDmaDev = DMA2; + _settings[2].spiTxDmaChannel = DMA_CH2; + _settings[2].spiRxDmaChannel = DMA_CH1; #endif //pinMode(BOARD_SPI_DEFAULT_SS,OUTPUT); @@ -358,51 +367,55 @@ uint8 SPIClass::dmaTransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint16 length if (length == 0) return 0; uint8 b; if (spi_is_rx_nonempty(_currentSetting->spi_d) == 1) b = spi_rx_reg(_currentSetting->spi_d); //Clear the RX buffer in case a byte is waiting on it. - dma1_ch3_Active=true; - dma_init(DMA1); - dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); +// dma1_ch3_Active=true; + dma_init(_currentSetting->spiDmaDev); +// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); // RX - spi_rx_dma_enable(SPI1); - dma_setup_transfer(DMA1, DMA_CH2, &SPI1->regs->DR, DMA_SIZE_8BITS, + spi_rx_dma_enable(_currentSetting->spi_d); + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// receive buffer DMA - dma_set_num_transfers(DMA1, DMA_CH2, length); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel, length); // TX - spi_tx_dma_enable(SPI1); + spi_tx_dma_enable(_currentSetting->spi_d); if (!transmitBuf) { static uint8_t ff = 0XFF; transmitBuf = &ff; - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, transmitBuf, DMA_SIZE_8BITS, (DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit FF repeatedly } else { - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, transmitBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));// Transmit buffer DMA } - dma_set_num_transfers(DMA1, DMA_CH3, length); + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); - dma_enable(DMA1, DMA_CH2);// enable receive - dma_enable(DMA1, DMA_CH3);// enable transmit + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel);// enable receive + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit // while (dma1_ch3_Active); // if (receiveBuf) { uint32_t m = millis(); - while (dma1_ch3_Active) { + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0) {//Avoid interrupts and just loop waiting for the flag to be set. if ((millis() - m) > 100) { - dma1_ch3_Active = 0; +// dma1_ch3_Active = 0; b = 2; break; } } + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); // } while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(DMA1, DMA_CH3); - dma_disable(DMA1, DMA_CH2); - spi_rx_dma_disable(SPI1); - spi_tx_dma_disable(SPI1); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiRxDmaChannel); + spi_rx_dma_disable(_currentSetting->spi_d); // And disable generation of DMA request from the SPI port so other peripherals can use the channels + spi_tx_dma_disable(_currentSetting->spi_d); + if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..." + uint8 x = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." + } return b; } @@ -415,24 +428,28 @@ uint8 SPIClass::dmaSend(uint8 *transmitBuf, uint16 length, bool minc) { if (length == 0) return 0; uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); uint8 b; - dma1_ch3_Active=true; - dma_init(DMA1); - dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); +// dma1_ch3_Active=true; + dma_init(_currentSetting->spiDmaDev); +// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); // TX - spi_tx_dma_enable(SPI1); - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, + spi_tx_dma_enable(_currentSetting->spi_d); + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_8BITS, transmitBuf, DMA_SIZE_8BITS, flags);// Transmit buffer DMA - dma_set_num_transfers(DMA1, DMA_CH3, length); - dma_enable(DMA1, DMA_CH3);// enable transmit + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit - while (dma1_ch3_Active); - while (spi_is_rx_nonempty(_currentSetting->spi_d) == 0); // "4. Wait until RXNE=1 ..." - b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." +// while (dma1_ch3_Active); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0); //Avoid interrupts and just loop waiting for the flag to be set. + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(DMA1, DMA_CH3); - spi_tx_dma_disable(SPI1); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + spi_tx_dma_disable(_currentSetting->spi_d); + if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..." + uint8 x = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." + } return b; } @@ -441,23 +458,27 @@ uint8 SPIClass::dmaSend(uint16 *transmitBuf, uint16 length, bool minc) { uint32 flags = ((DMA_MINC_MODE * minc) | DMA_FROM_MEM | DMA_TRNS_CMPLT); uint8 b; dma1_ch3_Active=true; - dma_init(DMA1); - dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); + dma_init(_currentSetting->spiDmaDev); +// dma_attach_interrupt(DMA1, DMA_CH3, &SPIClass::DMA1_CH3_Event); // TX - spi_tx_dma_enable(SPI1); - dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_16BITS, + spi_tx_dma_enable(_currentSetting->spi_d); + dma_setup_transfer(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, &_currentSetting->spi_d->regs->DR, DMA_SIZE_16BITS, transmitBuf, DMA_SIZE_16BITS, flags);// Transmit buffer DMA - dma_set_num_transfers(DMA1, DMA_CH3, length); - dma_enable(DMA1, DMA_CH3);// enable transmit + dma_set_num_transfers(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel, length); + dma_enable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel);// enable transmit - while (dma1_ch3_Active); - while (spi_is_rx_nonempty(_currentSetting->spi_d) == 0); // "4. Wait until RXNE=1 ..." - b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." +// while (dma1_ch3_Active); + while ((dma_get_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel) & 0x2)==0); //Avoid interrupts and just loop waiting for the flag to be set. + dma_clear_isr_bits(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + while (spi_is_tx_empty(_currentSetting->spi_d) == 0); // "5. Wait until TXE=1 ..." while (spi_is_busy(_currentSetting->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." - dma_disable(DMA1, DMA_CH3); - spi_tx_dma_disable(SPI1); + dma_disable(_currentSetting->spiDmaDev, _currentSetting->spiTxDmaChannel); + spi_tx_dma_disable(_currentSetting->spi_d); + if (spi_is_rx_nonempty(_currentSetting->spi_d) != 0){; // "4. Wait until RXNE=1 ..." + b = spi_rx_reg(_currentSetting->spi_d); // "... and read the last received data." + } return b; } diff --git a/STM32F1/libraries/SPI/src/SPI.h b/STM32F1/libraries/SPI/src/SPI.h index 0e69989..9bfe4f4 100644 --- a/STM32F1/libraries/SPI/src/SPI.h +++ b/STM32F1/libraries/SPI/src/SPI.h @@ -121,7 +121,9 @@ private: spi_dev *spi_d; uint8_t _SSPin; - uint32_t clockDivider; + uint32_t clockDivider; + dma_channel spiRxDmaChannel, spiTxDmaChannel; + dma_dev* spiDmaDev; friend class SPIClass; }; @@ -310,6 +312,23 @@ public: * this HardwareSPI instance. */ spi_dev* c_dev(void) { return _currentSetting->spi_d; } + + + spi_dev *dev(){ return _currentSetting->spi_d;} + + /** + * @brief Sets the number of the SPI peripheral to be used by + * this HardwareSPI instance. + * + * @param spi_num Number of the SPI port. 1-2 in low density devices + * or 1-3 in high density devices. + */ + + void setModule(int spi_num) + { + _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed + } + /* -- The following methods are deprecated --------------------------- */ @@ -343,15 +362,8 @@ public: */ uint8 recv(void); - spi_dev *dev(){ return _currentSetting->spi_d;} - - void setModule(int spi_num) - { - _currentSetting=&_settings[spi_num-1];// SPI channels are called 1 2 and 3 but the array is zero indexed - } - private: - +/* static inline void DMA1_CH3_Event() { dma1_ch3_Active = 0; // dma_disable(DMA1, DMA_CH3); @@ -359,7 +371,7 @@ private: // To Do. Need to wait for } - +*/ SPISettings _settings[BOARD_NR_SPI]; SPISettings *_currentSetting;