I need to send some Data over SPI really fast. Goal is an continuous data stream with 5 Mbit data rate. Data is 64 frames with 32 bytes each. The data I need to send repeats itself, after I reach frame 64, we start with frame 0 again. After each frame, Chip Select has to be deasserted.
First I got the SPI up and running, just using interrupts. I used the SPI Interrupt example as base. The result was a 5-10µSec gap after each 16 bit sent. Also there was an event longer 30-50µSec gap after each frame while the SPI interrupt triggered and check for the "mstidle" state, waiting to send the next frame.
Next I tried SPI with DMA. This went far better. There was no gap between the bytes inside a frame. But with DMA i get a really big 250µSec gap after each frame. I guess this is caused by preparing the next frame for DMA.
At last I tried to chain up all frames as dma_descriptor_t:
dma_transfer_config_t masterTxDmaConfig;
lastData = spi0_user_data.cycles[spi0_user_data.cycle][DRIVER_COUNT] | kSPI_EndOfTransfer | (SPI0->TXCTL & 0xFFFF0000);
DMA_CreateDescriptor(&txDescriptor[0], &dma_cfg_end, &lastData, (void *)&SPI0->TXDATCTL, &txDescriptor[1]);
DMA_CreateDescriptor(&txDescriptor[1], &dma_cfg_base, spi0_user_data.cycles[spi0_user_data.cycle+1], (void *)&SPI0->TXDATCTL, &txDescriptor[2]);
DMA_CreateDescriptor(&txDescriptor[2], &dma_cfg_end, &lastData, (void *)&SPI0->TXDATCTL, &txDescriptor[3]);
DMA_CreateDescriptor(&txDescriptor[3], &dma_cfg_base, spi0_user_data.cycles[spi0_user_data.cycle+1], (void *)&SPI0->TXDATCTL, &txDescriptor[4]);
DMA_CreateDescriptor(&txDescriptor[4], &dma_cfg_end, &lastData, (void *)&SPI0->TXDATCTL, &txDescriptor[0]);
DMA_PrepareTransfer(&masterTxDmaConfig, spi0_user_data.cycles[spi0_user_data.cycle], (void *)&SPI0->TXDAT, sizeof(uint16_t), DRIVER_COUNT - 1, kDMA_MemoryToPeripheral, &txDescriptor[0]);
masterTxDmaConfig.xfercfg.intA = false;
masterTxDmaConfig.xfercfg.intB = false;
DMA_SubmitTransfer(&masterTxHandle, &masterTxDmaConfig);
DMA_StartTransfer(&masterTxHandle);
Config:
DMA_Init(DMA0);
DMA_EnableChannel(DMA0, DMA_SPI_MASTER_TX_CHANNEL);
DMA_CreateHandle(&masterTxHandle, DMA0, DMA_SPI_MASTER_TX_CHANNEL);
DMA_SetCallback(&masterTxHandle, spi_dma_finished, NULL);
DMA_SetChannelPriority(DMA0, DMA_SPI_MASTER_TX_CHANNEL, kDMA_ChannelPriority3);
dma_cfg_end.valid = true;
dma_cfg_end.swtrig = true;
dma_cfg_end.intA = true;
dma_cfg_end.byteWidth = sizeof(uint32_t);
dma_cfg_end.srcInc = 0;
dma_cfg_end.dstInc = 0;
dma_cfg_end.transferCount = 1;
dma_cfg_base.valid = true;
dma_cfg_base.swtrig = true;
dma_cfg_base.intA = false;
dma_cfg_base.byteWidth = sizeof(uint16_t);
dma_cfg_base.srcInc = 1;
dma_cfg_base.dstInc = 0;
dma_cfg_base.transferCount = DRIVER_COUNT;
But in this case the interrupts never fired and chip selct (SSEL) was never deasserted.
Any Idea how to close this gap between frames?