2014-01-06 09:27 AM
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);
2014-01-06 09:33 AM
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);
2014-01-06 09:49 AM
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 above2014-01-06 10:01 AM
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.
2014-01-07 03:19 AM
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?
2014-01-08 08:08 AM
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?
2014-01-08 10:29 AM
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.
2014-01-09 12:24 AM
So in other words, I'll have to de-initialise and then re-initialise DMA each time?