AnsweredAssumed Answered

Combining SPI DMA (SPI mode SD card) and I2S DMA

Question asked by Jeremy Gordon on Sep 7, 2015
Latest reply on Sep 28, 2015 by isaacavila



I'm having problems trying to combine two working "bare metal" implementations I created and looking for guidance or tips. Short version, I'm not sure I understand how to get multiple DMA channels to play nice together.


I'm using a custom K20 based board I designed running at 72mhz, and I used the bare minimum of processor expert to configure the system clocks, etc. I'm also using MQX Lite, for tasks and light weight events.


I have a working "bare metal" SPI mode SD card implementation using a from scratch implementation of diskio.c for FatFS, but I used the Kintetis SDK source code as a guide to get a three channel SPI/DMA implementation working. The first DMA channel is for SPI receive, the second DMA channel copies bytes to a temporary location where it is combined with the SPI control flags, and the third DMA channel copies from the temporary location to the SPI PUSHR to transmit. I'm able to get this reading data from an SD card in SPI mode at ~18mhz.


I also have a working "bare metal" I2S implementation that I wrote talking to a codec and using DMA to play back stereo 44.1khz 16-bit audio. My playback is of a sin(x) wave generated in my DMA half complete ISR routine.


My goal is to have audio data DMA'd from the SD card into a buffer then DMA'd to the I2S to the audio codec.


My initial implementation is to set an event in the DMA half complete ISR routine for the I2S. In my task, I have a while loop waiting on the event. When it gets the event, I read 512 bytes from the SD card into the opposite half of the buffer from the one being read by the DMA->I2S.


--- I2S (audio codec)

DMA0 = 1024/2 buffer->I2S

--- SPI (SD card)

DMA1 = 32-bit SPI command->SPI PUSHR

DMA2 = 512 byte memory->32-bit SPI command

DMA3 = 512 byte memory->SPI POPR


I've tried setting the priorities up as 0, 1, 2, 3 respectively on the three DMA channels with the ECP bit enabled, and I've enabled BWC to throttle them a bit, but I keep getting I2S transmit fifo under run errors indicating I'm not feeding the I2S fast enough but unless my math is totally off I should more than be able to feed the 44.1khz 16-bit stereo from 18mhz clocked SPI.


Anyone have any suggestions on samples or documentation, or tips on architecture for something like this?