AnsweredAssumed Answered

Adding DMA SPI in RX mode help :)

Question asked by yao.randy.001 on Sep 4, 2014
Latest reply on Sep 4, 2014 by prasad.balmukund
Hi all, I have two SPI buses running on the STM32F407(Discovery board). They both transmit fine in DMA mode. I want to add RX, so a few questions:

1. How to do this? Is it using NVIC interrupt? If anyone can give suggestion or have example it would be greatly appreciated.
2. For Slave select in DMA mode, how do you implement this? It's easy in polling mode, but how do you do it in DMA? Also, if there's only one chip for each SPI channel, is it theoretically OK to just tie them both to GND?

Here's my working SPI1, SPI2, DMA_TX:

//Two channels SPI_DMA Mode working 09/03/2014
//PB13 SPI2_SCK
//PB14 SPI2_MISO
//PB15 SPI2_MOSI
//PA4 SPI1_NSS
//PA5 SPI1_SCK
//PA6 SPI1_MISO
//PA7 SPI1_MOSI
//Both SCLK frequencies ~60KHz


#include <stm32f4xx_gpio.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_dma.h>
#include <stm32f4xx_spi.h>
#include <semihosting.h>


void Setup(void);


char SPI_Buffer[] = "AAAA";
char SPI2_Buffer[] = "A000";


int main(void)
{
     Setup();
    while(1)
    {
    }
}


void Setup(void)
{
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE);


     GPIO_InitTypeDef GPIO_InitStructure;
     SPI_InitTypeDef SPI_InitStructure;
     DMA_InitTypeDef DMA_InitStructure;


     //PB13 SPI2_SCK
     //PB14 SPI2_MISO
     //PB15 SPI2_MOSI
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB,&GPIO_InitStructure);


     GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
     GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);
     GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);


     //Slave Select PC10
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_Init(GPIOC,&GPIO_InitStructure);


     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //Should be Full Duplex
     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
     SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;         //SCK idle high
     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;       //Second transition
     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;              //SPI_BaudRatePrescaler
     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //SPI_CRCPolynomial
     SPI_Init(SPI2, &SPI_InitStructure);
     SPI_Cmd(SPI2, ENABLE);


     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOA,&GPIO_InitStructure);


     GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_SPI1); //PA4 SPI1_NSS
     GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1); //PA5 SPI1_SCK
     GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1); //PA6 SPI1_MISO
     GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1); //PA7 SPI1_MOSI


     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //Should be Full Duplex
     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
     SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;         //SCK idle high
     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;       //Second transition
     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;              //SPI_BaudRatePrescaler
     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //SPI_CRCPolynomial
     SPI_Init(SPI1, &SPI_InitStructure);
     SPI_Cmd(SPI1, ENABLE);


     //DMA1 setup for SPI2
     //DMA1_Channel4_Stream0
     DMA_DeInit(DMA1_Stream4);
     DMA_InitStructure.DMA_Channel               = DMA_Channel_0;
     DMA_InitStructure.DMA_DIR                   = DMA_DIR_MemoryToPeripheral; //Transmit
     DMA_InitStructure.DMA_Memory0BaseAddr       = (uint32_t)SPI_Buffer;
     DMA_InitStructure.DMA_BufferSize            = (uint16_t)(sizeof(SPI_Buffer)-1);
     DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&SPI2->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_Circular;
     DMA_InitStructure.DMA_Priority              = DMA_Priority_VeryHigh;
     DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Enable;
     DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_1QuarterFull;
     DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;
     DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;


     SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
     DMA_Init(DMA1_Stream4,&DMA_InitStructure);
     DMA_Cmd(DMA1_Stream4,ENABLE);


     //DMA2 setup for SPI1 (DMA2_Channel3_Stream3)
     DMA_DeInit(DMA2_Stream3);
     DMA_InitStructure.DMA_Channel               = DMA_Channel_3;
     DMA_InitStructure.DMA_DIR                   = DMA_DIR_MemoryToPeripheral; //Transmit
     DMA_InitStructure.DMA_Memory0BaseAddr       = (uint32_t)SPI2_Buffer;
     DMA_InitStructure.DMA_BufferSize            = (uint16_t)(sizeof(SPI2_Buffer)-1);
     DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&SPI1->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_Circular;
     DMA_InitStructure.DMA_Priority              = DMA_Priority_VeryHigh;
     DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Enable;
     DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_1QuarterFull;
     DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;
     DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;


     //DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t)SPI_Buffer, DMA_Memory_0);
     //DMA_DoubleBufferModeCmd(DMA1_Stream4, ENABLE);
     SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
     DMA_Init(DMA2_Stream3,&DMA_InitStructure);
     DMA_Cmd(DMA2_Stream3,ENABLE);
}

Outcomes