cancel
Showing results for 
Search instead for 
Did you mean: 

DMA to SPI hangs at second transfer

elektro255
Associate
Posted on January 01, 2012 at 22:58

When I use DMA to trasfer data from memory to SPI2 everything works well util I try do another trasfer, then I reload NDTR register I try enable DMA, but nothing happens, there are no errors in setatus register, just cant set EN bit for stream. When I do deinitialization of DMA stream, and initialize again, it works well.

Siple code where problem occurs:

SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;

    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

    SPI_InitStructure.SPI_CRCPolynomial = 7;

    SPI_Init(SPI2, &SPI_InitStructure);

    SPI_Cmd(SPI2, ENABLE);

    DMA_DeInit(DMA1_Stream4);

    DMA_Cmd(DMA1_Stream4, DISABLE);

    DMA_InitTypeDef DMA_InitStructure;

    DMA_InitStructure.DMA_Channel = DMA_Channel_0;

    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) (&(SPI2->DR));

    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) (&buuf);

    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

    DMA_InitStructure.DMA_BufferSize = (uint32_t) 10;

    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_Cmd(DMA1_Stream4, ENABLE);   //THIS TRANSATION WORK WELL

    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

  while (DMA_GetCurrDataCounter(DMA1_Stream4));

    DMA_Cmd(DMA1_Stream4,DISABLE);

    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);

    while (DMA1_Stream4->CR & 0x01 == 1);

    DMA1_Stream4->NDTR=17;

    DMA_Cmd(DMA1_Stream4,ENABLE); //THIS WILL NOT ENABLE STREAM EN=0

    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); //HANG HERE

    while (DMA_GetCurrDataCounter(DMA1_Stream4));

    DMA_Cmd(DMA1_Stream4,DISABLE);

    while (DMA1_Stream4->CR & 0x01 == 1);

    DMA1_Stream4->M0AR = (uint32_t) (&buuf);

    DMA1_Stream4->NDTR=27;

    DMA_Cmd(DMA1_Stream4,ENABLE);

#dma-spi
2 REPLIES 2
raptorhal2
Lead
Posted on January 01, 2012 at 23:43

The DMA mode is Normal, not Circular. I believe you have to reset the address pointer (MOAR) each time.

Happy New Year, Hal

elektro255
Associate
Posted on January 02, 2012 at 18:09

I solved problem, to start new DMA transation I have to reset ''DMA Transfer complete interrupt flag'' TCIF, I'm not using interrupts and I have no idea why I should reset this flag, especialy there is no a single word about it in Reference Manual DM00031020