2014-12-04 04:14 PM
I need to make a single small TX transfer over I2S interface using DMA. But instead of short transfer I've got a long-long transfer (seems of maximum size). What is the right method to set the number of packets to be sent? Isn't it a DMA_BufferSize member? Here is my code:
void I2S_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; I2S_InitTypeDef I2S_Config; DMA_InitTypeDef DMA_InitStructure; /* I2S PCLK = 2Mhz * 200 / 2 = 200Mhz */ /* 2Mhz * N = <192-432> */ RCC_PLLI2SConfig(200, 2); RCC_PLLI2SCmd(ENABLE); /* Enable GPIOs clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* Connect pins to AF ************************************************/ /* CLK and SD (TX)*/ GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); /* GPIO configuration **************************************************/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); I2S_StructInit(&I2S_Config); I2S_Config.I2S_AudioFreq = I2S_AudioFreq_Default; I2S_Config.I2S_CPOL = I2S_CPOL_Low; I2S_Config.I2S_DataFormat = I2S_DataFormat_16b; I2S_Config.I2S_MCLKOutput = I2S_MCLKOutput_Disable; I2S_Config.I2S_Mode = I2S_Mode_MasterTx; I2S_Config.I2S_Standard = I2S_Standard_Phillips; I2S_Init(SPI2, &I2S_Config); /* I2S CLK = I2S PCLK / 2 * DIV = 200 / 2 * DIV/ /* 200 / (2 * 50) = 2Mhz */ SPI2->I2SPR = 0x0000 + 50; I2S_Cmd(SPI2, ENABLE); /* Enable DMA1 clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); /* DMA1 Stream4 Configuration */ DMA_DeInit(DMA1_Stream4); DMA_InitStructure.DMA_Channel = DMA_Channel_0; // SPI DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&MySYNCBuffer[0]; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = I2S_BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream4, &DMA_InitStructure); DMA_FlowControllerConfig(DMA1_Stream4, DMA_FlowCtrl_Peripheral); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);}int main(void){ RCC_GetClocksFreq(&RCC_Clocks); I2S_Config(); DMA_Cmd(DMA1_Stream4, ENABLE); while (DMA_GetCmdStatus(DMA1_Stream4) == ENABLE); while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET); while (1) { }}In this example I've got a million of packets instead of I2S_BUFFER_SIZE. Who knows what I am doing wrong? #i2s #stm32f #dma2014-12-05 03:39 AM
> DMA_FlowControllerConfig(DMA1_Stream4, DMA_FlowCtrl_Peripheral);
If this does what I believe it does (probably sets PFCTRL bit in DMA_SxCR - I don't speak the ''library'' gobbledygook), I know what do you do wrong: you don't read the manual. RM0090 rev.8 ch.10.3.15 Flow controller JW2014-12-05 12:35 PM
Jan, thank you very much ! It really helped. I also read AN4031 and wish ST include some parts of it in Reference Manual. AppNotes are more clear in understanding. I tried both values for FlowController and it seems ''Peripherial'' was the last when I end my experiments and posted code here. Some other parameters values makes my code non-working when FlowController had correct value.
Good luck!