cancel
Showing results for 
Search instead for 
Did you mean: 

SPI1 in DMA2 on STM32F4

neoirto
Associate II
Posted on October 29, 2012 at 15:16

Hi,

I'm trying to switch SPI1 to DMA mode. First I just try to enable on RX channel only, but I tried both RX TX, and many configuration, and I can't figure why it doesn't want to start...

 

#define NBR_BYTES_ 15

 

uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { ADDRESS_TO_READ, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };

 

uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};

 

 

SPI_InitTypeDef  SPI_InitStructure;

 

 

SPI_I2S_DeInit(SPI1);

 

 

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

 

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

 

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

 

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /// cad

 

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/// cad

 

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

 

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;

 

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

 

SPI_InitStructure.SPI_CRCPolynomial = 7;

 

SPI_Init(SPI1, &SPI_InitStructure);

 

 

SPI_Cmd(SPI1, ENABLE);

 

 

 

Init_device_in_poll_mode(); /// works ok

 

 

 

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE); 

 

 

DMA_Cmd(DMA2_Stream0, DISABLE);

 

DMA_Cmd(DMA2_Stream5, DISABLE);

 

 

/////////////// RX DMA

 

DMA_InitTypeDef DMA_InitStructure;

 

DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;

 

DMA_InitStructure.DMA_Channel = DMA_Channel_3;

 

DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_MASTER_Buffer_Rx;

 

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;

 

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

 

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_Mode_Circular; //DMA_Mode_Normal;

 

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

 

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

 

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

 

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

 

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

 

DMA_Init(DMA2_Stream0, &DMA_InitStructure);

 

 

/////////////// TX DMA

 

// DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;

 

// DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;

 

// DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;

 

 

// DMA_InitStructure.DMA_Channel = DMA_Channel_3;

 

// DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

 

// 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_Mode_Circular; //DMA_Mode_Normal;

 

// DMA_InitStructure.DMA_Priority = DMA_Priority_High;

 

// DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

 

// DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

 

// DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

 

// DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

 

// DMA_Init(DMA2_Stream5, &DMA_InitStructure);

 

 

// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

 

// DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

 

 

while(SPI1->SR & SPI_SR_TXE == 0);                // wait for empty TX buffer 

 

SPI1->DR = ADDRESS_TO_READ;                                

 

 

// DMA_Cmd(DMA2_Stream5, ENABLE);

 

DMA_Cmd(DMA2_Stream0, ENABLE);

 

 

GPIO_ResetBits(GPIOB, GPIO_Pin_15); ///// debug blue led

 

 

while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0));

 

 

GPIO_SetBits(GPIOB, GPIO_Pin_15); ///// debug blue led

Tx for your help !
11 REPLIES 11
Posted on October 29, 2012 at 15:21

In bound SPI on a master is driven by the transmit clock, generated by out bound data,  receive is merely a side effect.

You need to transmit something, even if it is junk.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
neoirto
Associate II
Posted on October 29, 2012 at 15:29

Thank you Clive1, 

You mean with something like this ?

 

#define NBR_BYTES_ 15

 

uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { ADDRESS_TO_READ, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };

 

uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};

 

 

SPI_InitTypeDef  SPI_InitStructure;

 

 

 

SPI_I2S_DeInit(SPI1);

 

 

 

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

 

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

 

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

 

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /// cad

 

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/// cad

 

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

 

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;

 

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

 

SPI_InitStructure.SPI_CRCPolynomial = 7;

 

SPI_Init(SPI1, &SPI_InitStructure);

 

 

 

SPI_Cmd(SPI1, ENABLE);

 

 

 

Init_device_in_poll_mode(); /// works ok

 

 

 

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE); 

 

 

DMA_Cmd(DMA2_Stream0, DISABLE);

 

DMA_Cmd(DMA2_Stream5, DISABLE);

 

 

/////////////// RX DMA

 

DMA_InitTypeDef DMA_InitStructure;

 

DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;

 

DMA_InitStructure.DMA_Channel = DMA_Channel_3;

 

DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_MASTER_Buffer_Rx;

 

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;

 

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

 

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_Mode_Circular; //DMA_Mode_Normal;

 

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

 

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

 

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

 

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

 

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

 

DMA_Init(DMA2_Stream0, &DMA_InitStructure);

 

 

/////////////// TX DMA

 

DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;

 

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;

 

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;

 

 

DMA_InitStructure.DMA_Channel = DMA_Channel_3;

 

DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

 

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_Mode_Circular; //DMA_Mode_Normal;

 

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

 

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

 

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

 

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

 

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

 

DMA_Init(DMA2_Stream5, &DMA_InitStructure);

 

 

// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

 

// DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

 

 

while(SPI1->SR & SPI_SR_TXE == 0);                // wait for empty TX buffer 

 

SPI1->DR = ADDRESS_TO_READ;                                

 

 

DMA_Cmd(DMA2_Stream5, ENABLE);

 

DMA_Cmd(DMA2_Stream0, ENABLE);

 

 

GPIO_ResetBits(GPIOB, GPIO_Pin_15); ///// debug blue led

 

 

while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0));

 

 

GPIO_SetBits(GPIOB, GPIO_Pin_15); ///// debug blue led

 

It doesn't work too, at the moment, and I can't figure why (I tried many combinations...)
Posted on October 29, 2012 at 15:55

Don't you need something like

    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

To light it off?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
neoirto
Associate II
Posted on October 29, 2012 at 16:07

I appreciate your help a lot, Clive

Now :

#define NBR_BYTES_ 14

uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { 0, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };

uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};

SPI_InitTypeDef  SPI_InitStructure;

SPI_I2S_DeInit(SPI1);

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /// cad

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/// cad

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStructure.SPI_CRCPolynomial = 7;

SPI_Init(SPI1, &SPI_InitStructure);

SPI_Cmd(SPI1, ENABLE);

Init_device_in_poll_mode(); /// works ok

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE); 

DMA_Cmd(DMA2_Stream0, DISABLE);

DMA_Cmd(DMA2_Stream5, DISABLE);

/////////////// RX DMA

DMA_InitTypeDef DMA_InitStructure;

DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;

DMA_InitStructure.DMA_Channel = DMA_Channel_3;

DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_MASTER_Buffer_Rx;

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

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_Mode_Circular; //DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA2_Stream0, &DMA_InitStructure);

/////////////// TX DMA

DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;

DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;

DMA_InitStructure.DMA_Channel = DMA_Channel_3;

DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

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_Mode_Circular; //DMA_Mode_Normal;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA2_Stream5, &DMA_InitStructure);

// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

// DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

  SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

  SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

  

while(SPI1->SR & SPI_SR_TXE == 0);                // wait for empty TX buffer 

SPI1->DR = ADDRESS_TO_READ;                                

DMA_Cmd(DMA2_Stream5, ENABLE);

DMA_Cmd(DMA2_Stream0, ENABLE);

GPIO_ResetBits(GPIOB, GPIO_Pin_15); ///// debug blue led

while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0));

GPIO_SetBits(GPIOB, GPIO_Pin_15); ///// debug blue led

But led is still on...

I modified this part too : because I have to send ADDRESS_TO_READ, and then read 14 bytes coming from device : is that correct ?

#define NBR_BYTES_ 14

uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { 0, 0,0,0,0,0,0, 0,0,0,0,0,0,0 };

uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99, 99,99,99,99,99,99 ,99,99,99,99,99,99 ,99};
neoirto
Associate II
Posted on October 30, 2012 at 11:11

Well, I've done my best, and it still light my led...

Does anybody can send me a known working SPI+DMA configuration (even if it's not a SPI1) on STM32F4xx please ?

Is it possible it's related to the DMA2 bug (

http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/ERRATA_SHEET/DM00037591.pdf

) ?

I don't believe in a first step, it may be my initialization procedure. But I can't find any complete and working configuration example SPI+DMA.

Your help would be greatly appreciated !
russdx
Associate II
Posted on October 30, 2012 at 13:37

SPI1 + DMA on a STM32F4

//#define SPI SPI1
#define SPI_PORT SPI1
#define SPI_PORT_CLOCK RCC_APB2Periph_SPI1
#define SPI_PORT_CLOCK_INIT RCC_APB2PeriphClockCmd
#define SPI_SCK_PIN GPIO_Pin_5
#define SPI_SCK_GPIO_PORT GPIOA
#define SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOA
#define SPI_SCK_SOURCE GPIO_PinSource5
#define SPI_SCK_AF GPIO_AF_SPI1
#define SPI_MOSI_PIN GPIO_Pin_7
#define SPI_MOSI_GPIO_PORT GPIOA
#define SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOA
#define SPI_MOSI_SOURCE GPIO_PinSource7
#define SPI_MOSI_AF GPIO_AF_SPI1
#define SPI_PORT_DR_ADDRESS SPI_PORT->DR
#define SPI_PORT_DMA DMA2
#define SPI_PORT_DMAx_CLK RCC_AHB1Periph_DMA2
#define SPI_PORT_TX_DMA_CHANNEL DMA_Channel_3
#define SPI_PORT_TX_DMA_STREAM DMA2_Stream3
#define SPI_PORT_TX_DMA_FLAG_FEIF DMA_FLAG_FEIF3
#define SPI_PORT_TX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF3
#define SPI_PORT_TX_DMA_FLAG_TEIF DMA_FLAG_TEIF3
#define SPI_PORT_TX_DMA_FLAG_HTIF DMA_FLAG_HTIF3
#define SPI_PORT_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF3
#define SPI_PORT_DMA_TX_IRQn DMA2_Stream3_IRQn
#define SPI_PORT_DMA_TX_IRQHandler DMA2_Stream3_IRQHandler
uint8_t refresh_count; 
//tells the DMA updater to refresh the display
uint8_t spi_buf[16];
DMA_InitTypeDef DMA_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure2;
//*****************************************************
//* Name: initDMD
//* Purpose: 
//* In:
//* Out:
//*****************************************************
void
initDMD(
void
){
//******************* SPI *******************
// enable the SPI peripheral clock
SPI_PORT_CLOCK_INIT(SPI_PORT_CLOCK, ENABLE);
// enable the peripheral GPIO port clocks
RCC_AHB1PeriphClockCmd(SPI_SCK_GPIO_CLK | SPI_MOSI_GPIO_CLK, ENABLE);
// Connect SPI pins to AF5 - see section 3, Table 6 in the device data sheet
GPIO_PinAFConfig(SPI_SCK_GPIO_PORT, SPI_SCK_SOURCE, SPI_SCK_AF);
GPIO_PinAFConfig(SPI_MOSI_GPIO_PORT, SPI_MOSI_SOURCE, SPI_MOSI_AF);
// now configure the pins themselves
// they are all going to be fast push-pull outputs
// but the SPI pins use the alternate function
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN;
GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SPI_MOSI_PIN;
GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
// now we can set up the SPI peripheral
// Assume the target is write only and we look after the chip select ourselves
// SPI clock rate will be system frequency/4/prescaler
// so here we will go for 72/4/4 = 4.4mhz
SPI_I2S_DeInit(SPI_PORT);
SPI_StructInit(&SPI_InitStructure);
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_Init(SPI_PORT, &SPI_InitStructure);
// Enable the SPI port
SPI_Cmd(SPI_PORT, ENABLE);
//******************* DMA *******************
// first enable the clock
RCC_AHB1PeriphClockCmd(SPI_PORT_DMAx_CLK, ENABLE);
// start with a blank DMA configuration just to be sure
DMA_DeInit(SPI_PORT_TX_DMA_STREAM);
while
(DMA_GetCmdStatus (SPI_PORT_TX_DMA_STREAM) != DISABLE);
// Configure DMA controller to manage TX DMA requests for the HCMS display
// first make sure we are using the default values
DMA_StructInit (&DMA_InitStructure);
// these are the only parameters that change from the defaults
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (SPI_PORT->DR);
DMA_InitStructure.DMA_Channel = SPI_PORT_TX_DMA_CHANNEL;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*
* It 
is
not possible to call DMA_Init without values 
for
the source
* address and non-zero size even though a transfer 
is
not done here.
* These are 
checked
only when the assert_param macro 
is
active though.
*/
DMA_InitStructure.DMA_Memory0BaseAddr = 0;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_Init (SPI_PORT_TX_DMA_STREAM, &DMA_InitStructure);
// Enable the DMA transfer complete interrupt
DMA_ITConfig (SPI_PORT_TX_DMA_STREAM, DMA_IT_TC, ENABLE);
// enable the interrupt in the NVIC
NVIC_InitStructure.NVIC_IRQChannel = SPI_PORT_DMA_TX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
// Enable dma tx request.
SPI_I2S_DMACmd(SPI_PORT, SPI_I2S_DMAReq_Tx, ENABLE);
}
//*****************************************************
//* Name: SPI_PORT_DMA_TX_IRQHandler
//* Purpose: 
//* In:
//* Out:
//*****************************************************
void
SPI_PORT_DMA_TX_IRQHandler(){
// Test if DMA Stream Transfer Complete interrupt
if
(DMA_GetITStatus (SPI_PORT_TX_DMA_STREAM, DMA_IT_TCIF3)) {
DMA_ClearITPendingBit (SPI_PORT_TX_DMA_STREAM, DMA_IT_TCIF3);
// make sure spi dmd transfer is complete
//while (SPI_I2S_GetFlagStatus (SPI_PORT, SPI_I2S_FLAG_TXE) == RESET) {};
//while (SPI_I2S_GetFlagStatus (SPI_PORT, SPI_I2S_FLAG_BSY) == SET) {};
}
}
//*****************************************************
//* Name: updateDMD
//* Purpose: 
//* In:
//* Out:
//*****************************************************
void
updateDMD(uint8_t phase_){
// use SPI+DMA to shift out the 16 bytes per row
for
(i=0; i<16; i++)
spi_buf[i] = 0x00;
SPI_PORT_TX_DMA_STREAM->NDTR = (uint32_t) 16;
SPI_PORT_TX_DMA_STREAM->M0AR = (uint32_t) spi_buf;
DMA_Cmd(SPI_PORT_TX_DMA_STREAM, ENABLE);
}

neoirto
Associate II
Posted on October 30, 2012 at 14:30

Thanks a lot Pirie,

There is a lack of working example SPI+DMA on the net, so I believe it will help a lot. Unfortunately, I didn't succeed by inspiring from your code. I didn't noticed any IRQ on Tx channel, even with Rx channel disabled. One question : why do you change thos registers after initialization, and not during initialization ? Was it a bug fix ?

DMA2_Stream3->NDTR = (uint32_t) 16;
DMA2_Stream3->M0AR = (uint32_t) spi_buf;

DMA2_Stream3->NDTR is DMA_BufferSize?

DMA2_Stream3->M0AR is DMA_Memory0BaseAddr?

Is it possible it comes from theSPI_Direction_2Lines_FullDuplex ? Thanks again
neoirto
Associate II
Posted on October 30, 2012 at 16:39

Still debugging, I found this :

char
temp_string_3[512];
sprintf
(temp_string_3,
''REGISTERS DMA2_Stream0 %u %u %u

REGISTERS DMA2_Stream3 %u %u %u || %u

''
,
(unsigned 
int
)DMA2_Stream0->NDTR,
(unsigned 
int
)DMA2_Stream0->M0AR,
(unsigned 
int
)DMA2_Stream0->PAR,
(unsigned 
int
)DMA2_Stream3->NDTR,
(unsigned 
int
)DMA2_Stream3->M0AR,
(unsigned 
int
)DMA2_Stream3->PAR,
(unsigned 
int
)((SPI1->DR) )
);
USART_puts( USART1, temp_string_3);

Give this in console, before intialization and the same after !!!

REGISTERS DMA2_Stream0 0 0 0
REGISTERS DMA2_Stream3 0 0 0 || 104

With 104 which last value read() in poll mode with success. Any advice ?
frankfrank956
Associate III
Posted on October 30, 2012 at 17:50

I have only done TX but does this help?

http://www.micromouseonline.com/2012/03/11/adding-dma-to-the-spi-driver-with-the-stm32f4