I am using F411RE Nucleo board to communicate with some other devices through SPI.
My code is based on SPI LL example SPI_TwoBoards_FullDuplex_DMA in package STM32Cube_FW_F4_V1.26.0.
The original code works well. However, my app needs more than one SPI; so I tried to change SPI1 to SPI4.
The DMA and SPI configurations are showed in below:
/** * @brief This function configures the DMA Channels for SPI1 * @note This function is used to : * -1- Enable DMA2 clock * -2- Configure NVIC for DMA2 transfer complete/error interrupts * -3- Configure the DMA2_Stream2 functional parameters * -4- Configure the DMA2_Stream3 functional parameters * -5- Enable DMA2 interrupts complete/error * @param None * @retval None */ void Configure_DMA(void) { /* DMA2 used for SPI1 Transmission * DMA2 used for SPI1 Reception */ /* (1) Enable the clock of DMA2 and DMA2 */ LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2); /* (2) Configure NVIC for DMA transfer complete/error interrupts */ #ifdef USE_SPI1 NVIC_SetPriority(DMA2_Stream2_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream2_IRQn); NVIC_SetPriority(DMA2_Stream3_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream3_IRQn); #endif #ifdef USE_SPI4 NVIC_SetPriority(DMA2_Stream0_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream0_IRQn); NVIC_SetPriority(DMA2_Stream1_IRQn, 0); NVIC_EnableIRQ(DMA2_Stream1_IRQn); #endif /* (3) Configure the DMA2_Stream2 functional parameters */ LL_DMA_ConfigTransfer(DMA2, SPI_RX_STREAM, LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE); LL_DMA_ConfigAddresses(DMA2, SPI_RX_STREAM, LL_SPI_DMA_GetRegAddr(SPI), (uint32_t)aRxBuffer, LL_DMA_GetDataTransferDirection(DMA2, SPI_RX_STREAM)); LL_DMA_SetDataLength(DMA2, SPI_RX_STREAM, ubNbDataToReceive); LL_DMA_SetChannelSelection(DMA2, SPI_RX_STREAM, SPI_RX_CHANNEL); /* (4) Configure the DMA2_Stream3 functional parameters */ LL_DMA_ConfigTransfer(DMA2, SPI_TX_STREAM, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE); LL_DMA_ConfigAddresses(DMA2, SPI_TX_STREAM, (uint32_t)aTxBuffer, LL_SPI_DMA_GetRegAddr(SPI), LL_DMA_GetDataTransferDirection(DMA2, SPI_TX_STREAM)); LL_DMA_SetDataLength(DMA2, SPI_TX_STREAM, ubNbDataToTransmit); LL_DMA_SetChannelSelection(DMA2, SPI_TX_STREAM, SPI_TX_CHANNEL); /* (5) Enable DMA interrupts complete/error */ LL_DMA_EnableIT_TC(DMA2, SPI_RX_STREAM); LL_DMA_EnableIT_TE(DMA2, SPI_RX_STREAM); LL_DMA_EnableIT_TC(DMA2, SPI_TX_STREAM); LL_DMA_EnableIT_TE(DMA2, SPI_TX_STREAM); } /** * @brief This function configures SPI1. * @note This function is used to : * -1- Enables GPIO clock and configures the SPI1 pins. * -2- Configure SPI1 functional parameters. * @note Peripheral configuration is minimal configuration from reset values. * Thus, some useless LL unitary functions calls below are provided as * commented examples - setting is default configuration from reset. * @param None * @retval None */ void Configure_SPI(void) { /* (1) Enables GPIO clock and configures the SPI1 pins ********************/ /* Enable the peripheral clock of GPIOB */ if(! LL_AHB1_GRP1_IsEnabledClock(LL_AHB1_GRP1_PERIPH_GPIOB)) { LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB); } if(! LL_AHB1_GRP1_IsEnabledClock(LL_AHB1_GRP1_PERIPH_GPIOA)) { LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); } #ifdef USE_SPI1 /* Configure SCK Pin connected to pin 31 of CN10 connector */ LL_GPIO_SetPinMode(GPIOB, SPI_CLK_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOB, SPI_CLK_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOB, SPI_CLK_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_CLK_PIN, LL_GPIO_PULL_DOWN); /* Configure MISO Pin connected to pin 27 of CN10 connector */ LL_GPIO_SetPinMode(GPIOB, SPI_MISO_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOB, SPI_MISO_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOB, SPI_MISO_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_MISO_PIN, LL_GPIO_PULL_DOWN); /* Configure MOSI Pin connected to pin 29 of CN7 connector */ LL_GPIO_SetPinMode(GPIOB, SPI_MOSI_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOB, SPI_MOSI_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOB, SPI_MOSI_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_MOSI_PIN, LL_GPIO_PULL_DOWN); /* (2) Configure SPI1 functional parameters ********************************/ /* Enable the peripheral clock of GPIOB */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); #endif #ifdef USE_SPI4 /* Configure SCK Pin PB13 */ LL_GPIO_SetPinMode(GPIOB, SPI_CLK_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_8_15(GPIOB, SPI_CLK_PIN, LL_GPIO_AF_6); LL_GPIO_SetPinSpeed(GPIOB, SPI_CLK_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOB, SPI_CLK_PIN, LL_GPIO_PULL_DOWN); /* Configure MISO Pin PA11 */ LL_GPIO_SetPinMode(GPIOA, SPI_MISO_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_8_15(GPIOA, SPI_MISO_PIN, LL_GPIO_AF_6); LL_GPIO_SetPinSpeed(GPIOA, SPI_MISO_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOA, SPI_MISO_PIN, LL_GPIO_PULL_DOWN); /* Configure MOSI Pin PA1 */ LL_GPIO_SetPinMode(GPIOA, SPI_MOSI_PIN, LL_GPIO_MODE_ALTERNATE); LL_GPIO_SetAFPin_0_7(GPIOA, SPI_MOSI_PIN, LL_GPIO_AF_5); LL_GPIO_SetPinSpeed(GPIOA, SPI_MOSI_PIN, LL_GPIO_SPEED_FREQ_HIGH); LL_GPIO_SetPinPull(GPIOA, SPI_MOSI_PIN, LL_GPIO_PULL_DOWN); /* (2) Configure SPI4 functional parameters ********************************/ /* Enable the peripheral clock of GPIOB */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI4); #endif /* Configure SPI1 communication */ LL_SPI_SetBaudRatePrescaler(SPI, LL_SPI_BAUDRATEPRESCALER_DIV8); LL_SPI_SetTransferDirection(SPI, LL_SPI_FULL_DUPLEX); LL_SPI_SetClockPhase(SPI, LL_SPI_PHASE_1EDGE); LL_SPI_SetClockPolarity(SPI, LL_SPI_POLARITY_LOW); /* Reset value is LL_SPI_MSB_FIRST */ LL_SPI_SetTransferBitOrder(SPI, LL_SPI_MSB_FIRST); LL_SPI_SetDataWidth(SPI, LL_SPI_DATAWIDTH_8BIT); LL_SPI_SetNSSMode(SPI, LL_SPI_NSS_SOFT); #ifdef MASTER_BOARD LL_SPI_SetMode(SPI, LL_SPI_MODE_MASTER); #else /* Reset value is LL_SPI_MODE_SLAVE */ //LL_SPI_SetMode(SPI, LL_SPI_MODE_SLAVE); #endif /* MASTER_BOARD */ /* Configure SPI1 DMA transfer interrupts */ /* Enable DMA RX Interrupt */ LL_SPI_EnableDMAReq_RX(SPI); /* Enable DMA TX Interrupt */ LL_SPI_EnableDMAReq_TX(SPI); }
Some of the macro definitions are showed here:
//#define USE_SPI1 #define USE_SPI4 #ifdef USE_SPI1 #define SPI SPI1 #define SPI_RX_STREAM LL_DMA_STREAM_2 #define SPI_RX_CHANNEL LL_DMA_CHANNEL_3 #define SPI_TX_STREAM LL_DMA_STREAM_3 #define SPI_TX_CHANNEL LL_DMA_CHANNEL_3 #define SPI_CLK_PIN LL_GPIO_PIN_3 #define SPI_MOSI_PIN LL_GPIO_PIN_5 #define SPI_MISO_PIN LL_GPIO_PIN_4 #endif #ifdef USE_SPI4 #define SPI SPI4 #define SPI_RX_STREAM LL_DMA_STREAM_0 #define SPI_RX_CHANNEL LL_DMA_CHANNEL_4 #define SPI_TX_STREAM LL_DMA_STREAM_1 #define SPI_TX_CHANNEL LL_DMA_CHANNEL_4 #define SPI_CLK_PIN LL_GPIO_PIN_13 #define SPI_MOSI_PIN LL_GPIO_PIN_1 #define SPI_MISO_PIN LL_GPIO_PIN_11 #endif
The whole project works well when I enable SPI1, but does not work when SPI4 is enabled (SPI1 disabled). The problem is that I cannot see any signal on CLK, MISO, and MOSI pins.
Thx. Where is the tutorial?