cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 I2S single DMA transfer size

michaelisaev9
Associate II
Posted on December 05, 2014 at 01:14

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 #dma
2 REPLIES 2
Posted on December 05, 2014 at 12:39

> 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

JW

michaelisaev9
Associate II
Posted on December 05, 2014 at 21:35

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!