Updaded SPI with update from VictorPV

This commit is contained in:
Roger Clark 2015-07-26 04:58:12 +10:00
parent b8d1cd472a
commit 07ba8f279a
2 changed files with 84 additions and 51 deletions

View File

@ -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;
}

View File

@ -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;