Second attempt at SPI::DMATransfer. Now uses separate tx and rx buffers, and I also added code to wait for tx to complete and SPI to not be busy before exiting the function. Note. Operation of rx buffer has not been tested

This commit is contained in:
Roger Clark 2015-03-30 06:47:26 +11:00
parent 5f9e8a04dd
commit 664e1c88ac
3 changed files with 31 additions and 17 deletions

View File

@ -457,19 +457,21 @@ void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uin
if (true) if (true)
{ {
// Use DMA // Use DMA
byte lineBuffer[h*2];// Buffer to be sent via DMA byte txBuf[h*2];// Buffer to be sent via DMA
byte rxBuf[h*2];// Buffer to be sent via DMA
// need to build a buffer of the required height (h) // need to build a buffer of the required height (h)
// Note I suspect there is a faster way to do this // Note I suspect there is a faster way to do this
for(int i=0;i<h*2;i++) for(int i=0;i<h*2;i++)
{ {
lineBuffer[i++] = hi&0xff; txBuf[i++] = hi&0xff;
lineBuffer[i] = lo&0xff; txBuf[i] = lo&0xff;
} }
// Tansfer each line by DMA // Tansfer each line by DMA
for(int i=0;i<w;i++) for(int i=0;i<w;i++)
{ {
SPI.DMATransfer(lineBuffer,h*2); //memcpy(rxBuf,txBuf,h*2);
SPI.DMATransfer(txBuf,rxBuf,h*2);
} }
} }
else else

View File

@ -330,24 +330,33 @@ uint8 SPIClass::transfer(uint8 byte) {
return b; return b;
} }
uint8 SPIClass::DMATransfer(uint8 *data, uint32 length) { uint8 SPIClass::DMATransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint32 length) {
uint8 b; uint8 b;
dma1_ch3_Active=true; dma1_ch3_Active=true;
spi_tx_dma_enable(SPI1);
dma_init(DMA1); dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH2, &SPIClass::DMA1_CH3_Event);
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,
receiveBuf, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT | DMA_TRNS_ERR));// receive buffer DMA
dma_set_num_transfers(DMA1, DMA_CH2, length);
// TX
spi_tx_dma_enable(SPI1);
dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS, dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS,
data, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT)); 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_enable(DMA1, DMA_CH2);// enable receive
dma_enable(DMA1, DMA_CH3);// enable transmit
dma_set_num_transfers(DMA1, DMA_CH3, length); // 2 bytes per pixel
dma_enable(DMA1, DMA_CH3);
while (dma1_ch3_Active); while (dma1_ch3_Active);
while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..."
while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI."
return b; return b;
} }

View File

@ -228,7 +228,7 @@ public:
*/ */
uint8 transfer(uint8 data); uint8 transfer(uint8 data);
uint8 DMATransfer(uint8 *data, uint32 length); uint8 DMATransfer(uint8 *transmitBuf, uint8 *receiveBuf, uint32 length);
/* /*
* Pin accessors * Pin accessors
@ -303,6 +303,9 @@ private:
static inline void DMA1_CH3_Event() { static inline void DMA1_CH3_Event() {
dma1_ch3_Active = 0; dma1_ch3_Active = 0;
dma_disable(DMA1, DMA_CH3); dma_disable(DMA1, DMA_CH3);
dma_disable(DMA1, DMA_CH2);
// To Do. Need to wait for
} }
spi_dev *spi_d; spi_dev *spi_d;
uint8_t _SSPin; uint8_t _SSPin;