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
neoirto
Associate II
Posted on October 30, 2012 at 19:35

Yes Peter, it helped...

Get it working, I believe it's ok. I'll do some complete tests tomorrow, and will post good config, because it's a big mess at the moment...

Tx all !
neoirto
Associate II
Posted on October 31, 2012 at 12:06

Ok, so this config works :

#define NBR_BYTES 14
unsigned 
char
SPI_MASTER_Buffer_Tx[NBR_BYTES] = { 0, 0,0,0,0,0,0, 0,0,0,0,0,0 ,0, 0, 0 };
unsigned 
char
SPI_MASTER_Buffer_Rx[NBR_BYTES+1] = { 99, 99,99,99,99,99,99, 99,99,99,99,99,99 ,99, 99, 99};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_DeInit (DMA2_Stream3);
/*
* Check if the DMA Stream is disabled before enabling it.
* Note that this step is useful when the same Stream is used multiple times:
* enabled, then disabled then re-enabled... In this case, the DMA Stream disable
* will be effective only at the end of the ongoing data transfer and it will
* not be possible to re-configure it before making sure that the Enable bit
* has been cleared by hardware. If the Stream is used only once, this step might
* be bypassed.
*/
while
(DMA_GetCmdStatus (DMA2_Stream3) != DISABLE);
DMA_StructInit (&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (SPI1->DR);
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralInc = 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_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&SPI_MASTER_Buffer_Tx;
DMA_InitStructure.DMA_BufferSize = NBR_BYTES;
DMA_Init (DMA2_Stream3, &DMA_InitStructure);
// Enable dma tx request.
SPI_I2S_DMACmd (SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
///////////////////////////////
//////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
///////////////////////////////
DMA_InitTypeDef DMA_InitStructure_RX;
NVIC_InitTypeDef NVIC_InitStructure_RX;
DMA_DeInit (DMA2_Stream0);
/*
* Check if the DMA Stream is disabled before enabling it.
* Note that this step is useful when the same Stream is used multiple times:
* enabled, then disabled then re-enabled... In this case, the DMA Stream disable
* will be effective only at the end of the ongoing data transfer and it will
* not be possible to re-configure it before making sure that the Enable bit
* has been cleared by hardware. If the Stream is used only once, this step might
* be bypassed.
*/
while
(DMA_GetCmdStatus (DMA2_Stream0) != DISABLE);
DMA_StructInit (&DMA_InitStructure_RX);
DMA_InitStructure_RX.DMA_PeripheralBaseAddr = (uint32_t) & (SPI1->DR);
DMA_InitStructure_RX.DMA_Channel = DMA_Channel_3;
DMA_InitStructure_RX.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure_RX.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure_RX.DMA_PeripheralInc = DMA_MemoryInc_Enable;
DMA_InitStructure_RX.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure_RX.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 
/// DMA_MemoryDataSize_Byte;
DMA_InitStructure_RX.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure_RX.DMA_Priority = DMA_Priority_High;
DMA_InitStructure_RX.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure_RX.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure_RX.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure_RX.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure_RX.DMA_Memory0BaseAddr = (uint32_t)&SPI_MASTER_Buffer_Rx; 
/// (uint32_t)&SPI_MASTER_Buffer_Rx->preamble;
DMA_InitStructure_RX.DMA_BufferSize = (NBR_BYTES+1);
DMA_Init (DMA2_Stream0, &DMA_InitStructure_RX);
///////////// INTERRUPTIONS
DMA_ITConfig (DMA2_Stream0, DMA_IT_TC, ENABLE); 
// Transfer complete interrupt mask
// DMA_ITConfig (DMA2_Stream0, DMA_IT_HT, ENABLE); // Half transfer complete interrupt mask
// DMA_ITConfig (DMA2_Stream0, DMA_IT_TE, ENABLE); // Transfer error interrupt mask
// DMA_ITConfig (DMA2_Stream0, DMA_IT_FE, ENABLE); // FIFO error interrupt mask
NVIC_InitStructure_RX.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure_RX.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure_RX.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure_RX.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure_RX);
// Enable dma tx request.
SPI_I2S_DMACmd (SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
while
(1)
{ 
delay_us(10);
GPIO_SetBits(GPIOC, GPIO_Pin_4); 
///// toggle PC4 = GPIO_EXT1
DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF3);
GPIO_ResetBits(GPIOB, GPIO_Pin_0); 
///// Low CS 
//////// engage transfer in poll
while
(SPI1->SR & SPI_SR_TXE == 0); 
// wait for empty TX buffer 
SPI1->DR = (ADDRESS_READ); 
//////////////// ENABLE DMA transfer Mode Normal : cad one shot / stop
DMA_Cmd(DMA2_Stream0, ENABLE); 
/// RX
DMA_Cmd(DMA2_Stream3, ENABLE); 
/// TX
///////// you can test during transfer :
// uint16_t Data_received_nbr = DMA_GetCurrDataCounter(DMA2_Stream0);
GPIO_ResetBits(GPIOB, GPIO_Pin_15); 
///// allume LED BLEU
uint16_t Idle_cpteur = 0;
while
(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF3)){ 
/// RX
// while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0)){ /// TX
Idle_cpteur++;
}
GPIO_SetBits(GPIOB, GPIO_Pin_0); 
///// HIGH CS 
//////////////// DISABLE DMA transfer Mode Normal : cad one shot / stop
DMA_Cmd(DMA2_Stream0, DISABLE); 
/// RX
DMA_Cmd(DMA2_Stream3, DISABLE); 
/// TX
GPIO_SetBits(GPIOB, GPIO_Pin_15); 
///// eteinds LED BLEU
GPIO_ResetBits(GPIOC, GPIO_Pin_4); 
///// toggle PC4 = GPIO_EXT1
}
}
void
DMA2_Stream0_IRQHandler(){ 
//////////// RECEPTION SPI1
if
(DMA_GetITStatus (DMA2_Stream0, DMA_IT_TCIF0)) { 
/// RX complete
DMA_ClearITPendingBit (DMA2_Stream0, DMA_IT_TCIF0);
// make sure spi dmd transfer is complete
//while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == SET) {};
//while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_BSY) == SET) {};
}
}