cancel
Showing results for 
Search instead for 
Did you mean: 

Buffer sizes for SPI and DMA

jdcowpland
Associate II
Posted on January 06, 2014 at 18:27

Quick Question: I'm using DMA to transfer some data over SPI, and the first time round, I'm sending data from a buffer of size 3 bytes. I then redefine the DMA to try and send a buffer of size 4 bytes, but it just sends the first 3 bytes. Any idea why? This is my DMA setup, and all I do is call the function with a different sized cmd array each time, and then enable it after the setup.

void DMA_Config(uint8_t cmd[]){
DMA_InitTypeDef DMA_InitStructure;
DMA_Cmd(DMA1_Stream0,DISABLE);
DMA_Cmd(DMA1_Stream5,DISABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
DMA_DeInit(DMA1_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // Receive
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) spi_rd;
DMA_InitStructure.DMA_BufferSize = sizeof(spi_rd);
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPI3->DR));
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_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_Stream0, &DMA_InitStructure);
DMA_DeInit(DMA1_Stream5);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Transmit
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) cmd;//(uint8_t)Buffer;
DMA_InitStructure.DMA_BufferSize = (sizeof(cmd)-1);
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPI3->DR));
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_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_Stream5, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Stream5, DMA_IT_TC, ENABLE);
/* Enable SPI DMA TX Requests */
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
/* Enable SPI DMA RX Requests */
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, ENABLE);

7 REPLIES 7
jdcowpland
Associate II
Posted on January 06, 2014 at 18:33

For example, one of my function calls is like this:

uint8_t cmd[] = {0x00,0x00,0x00};
GPIO_SetBits(GPIOA,GPIO_Pin_15);
while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
Delay(1);
GPIO_ResetBits(GPIOA,GPIO_Pin_15);
DMA_Config(cmd);
DMA_Cmd(DMA1_Stream5, ENABLE);

And the other one is like this:

uint32_t address = 0x102400;
GPIO_SetBits(GPIOA,GPIO_Pin_15);
uint8_t add[]={(address >> 16),((address >> 8) & 0xFF),(address & 0xFF), 0x00};
DMA_Config(add);
GPIO_ResetBits(GPIOA,GPIO_Pin_15);
DMA_Cmd(DMA1_Stream5, ENABLE);

francescatodiego
Associate II
Posted on January 06, 2014 at 18:49

two suggestions:

1.- C language

uint8_t cmd[] ;

sizeof(cmd) is equivalent to (sizeof(uint8_t *)) = 4 for STM32 compiler

2.- STM32 library You can use DMA_SetCurrDataCounter for changing the DMA_BufferSize value without recall DMAcfg every TX

Init DMAcfg with dummy value  (NOT zero) and change it before start TX using the procudere mentioned above

 

Posted on January 06, 2014 at 19:01

I think might want to ensure the Tx/Rx buffer lengths are symmetrical. Doing a TX TC interrupt seems a little pointless if the RX TC comes immediately after the transfer has completed.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jdcowpland
Associate II
Posted on January 07, 2014 at 12:19

Ok thanks, I have now got it working after making the changes you suggested! Got another issue now though. With the device I'm working with, it only accepts data at a low baud rate for setup, and after setup I can increase the baud rate. I've set that up, but after disabling SPI, reconfiguring it with the higher baud rate and re-enabling it, nothing sends. Any idea if I have to do something with the DMA side of things?

jdcowpland
Associate II
Posted on January 08, 2014 at 17:08

Turns out that if I call the DMA config again after changing the baud rate, it all works again. Another issue I've just come across is to do with the buffer pointer for rx. I receive data which is put into my rx buffer by the dma. i then read that data and clear the buffer for the next bunch of data to come in. However when the next bunch of data comes in, the dma puts in into the buffer in the place it last stopped. Is there anyway to move the pointer back to the start of the buffer after every read?

Posted on January 08, 2014 at 19:29

In Normal mode the DMA_Init() is a one-shot deal, I haven't done the homework to tell you what the minimum reconfiguration requirement is.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jdcowpland
Associate II
Posted on January 09, 2014 at 09:24

So in other words, I'll have to de-initialise and then re-initialise DMA each time?