Why is my DMA-controller not working with my SPI bus?
I'm working with the Discovery Development Board and I am trying to use the DMA-controller with my SPI-bus in order to support longer continuous transfers than 16 bits. I have assigned SPI1 as my master and SPI2 as my slave and connected wires in between and I have verified using a logic analyzer that my master is working properly. My slave, on the other hand, is not working properly. I get SPI2_IRQHandler-interrupts which containthe first 2 bytes (out of 4) in each transmission, but there are no signs of life at all from my DMA-controller. Any type of interrupt from the DMA-controller would be a step forward for me. One more thing, the line
__IO uint32_t DMA_S0CR;/*!< Some kind of DMA interrupt enable, Address offset: 0x10 */ was missing in the typedef struct of the DMA_TypeDef inmy stm32f407xx.h-file so I added that myself.Can anybody please help me make the DMA-controller work?void initializeSpi2controlPins(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/***************************************************
***************** SPI MISO ***********************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_2;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/***************************************************
***************** SPI MOSI ***********************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_3;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/***************************************************
***************** SPI CLK ************************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_10;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
/***************************************************
***************** SPI NSS ************************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void enableSpi2module(void)
{
SPI_HandleTypeDef hspi;
hspi.Instance = SPI2;
hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi.Init.Direction = SPI_DIRECTION_2LINES;
hspi.Init.Mode = SPI_MODE_SLAVE;
hspi.Init.DataSize = SPI_DATASIZE_16BIT;
hspi.Init.NSS = SPI_NSS_HARD_INPUT;
hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi.Init.TIMode = SPI_TIMODE_DISABLE;
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // Enable clock for SPI 2
SPI2->DR = 0x9876; // Load some data for the master to receive
if (HAL_SPI_Init(&hspi) != HAL_OK)
{
UART4_TransmitNullTerminatedString((uint8_t*)''\r\nSPI2. Initialization Error'');
UART4_WaitForTransmitToFinish();
}
__HAL_SPI_ENABLE(&hspi);
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // Enable clock for DMA1
__HAL_RCC_DMA1_CLK_ENABLE();
static DMA_HandleTypeDef hdma_tx;
static DMA_HandleTypeDef hdma_rx;
//SPI2_TX
//==Configure DMA1 - Channel0== (memory -> SPI)
hdma_tx.Instance = DMA1_Stream4;
hdma_tx.Init.Channel = DMA_CHANNEL_0;
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_tx.Init.MemInc = DMA_MINC_DISABLE;
hdma_tx.Init.Mode = DMA_CIRCULAR;
hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&hdma_tx);
/* Associate the initialized DMA handle to the the SPI handle */
__HAL_LINKDMA(&hspi, hdmatx, hdma_tx);
//SPI2_RX
//==Configure DMA1 - Channel0== (SPI -> memory)
hdma_rx.Instance = DMA1_Stream3;
hdma_rx.Init.Channel = DMA_CHANNEL_0;
hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
hdma_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_rx.Init.MemInc = DMA_MINC_DISABLE;
hdma_rx.Init.Mode = DMA_CIRCULAR;
hdma_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&hdma_rx);
/* Associate the initialized DMA handle to the the SPI handle */
__HAL_LINKDMA(&hspi, hdmarx, hdma_rx);
/* NVIC configuration for DMA transfer complete interrupt (SPI2_RX) */
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
HAL_NVIC_EnableIRQ(SPI2_IRQn); // Enable SPI bus interrupts
DMA1->DMA_S0CR|= 0x08; // HTIE
DMA1->DMA_S0CR|= 0x10; // TCIE
DMA1->DMA_S0CR|= 0x04; // TEIE
DMA1->DMA_S0CR|= 0x02; // DMEIE
SPI2->CR2 |= SPI_CR2_RXNEIE;
}
//Interrupt Service Routine for DMA1_channel3: when the slave finishes transmitting the data to the master
void DMA1_Stream3_IRQHandler(void)
{
UART4_TransmitNullTerminatedString((uint8_t*)''\r\nDMA1_Stream3_IRQHandler'');
UART4_WaitForTransmitToFinish();
}
void DMA1_Stream4_IRQHandler(void)
{
UART4_TransmitNullTerminatedString((uint8_t*)''\r\nDMA1_Stream4_IRQHandler'');
UART4_WaitForTransmitToFinish();
}
void SPI2_IRQHandler(void)
{
uint16_t receivedWord;
while( !(SPI2->SR & SPI_SR_TXE) ); // Wait until transmit complete
while( !(SPI2->SR & SPI_SR_RXNE) ); // Wait until receive complete
while( SPI2->SR & SPI_SR_BSY ); // Wait until SPI is not busy anymore
receivedWord = SPI2->DR; // Return received data from SPI data register
UART4_TransmitNullTerminatedString((uint8_t*)''\r\nSPI2_IRQHandler. Received the following: 0x'');
UART4_TransmitHexNumberAsASCII((uint32_t)receivedWord);
UART4_WaitForTransmitToFinish();
}
#no-hablo-hal