AnsweredAssumed Answered

STM32F407 I2S single DMA transfer size

Question asked by isaev.michael on Dec 5, 2014
Latest reply on Dec 5, 2014 by isaev.michael
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?

Outcomes