2016-02-04 09:24 AM
How to use DMA with SPI? Im trying to send image from SDRAM via SPI to LCD on STM32F429i-disco board:
void LCD_ILI9341_SendImageFrame(uint8_t* data) { ILI9341_WRX_SET; ILI9341_CS_RESET; HAL_SPI_Transmit_DMA(&lcd_spi, data, (uint16_t)320*240*2); } void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { lcd_refreshed = true; ILI9341_CS_SET; } ... while (1) { if(lcd_refreshed == true) { LCD_ILI9341_SendImageFrame((uint8_t*)SDRAM_BANK_ADDR); lcd_refreshed = false; } } It displays part of the data (~ 1/6) and then triggers FIFO error in HAL_DMA_IRQHandler function: /* FIFO Error Interrupt management ******************************************/ if ((regs->ISR & (DMA_FLAG_FEIF0_4 << hdma->StreamIndex)) != RESET) { if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != RESET) { /* Disable the FIFO Error interrupt */ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_FE); /* Clear the FIFO error flag */ regs->IFCR = DMA_FLAG_FEIF0_4 << hdma->StreamIndex; /* Update error code */ hdma->ErrorCode |= HAL_DMA_ERROR_FE; /* Change the DMA state */ hdma->State = HAL_DMA_STATE_ERROR; /* Process Unlocked */ __HAL_UNLOCK(hdma); if(hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } If I change transmit dma size to less than 65530, it displays whole size, but still triggers FIFO error. Its all ok without using DMA: void LCD_ILI9341_SendImageFrame(uint8_t* data) { ILI9341_WRX_SET; ILI9341_CS_RESET; HAL_SPI_Transmit(&lcd_spi, data, ILI9341_SPI_IMAGE_BLOCK, 5000); ILI9341_CS_SET; } P.S. It does not depend on the value of hdma_spi5_tx.Init.FIFOMode, disabled fifo still triggers error. SPI DMA initialization function: void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_InitStruct; if(hspi->Instance==SPI5) { /* USER CODE BEGIN SPI5_MspInit 0 */ /* USER CODE END SPI5_MspInit 0 */ /* Peripheral clock enable */ __SPI5_CLK_ENABLE(); /**SPI5 GPIO Configuration PF7 ------> SPI5_SCK PF8 ------> SPI5_MISO PF9 ------> SPI5_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI5; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); /* Peripheral DMA init*/ hdma_spi5_tx.Instance = DMA2_Stream4; hdma_spi5_tx.Init.Channel = DMA_CHANNEL_2; hdma_spi5_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_spi5_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi5_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi5_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_spi5_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_spi5_tx.Init.Mode = DMA_NORMAL; hdma_spi5_tx.Init.Priority = DMA_PRIORITY_MEDIUM; hdma_spi5_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_spi5_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_spi5_tx.Init.MemBurst = DMA_MBURST_SINGLE; hdma_spi5_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; HAL_DMA_Init(&hdma_spi5_tx); __HAL_LINKDMA(hspi,hdmatx,hdma_spi5_tx); /* USER CODE BEGIN SPI5_MspInit 1 */ /* USER CODE END SPI5_MspInit 1 */ } } #stm32f4 #dma #discovery #spi2016-02-04 08:24 PM
Understanding how the peripherals are configured at a register level, without the obscuration of the HAL rubbish, would be very useful when working out what’s going wrong.
Can you post the contents of the DMA2 registers just before the transaction starts, i.e.
DMA2->HISR, S4CR, S4NDTR, S4PAR, S4M0AR, S4FCR?Perhaps also the SPI5 registers, i.e. SPI5->CR1, CR2, SR?
The transaction is probably being triggered by setting one or the other of DMA2->S4CR.EN or SPI5->CR2.TXDMAEN. There should be code to that effect somewhere in the function call that starts the transaction.
2016-02-06 02:50 AM
I have added disabling of DMA_IT_FE (
FIFO error interrupt mask
) before calling interrupt handler and it works now, lcd fps changed from 11 to 28. void DMA2_Stream4_IRQHandler(void) { /* USER CODE BEGIN DMA2_Stream4_IRQn 0 */ hdma_spi5_tx.Instance->FCR &= ~DMA_IT_FE; /* USER CODE END DMA2_Stream4_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_spi5_tx); /* USER CODE BEGIN DMA2_Stream4_IRQn 1 */ /* USER CODE END DMA2_Stream4_IRQn 1 */ }