cancel
Showing results for 
Search instead for 
Did you mean: 

DMA Transfer Complete Interrupt firing before end of transfer

isaquesuzuki
Associate II
Posted on September 04, 2013 at 22:45

Hello everyone, 

I'm trying to transfer 2 bytes using SPI in master mode and DMA. Additionally I have to set and reset CS signal by software. CS signal is low before starting transfer and is high after transfer.

So this is the code:

SPI Configuration:

  

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  

  SPI_InitStruct.SPI_BaudRatePrescaler  = SPI_BaudRatePrescaler_16;

  SPI_InitStruct.SPI_CPHA               = SPI_CPHA_1Edge;

  SPI_InitStruct.SPI_CPOL               = SPI_CPOL_High;

  SPI_InitStruct.SPI_CRCPolynomial      = 7;

  SPI_InitStruct.SPI_DataSize           = SPI_DataSize_8b;

  SPI_InitStruct.SPI_Direction          = SPI_Direction_1Line_Tx;

  SPI_InitStruct.SPI_FirstBit           = SPI_FirstBit_MSB;

  SPI_InitStruct.SPI_Mode               = SPI_Mode_Master;

  SPI_InitStruct.SPI_NSS                = SPI_NSS_Soft;

  SPI_Init(SPI1,&SPI_InitStruct);

  

  SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);

DMA Configuration:

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  DMA_DeInit(DMA1_Channel3);

  DMA_InitStructure.DMA_PeripheralBaseAddr = SPI1_DR_Address;

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Sine12bit;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

  DMA_InitStructure.DMA_BufferSize = 2;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

  DMA_Init(DMA1_Channel3, &DMA_InitStructure);

  

  DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE);

and DMA ISR:

void DMA1_Channel2_3_IRQHandler(void) {

  if(DMA_GetITStatus(DMA1_IT_TC3)) {

    //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) { };

    //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET) { };

    GPIO_SetBits(GPIOA,GPIO_Pin_4);       // CS

    DMA_ClearITPendingBit(DMA1_IT_GL3);

  }

}

Before enabling SPI DMA transfer I reset CS signal. As you can see below the DMA transfer completes before transfering all bits. Is this expected?

0690X00000604yyQAA.png

#spi-dma #stm32f0-spi-dma
2 REPLIES 2
Posted on September 04, 2013 at 23:13

Is this expected?

Well if you understand that TXE flags if a holding buffer is empty and doesn't relate to if the bits have hit the wire. TXE will assert immediately before the last byte starts transmitting.

 RXNE would be a better signal that the last bit was actually transmitted.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jpeacock2399
Associate II
Posted on September 05, 2013 at 00:35

Since SPI is always bi-directional you have to receive the data shifted in as well as sending the data shifting out.  Set up both RX and TX DMA channels for SPI, but set the RX to a single dummy location, no memory increment, since you don't need the results.  Then use the TC from the RX DMA channel to signal the last byte has shifted in, and by implication the last byte must also have been shifted out.

  Jack Peacock