cancel
Showing results for 
Search instead for 
Did you mean: 

SPI3 DMA breaks after first halfword

stst9184
Associate II
Posted on March 13, 2012 at 17:51

If I let run this DMA interrupts, without a while looop on the line
 64 I get only first word transmitted. With a while loop it is always OK.What's wrong?


void dma_tx(uint16_t *rxbuf, uint16_t *txbuf, uint16_t count)

{

DMA_InitTypeDef DMA_InitStructure;




DMA_ClearITPendingBit(DMA2_IT_GL1);

DMA_ClearITPendingBit(DMA2_IT_GL2);

DMA_ClearFlag(DMA2_IT_GL1);

DMA_ClearFlag(DMA2_IT_GL2);



/* DMA Channel configuration ----------------------------------------------*/

DMA_Cmd(DMA2_Channel1, DISABLE);

//DMA_ITConfig(DMA2_Channel1, DMA_IT_TC/*| DMA_IT_HT| DMA_IT_TE*/, ENABLE);

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

DMA_InitStructure.DMA_MemoryBaseAddr = (u32) rxbuf;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = count;

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_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA2_Channel1, &DMA_InitStructure);





/* Dummy TX channel configuration */

DMA_Cmd(DMA2_Channel2, DISABLE);

//DMA_ITConfig(DMA2_Channel2, DMA_IT_TC/*| DMA_IT_HT| DMA_IT_TE*/, ENABLE);

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

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(txbuf);

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = count;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA2_Channel2, &DMA_InitStructure);




SPI3->SR &= ~SPI_SR_CRCERR;

SPI3->CR1 &= ~(SPI_CR1_CRCNEXT | SPI_CR1_CRCEN);

SPI_I2S_ClearFlag(SPI3, SPI_I2S_FLAG_RXNE);

SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);

SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, ENABLE);

SPI_Cmd(SPI3, ENABLE);


DMA_Cmd(DMA2_Channel1, ENABLE);

DMA_Cmd(DMA2_Channel2, ENABLE);





//while(1);

while (DMA_GetFlagStatus(DMA2_FLAG_TC2) == RESET);


//SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE);


}

#spi-dma-irq
6 REPLIES 6
stst9184
Associate II
Posted on March 13, 2012 at 20:31

In between I've studied a little bit more my case:

Transmission up to 4 halfwords works fine, from 5 is second not received etc.

What could be a problem?
Posted on March 13, 2012 at 20:32

If commenting out the while() on line 64 causes it to fail, then you should perhaps look at where the code flows after that, and whether you re-enter a DMA routine that disables the channel(s).

Why not incrementing?

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stst9184
Associate II
Posted on March 13, 2012 at 20:40

This I#ve already corrected. My actual version:
 void dma_tx(uint16_t *rxbuf, uint16_t *txbuf, uint16_t count)
{
DMA_InitTypeDef DMA_InitStructure;
uint32_t dummy;
DMA_ClearITPendingBit(DMA2_IT_GL1);
DMA_ClearITPendingBit(DMA2_IT_GL2);
DMA_ClearFlag(DMA2_IT_GL1);
DMA_ClearFlag(DMA2_IT_GL2);
/* DMA Channel configuration ----------------------------------------------*/
DMA_Cmd(DMA2_Channel1, DISABLE);
DMA_ITConfig(DMA2_Channel1, DMA_IT_TC| DMA_IT_HT| DMA_IT_TE, DISABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI3->DR));
DMA_InitStructure.DMA_MemoryBaseAddr = (u32) rxbuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = count;
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_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_Mode = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel1, &DMA_InitStructure);
/* Dummy TX channel configuration */
DMA_Cmd(DMA2_Channel2, DISABLE);
//DMA_ITConfig(DMA2_Channel2, DMA_IT_TC/*| DMA_IT_HT| DMA_IT_TE*/, ENABLE);
DMA_ITConfig(DMA2_Channel2, DMA_IT_TC| DMA_IT_HT| DMA_IT_TE, DISABLE);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI3->DR));
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(txbuf);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = count-1;
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_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel2, &DMA_InitStructure);
dummy = DMA2->ISR;
dummy = SPI3->DR;
dummy |= SPI3->SR;
SPI3->SR &= ~SPI_SR_CRCERR;
SPI3->CR1 &= ~(SPI_CR1_CRCNEXT | SPI_CR1_CRCEN);
SPI3->CR1 |= SPI_CR1_CRCEN;
SPI_I2S_ClearFlag(SPI3, SPI_I2S_FLAG_RXNE);
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_Cmd(SPI3, ENABLE);
DMA_ITConfig(DMA2_Channel2, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Channel1, ENABLE);
DMA_Cmd(DMA2_Channel2, ENABLE);
//Delay(20);
//while(1);
//while (DMA_GetFlagStatus(DMA2_FLAG_TC1) == RESET);
//SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE);
}

stst9184
Associate II
Posted on March 13, 2012 at 21:53

I am using SysTick_IRQn, which calls OS_tick, where are shorty disabled/enabled interrupts.

Tha't it. If I disable SysTick_IRQn it is OK. I though, that DMA runs also if interrupts are disabled.

Well even worth, I wanted to measure by GPIO how long takes these DMA functions, so I disabled around them interrupts.

Posted on March 13, 2012 at 22:22

No, my concern was that you were doing

while(1)

{

  // ..

  dma_tx(..);

}

And no interrupts being enabled/disabled should not impact DMA. JTAG/SWD might.

I would also check that memory is aligned, and not use auto/local variables as a DMA source/destination.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stst9184
Associate II
Posted on March 14, 2012 at 11:26

Problem found. I have an Idle task, which does a following:

while (1)

    {

        

        /* Go to sleep mode */

       __WFE();

    }

I've changed it with:

while (1)

    {

       ;

    }