Код
void MmcReceiveBlock (pInt8U pData, Int32U Size)
{
char SSP_WriteByte = 0xff;
DMA_InitTypeDef DMA_InitStruct;
/* Enable FIFO */
SSP_DMACmd(SSP0, SSP_DMA_Receive, ENABLE);
SSP_DMACmd(SSP0, SSP_DMA_Transmit, ENABLE);
/* RECIVE - DMA ch 0 */
DMA_StructInit(&DMA_InitStruct);
/*No linked lists used*/
DMA_InitStruct.DMA_Channel_LLstItm = 0;
/*Source address*/
DMA_InitStruct.DMA_Channel_SrcAdd = (u32)(&SSP0->DR);
/*Destination address*/
DMA_InitStruct.DMA_Channel_DesAdd = (u32)pData;
/*Source width of one byte*/
DMA_InitStruct.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte;
/*DMA burst size of 4 data*/
DMA_InitStruct.DMA_Channel_SrcBstSize = DMA_SrcBst_4Data;
/*Destination width of one byte*/
DMA_InitStruct.DMA_Channel_DesWidth = DMA_DesWidth_Byte;
/*The flow controller is the DMAC*/
DMA_InitStruct.DMA_Channel_FlowCntrl = DMA_FlowCntrl2_DMA;
/* DMA req source */
DMA_InitStruct.DMA_Channel_Src = DMA_SRC_SSP0_RX;
/*Transfer size */
DMA_InitStruct.DMA_Channel_TrsfSize = Size;
/*We increment the destination not the source */
DMA_ChannelSRCIncConfig (DMA_Channel0, DISABLE);
DMA_ChannelDESIncConfig (DMA_Channel0, ENABLE);
/* Init */
DMA_Init(DMA_Channel0, &DMA_InitStruct);
/* TRANSFER - DMA ch 1 */
DMA_StructInit(&DMA_InitStruct);
/*No linked lists used*/
DMA_InitStruct.DMA_Channel_LLstItm = 0;
/*Source address*/
DMA_InitStruct.DMA_Channel_SrcAdd = (u32)&SSP_WriteByte;
/*Destination address*/
DMA_InitStruct.DMA_Channel_DesAdd = (u32)((&SSP0->DR));
/*Source width of one byte*/
DMA_InitStruct.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte;
/*Destination width of one byte*/
DMA_InitStruct.DMA_Channel_DesWidth = DMA_DesWidth_Byte;
/*The flow controller is the DMAC*/
DMA_InitStruct.DMA_Channel_FlowCntrl = DMA_FlowCntrl1_DMA;
DMA_InitStruct.DMA_Channel_Des = DMA_DES_SSP0_TX;
/*Transfer size */
DMA_InitStruct.DMA_Channel_TrsfSize = Size;
/*We increment not the source not the destination*/
DMA_ChannelSRCIncConfig (DMA_Channel1, DISABLE);
DMA_ChannelDESIncConfig (DMA_Channel1, DISABLE);
/* Init */
DMA_Init(DMA_Channel1, &DMA_InitStruct);
/* Start transfer */
DMA_ChannelCmd(DMA_Channel0, ENABLE);
DMA_ChannelCmd(DMA_Channel1, ENABLE);
/* wait for the transmit channel FIFO to be empty */
while(DMA_GetChannelActiveStatus(DMA_Channel1));
/* wait for the recive channel FIFO to be empty */
while(DMA_GetChannelActiveStatus(DMA_Channel0));
Рабочий код. Производительность не мерил, но с ним уже удается без остановки "кормить" двухканальный PWM wav-файлом (44100 16 x 2) через EFSL. Это апримерно 176 Кбайт/сек. В два раза ускоряю - уже не вытягивает.
На всяк случай косяки на которые я наступил:
DMA на прием запускается не сразу - поэтому ловить его остановку стоит только после остановки DMA на передачу, иначе можем выскочить из функции еще до того, как DMA на прем принял хоть байт.
На сайте ST есть прмеры DMA под многие периферии. Правда примеров с одновременной передачей-приемом нет.
З.Ы. от шумов (потрескивания) PWM можно как-нить избавиться? Сейчас на выходе стоит цепочка (резистор)-(кондер на землю)-(резистор)-(кондер на землю). Противно посчелкивает сразу же после включения PWM.