Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
8 years, 11 months ago.
How to use spi with DMA in STM32F401RE NUCLEO?
Hi. I want to use DMA for spi in STM32F401RE NUCLEO board.
I tried as follows. SPISlave spi_slave(SPI_MOSI, SPI_MISO, SPI_SCK, NC);
It is slow to transmit and receive by using SPISlave class, so i want to use HAL Drivers.
I tried as follows, but it is not generated SPI CLK signal.
/*############################### SPI1 #######################################*/ #define NUCLEO_SPIx SPI1 #define NUCLEO_SPIx_CLK_ENABLE() __SPI1_CLK_ENABLE() #define NUCLEO_SPIx_SCK_AF GPIO_AF5_SPI1 #define NUCLEO_SPIx_SCK_GPIO_PORT GPIOA #define NUCLEO_SPIx_SCK_PIN GPIO_PIN_5 #define NUCLEO_SPIx_SCK_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE() #define NUCLEO_SPIx_SCK_GPIO_CLK_DISABLE() __GPIOA_CLK_DISABLE() #define NUCLEO_SPIx_MISO_MOSI_AF GPIO_AF5_SPI1 #define NUCLEO_SPIx_MISO_MOSI_GPIO_PORT GPIOA #define NUCLEO_SPIx_MISO_MOSI_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE() #define NUCLEO_SPIx_MISO_MOSI_GPIO_CLK_DISABLE() __GPIOA_CLK_DISABLE() #define NUCLEO_SPIx_MISO_PIN GPIO_PIN_6 #define NUCLEO_SPIx_MOSI_PIN GPIO_PIN_7 #endif /** @defgroup STM32F4XX_NUCLEO_LOW_LEVEL_Private_FunctionPrototypes * @{ */ static void SPIx_Init(void); static void SPIx_Write_DMA(uint8_t Value); static uint32_t SPIx_Read_DMA(void); static void SPIx_Error_DMA(void); static void SPIx_MspInit(SPI_HandleTypeDef *hspi); static void DMA_MspInit(SPI_HandleTypeDef *hspi); /****************************************************************************** BUS OPERATIONS *******************************************************************************/ #define NUCLEO_DMAx_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE() /* Definition for SPIx's DMA */ #define NUCLEO_SPIx_TX_DMA_CHANNEL DMA_CHANNEL_0 #define NUCLEO_SPIx_TX_DMA_STREAM DMA1_Stream4 #define NUCLEO_SPIx_RX_DMA_CHANNEL DMA_CHANNEL_0 #define NUCLEO_SPIx_RX_DMA_STREAM DMA1_Stream3 /* Definition for SPIx's NVIC */ #define NUCLEO_SPIx_DMA_TX_IRQn DMA1_Stream4_IRQn #define NUCLEO_SPIx_DMA_RX_IRQn DMA1_Stream3_IRQn #define NUCLEO_SPIx_DMA_TX_IRQHandler DMA1_Stream4_IRQHandler #define NUCLEO_SPIx_DMA_RX_IRQHandler DMA1_Stream3_IRQHandler #define NUCLEO_SPIx_FORCE_RESET() __HAL_RCC_SPI1_FORCE_RESET() #define NUCLEO_SPIx_RELEASE_RESET() __HAL_RCC_SPI1_RELEASE_RESET() #endif /** * @brief SPI MSP Initialization * This function configures the hardware resources used in this example: * - Peripheral's clock enable * - Peripheral's GPIO Configuration * - DMA configuration for transmission request by peripheral * - NVIC configuration for DMA interrupt request enable * @param hspi: SPI handle pointer * @retval None */ void DMA_MspInit(SPI_HandleTypeDef *hspi) { static DMA_HandleTypeDef hdma_tx; static DMA_HandleTypeDef hdma_rx; NUCLEO_DMAx_CLK_ENABLE(); /*##-3- Configure the DMA streams ##########################################*/ /* Configure the DMA handler for Transmission process */ hdma_tx.Instance = NUCLEO_SPIx_TX_DMA_STREAM; hdma_tx.Init.Channel = NUCLEO_SPIx_TX_DMA_CHANNEL; hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_tx.Init.Mode = DMA_NORMAL; hdma_tx.Init.Priority = DMA_PRIORITY_LOW; hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx.Init.MemBurst = DMA_MBURST_INC4; hdma_tx.Init.PeriphBurst = DMA_PBURST_INC4; HAL_DMA_Init(&hdma_tx); /* Associate the initialized DMA handle to the the SPI handle */ __HAL_LINKDMA(hspi, hdmatx, hdma_tx); /* Configure the DMA handler for Transmission process */ hdma_rx.Instance = NUCLEO_SPIx_RX_DMA_STREAM; hdma_rx.Init.Channel = NUCLEO_SPIx_RX_DMA_CHANNEL; hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_rx.Init.Mode = DMA_NORMAL; hdma_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_rx.Init.MemBurst = DMA_MBURST_INC4; hdma_rx.Init.PeriphBurst = DMA_PBURST_INC4; HAL_DMA_Init(&hdma_rx); /* Associate the initialized DMA handle to the the SPI handle */ __HAL_LINKDMA(hspi, hdmarx, hdma_rx); /*##-4- Configure the NVIC for DMA #########################################*/ /* NVIC configuration for DMA transfer complete interrupt (SPI3_TX) */ HAL_NVIC_SetPriority(NUCLEO_SPIx_DMA_TX_IRQn, 0, 1); HAL_NVIC_EnableIRQ(NUCLEO_SPIx_DMA_TX_IRQn); /* NVIC configuration for DMA transfer complete interrupt (SPI3_RX) */ HAL_NVIC_SetPriority(NUCLEO_SPIx_DMA_RX_IRQn, 0, 0); HAL_NVIC_EnableIRQ(NUCLEO_SPIx_DMA_RX_IRQn); NUCLEO_DMAx_CLK_ENABLE(); } /** * @brief SPI MSP De-Initialization * This function frees the hardware resources used in this example: * - Disable the Peripheral's clock * - Revert GPIO, DMA and NVIC configuration to their default state * @param hspi: SPI handle pointer * @retval None */ void DMA_MspDeInit(SPI_HandleTypeDef *hspi) { static DMA_HandleTypeDef hdma_tx; static DMA_HandleTypeDef hdma_rx; /*##-3- Disable the DMA Streams ############################################*/ /* De-Initialize the DMA Stream associate to transmission process */ HAL_DMA_DeInit(&hdma_tx); /* De-Initialize the DMA Stream associate to reception process */ HAL_DMA_DeInit(&hdma_rx); /*##-4- Disable the NVIC for DMA ###########################################*/ HAL_NVIC_DisableIRQ(NUCLEO_SPIx_DMA_TX_IRQn); HAL_NVIC_DisableIRQ(NUCLEO_SPIx_DMA_RX_IRQn); } ////////////////////////////////////////////////////////////////////////////// /** * @brief Initializes SPI MSP. * @param None * @retval None */ static void SPIx_MspInit(SPI_HandleTypeDef *hspi) { GPIO_InitTypeDef GPIO_InitStruct; /*** Configure the GPIOs ***/ /* Enable GPIO clock */ NUCLEO_SPIx_SCK_GPIO_CLK_ENABLE(); NUCLEO_SPIx_MISO_MOSI_GPIO_CLK_ENABLE(); /* Configure SPI SCK */ GPIO_InitStruct.Pin = NUCLEO_SPIx_SCK_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = NUCLEO_SPIx_SCK_AF; HAL_GPIO_Init(NUCLEO_SPIx_SCK_GPIO_PORT, &GPIO_InitStruct); /* Configure SPI MISO and MOSI */ GPIO_InitStruct.Pin = NUCLEO_SPIx_MOSI_PIN; GPIO_InitStruct.Alternate = NUCLEO_SPIx_MISO_MOSI_AF; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(NUCLEO_SPIx_MISO_MOSI_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = NUCLEO_SPIx_MISO_PIN; HAL_GPIO_Init(NUCLEO_SPIx_MISO_MOSI_GPIO_PORT, &GPIO_InitStruct); /*** Configure the SPI peripheral ***/ /* Enable SPI clock */ NUCLEO_SPIx_CLK_ENABLE(); } /** * @brief Initializes SPI HAL. * @param None * @retval None */ static void SPIx_Init(void) { if(HAL_SPI_GetState(&hnucleo_Spi) == HAL_SPI_STATE_RESET) { /* SPI Config */ hnucleo_Spi.Instance = NUCLEO_SPIx; /* SPI baudrate is set to 12,5 MHz maximum (PCLK2/SPI_BaudRatePrescaler = 100/8 = 12,5 MHz) to verify these constraints: - ST7735 LCD SPI interface max baudrate is 15MHz for write and 6.66MHz for read Since the provided driver doesn't use read capability from LCD, only constraint on write baudrate is considered. - SD card SPI interface max baudrate is 25MHz for write/read - PCLK2 max frequency is 100 MHz */ hnucleo_Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hnucleo_Spi.Init.Direction = SPI_DIRECTION_2LINES; hnucleo_Spi.Init.CLKPhase = SPI_PHASE_2EDGE; hnucleo_Spi.Init.CLKPolarity = SPI_POLARITY_HIGH; hnucleo_Spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; hnucleo_Spi.Init.CRCPolynomial = 7; hnucleo_Spi.Init.DataSize = SPI_DATASIZE_8BIT; hnucleo_Spi.Init.FirstBit = SPI_FIRSTBIT_MSB; hnucleo_Spi.Init.NSS = SPI_NSS_SOFT; hnucleo_Spi.Init.TIMode = SPI_TIMODE_DISABLED; hnucleo_Spi.Init.Mode = SPI_MODE_MASTER; SPIx_MspInit(&hnucleo_Spi); HAL_SPI_Init(&hnucleo_Spi); DMA_MspInit(&hnucleo_Spi); } } void main(void) { uint8_t Value = 0xFF; int status ; SPIx_Init(); while((status = HAL_SPI_GetState(&hnucleo_Spi)) != HAL_SPI_STATE_READY) { printf("\n\r status = 0x%x \n\r", status); } status = HAL_SPI_Transmit_DMA(&hnucleo_Spi, (uint8_t*) &Value, 1); /* Check the communication status */ if(status == HAL_OK) { /* Execute user timeout callback */ printf("\n\r HAL_OK \n\r"); // SPIx_Error_DMA(); } while ((status = HAL_SPI_GetState(&hnucleo_Spi)) != HAL_SPI_STATE_READY) { printf("\n\r status = 0x%x \n\r", status); } }
Please help me. Thank you.
Assigned to
8 years, 11 months ago.This means that the question has been accepted and is being worked on.
Is it possible to speed up to 20MHz for SPISlave class as spi slave?
posted by Tian CR 09 Dec 2015I have the same problem.
posted by 王 秀杰 25 Mar 2016