Hi guys,
I am working on simple project in atsame70q21 xplained board (using atmel start v4), which is to drive RA8875 LCD controller via SPI protocol. I used LVGL library to make the GUI drawing on the screen. Till now I have managed to get it working smoothly. I did it with both sync SPI and dma SPI in two separate projects. The sync SPI version works perfectly with just 26us between each transfer. However, the dma SPI version on the other hand takes 4ms between each transfer.
I cannot use the sync version because while the data (more than 16000 bytes) is transferred, the processor is needed to process or render the next chunk of data. Now, the problem is that when I send multiple transfers of two bytes each via DMA, it takes about 4ms between two transfers. The reason that each transfer has only two bytes because I want the chip select pin to be high at end of each second byte (to tell the LCD controller the transfer has ended) otherwise the LCD won't work. The only place I can keep it low in more than two bytes is when transferring the bitmap bytes. ( about 16000 bytes )
The code/logic I use in the dma version:
// Send a buffer with two bytes on each transfer void RA8875_sendBuffer(int numOfBytes, uint8_t* currArray){ currentCounter = 0; numberOfBytes = numOfBytes; currentArray = currArray; SPITransferDone = false; SPINoTransaction = false; spi_m_dma_transfer(&SPI_0, currArray, NULL, 2); while(!SPITransferDone){ delay_us(1); } return RA8875_SUCCESS; } // Send large chunk of data in one transfer void RA8875_flushBuffer(int numOfBytes, uint8_t* currArray){ currentCounter = 0; numberOfBytes = -1; currentArray = currArray; SPINoTransaction = false; SPITransferDone = false; isFlushing = true; spi_m_dma_transfer(&SPI_0, currArray, NULL, numOfBytes); //return RA8875_SUCCESS; }
// Callback function when DMA transfer completed. static void tx_complete_cb_SPI_0(struct _dma_resource *resource) { currentCounter++; // IsFlushing is true when large data is sent in one tranfer if(isFlushing){ //printf("Flush is ended.\r\n"); isFlushing = false; SPITransferDone = true; lv_disp_flush_ready(disp_drv_p); }else if(currentCounter < numberOfBytes/2){ delay_us(100); spi_m_dma_transfer(&SPI_0, currentArray + (2*currentCounter) , NULL, 2); }else if(currentCounter == numberOfBytes/2){ SPITransferDone = true; } SPINoTransaction = true; }
SPI Config File:
/* Auto-generated config file hpl_spi_config.h */ #ifndef HPL_SPI_CONFIG_H #define HPL_SPI_CONFIG_H // <<< Use Configuration Wizard in Context Menu >>> #include <peripheral_clk_config.h> // Enable configuration of module #ifndef CONF_SPI_0_ENABLE #define CONF_SPI_0_ENABLE 1 #endif // Set module in SPI Master mode #ifndef CONF_SPI_0_MODE #define CONF_SPI_0_MODE 0x01 #endif // Set FIFO disable #ifndef CONF_SPI_0_FIFO_DISABLE #define CONF_SPI_0_FIFO_DISABLE 0x01 #endif // Set peripheral select as fixed #ifndef CONF_SPI_0_PS #define CONF_SPI_0_PS 0x0 #endif // Set chip select decode as directly #ifndef CONF_SPI_0_PCSDEC #define CONF_SPI_0_PCSDEC 0x0 #endif //<o> SPI DMA TX Channel <0-23> //<i> This defines DMA channel to be used //<id> spi_master_dma_tx_channel #ifndef CONF_SPI_0_M_DMA_TX_CHANNEL #define CONF_SPI_0_M_DMA_TX_CHANNEL 0 #endif // <e> SPI RX Channel Enable // <id> spi_master_rx_channel #ifndef CONF_SPI_0_RX_CHANNEL #define CONF_SPI_0_RX_CHANNEL 1 #endif //<o> DMA Channel <0-23> //<i> This defines DMA channel to be used //<id> spi_master_dma_rx_channel #ifndef CONF_SPI_0_M_DMA_RX_CHANNEL #define CONF_SPI_0_M_DMA_RX_CHANNEL 1 #endif // </e> // <h> Basic Configuration // <o> Character Size // <i> Bit size for all characters sent over the SPI bus (CHSIZE) // <0x0=>8 bits // <0x1=>9 bits // <0x2=>10 bits // <0x3=>11 bits // <0x4=>12 bits // <0x5=>13 bits // <0x6=>14 bits // <0x7=>15 bits // <0x8=>16 bits // <id> spi_master_character_size #ifndef CONF_SPI_0_CHSIZE #define CONF_SPI_0_CHSIZE 0x0 #endif // <o> Baud rate <1-12000000> // <i> The SPI data transfer rate. Note: (fspi_clock / baudrate) < 255 // <id> spi_master_baud_rate #ifndef CONF_SPI_0_BAUD #define CONF_SPI_0_BAUD 1000000 #endif // </h> // <e> Advanced Configuration // <id> spi_master_advanced #ifndef CONF_SPI_0_ADVANCED #define CONF_SPI_0_ADVANCED 0 #endif // <o> Dummy byte <0x00-0xFFFF> // <id> spi_master_dummybyte // <i> Dummy byte used when reading data from the slave without sending any data #ifndef CONF_SPI_0_DUMMYBYTE #define CONF_SPI_0_DUMMYBYTE 0xffff #endif // <o> Clock Polarity // <0=>The inactive state value of SPCK is logic level zero. // <1=>The inactive state value of SPCK is logic level one. // <i> Determines the inactive state value of the serial clock (SPCK). // <id> spi_master_arch_cpol #ifndef CONF_SPI_0_CPOL #define CONF_SPI_0_CPOL 0x0 #endif // <o> Clock Phase // <0x0=>Data is changed on the leading edge of SPCK and captured on the following edge of SPCK. // <0x1=>Data is captured on the leading edge of SPCK and changed on the following edge of SPCK. // <i> Determines which edge of SPCK causes data to change and which edge causes data to be captured. // <id> spi_master_arch_cpha #ifndef CONF_SPI_0_NCPHA #define CONF_SPI_0_NCPHA 0x1 #endif // <o> Delay Before SPCK (ns) <0-255000> // <i> This field defines the delay from NPCS falling edge (activation) to the first valid SPCK transition (in ns). // <id> spi_master_dlybs #ifndef CONF_SPI_0_DLY_SPCK #define CONF_SPI_0_DLY_SPCK 800 #endif // <o> Delay Between Consecutive Transfers (ns) <0-8160000> // <i> This field defines the delay between two consecutive transfers with the same peripheral without removing the chip select (in ns). // <id> spi_master_dlybct #ifndef CONF_SPI_0_DLY_BCT #define CONF_SPI_0_DLY_BCT 800 #endif // </e> /* Calculate baud register value from requested baudrate value */ #ifndef CONF_SPI_0_BAUD_RATE #define CONF_SPI_0_BAUD_RATE (CONF_SPI0_FREQUENCY / CONF_SPI_0_BAUD) #endif /* Calculates the value of the CSR DLYBS field given the desired delay (in ns) */ #ifndef CONF_SPI_0_DLYBS #define CONF_SPI_0_DLYBS (((CONF_SPI0_FREQUENCY / 1000000) * CONF_SPI_0_DLY_SPCK) / 1000) #endif /* Calculates the value of the CSR DLYBCT field given the desired delay (in ns) */ #ifndef CONF_SPI_0_DLYBCT #define CONF_SPI_0_DLYBCT (((CONF_SPI0_FREQUENCY / 1000000) * CONF_SPI_0_DLY_BCT) / 32000) #endif // <<< end of configuration section >>> #endif // HPL_SPI_CONFIG_H
Is there any settings I can change to reduce this 4ms? or can I combine the sync version and the dma version in the same Atmel Start project in which I send large data through DMA and send the configuration data through sync spi?
Thank you in advance.