2012-03-13 09:51 AM
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
2012-03-13 12:31 PM
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?2012-03-13 12:32 PM
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;
2012-03-13 12:40 PM
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);
}
2012-03-13 01:53 PM
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.2012-03-13 02:22 PM
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.2012-03-14 03:26 AM
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) { ; }