Am using STM32F4 discovery board and I am attempting to get SPI loopback with DMA. I have succesfully get an "SPI-only" loopback running, but now i want use DMA in addition with the SPI, here are the functions am using:
Initialisation of SPI [EDIT]
void init_SPI1(void){
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct ;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5|GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// connect SPI1 pins to SPI alternate function
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
//Set chip select high
GPIOA->BSRRL |= GPIO_Pin_4; // set PA4 high
// enable SPI1 peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/* configure SPI1 in Mode 0
* CPOL = 0 --> clock is low when idle
* CPHA = 0 --> data is sampled at the first edge*/
SPI_StructInit(&SPI_InitStruct); // set default settings
SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // transmit in master mode, NSS pin has to be always high
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; // clock is low when idle
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // data sampled at first edge
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft ; // set the NSS management to internal and pull internal NSS high
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
SPI_Init(SPI1, &SPI_InitStruct);
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
return;
}
Configuration of DMA [EDIT]:
void DMA_Config()
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2);
DMA_Cmd(DMA2_Stream5, DISABLE);
while (DMA2_Stream5->CR & DMA_SxCR_EN);
DMA_DeInit(DMA2_Stream5);
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI1->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &spiTxBuff;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = SPI_TX_MAX;
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_Init(DMA2_Stream5, &DMA_InitStructure);
/**
configuration of the interrupts of DMA
******************************************************/
DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
return;
}
SPI Write function:
void SPI1_Write(uint8_t *txBuff,int length,tSPI_Callback fct)
{
DMA2_Stream5->M0AR = (uint32_t) &spiTxBuff;
DMA_Cmd(DMA2_Stream5, ENABLE);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_Cmd(SPI1, ENABLE);
}
The data received are writen in the Rx Buffer using spi interrupt handler.
void SPI1_IRQHandler()
{
spiRxBuff[spiRxCount] = SPI_I2S_ReceiveData(SPI1);
spiRxCount++;
}
am calling these functions in the main as follow :
main.c:
DMA_Config();
init_SPI1();
SPI1_Write(spiTxBuff,SPI_TX_MAX,(void*)0);
Using a debugger i found that ,in the DMA high interrupt status register, TCIF5(Transfer Complete Flag) and HTIF5(Half Transfer complete Flag) are set to 1 means that transfer is done successfully in my opinion, however i didn't get any data in the SPI Rx Buffer, the second strange thing is that neither DMA Interrupt nor SPI Interrupt is triggered. Could you please help me figure out what is wrong in my code.
EDIT
The DMA and SPI interrupts are triggered but the problem am getting now is that i can't receive all the elements, i can just receive the first one
uint8_t spiTxBuff[SPI_TX_MAX] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10};
but spiRxBuff[SPI_RX_MAX] ={0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
Did that problem come from the fact that DMA is faster than the interrupt handler and so SPI interrupt handler didn't have the time to handle all the received data ?
DMA1
in your code. Should that beDMA2
? – kkrambo