Skip to main content
JShro
Associate III
Dec 30, 2019 4:50 PM UTC
Question

STM32H7 triggering a SPI TX transmission via DMA with a synch event on EXTI0

Hi All,

Looking at the STM32H7 Ref manual it seems the DMAMUX would allow for a DMA channel to be synchronized with an external event on the EXTI0 input.

I would like to use this capability to trigger an SPI transmission to an ADC (since this would allow me to avoid time consuming tasks in the ISR routines )

I figured I would be able to configure the SPI2 TX in DMA mode and enable the DMA request synchronization settings so I have the following configuration.

SPI2 TX is assigned to DMA1 Stream 0. and the DMA Request synchronization settings are setup for

Enable Synchronization

Synchronization signal EXTI0

SignalPolarity: Synchronize on falling edge

Request Number: 1

The SPI initialization is as follows

hdma_spi2_tx.Instance = DMA1_Stream0;
 hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;
 hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
 hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_spi2_tx.Init.MemInc = DMA_MINC_DISABLE;
 hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_spi2_tx.Init.Mode = DMA_CIRCULAR; //DMA_NORMAL;
 hdma_spi2_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
 hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
 {
 Error_Handler();
 }
 
 pSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_EXTI0;
 pSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_FALLING;
 pSyncConfig.SyncEnable = ENABLE;
 pSyncConfig.EventEnable = DISABLE;
 pSyncConfig.RequestNumber = 1;
 if (HAL_DMAEx_ConfigMuxSync(&hdma_spi2_tx, &pSyncConfig) != HAL_OK)
 {
 Error_Handler();
 }
 
 __HAL_LINKDMA(hspi,hdmatx,hdma_spi2_tx);

The EXTI input is configured as follows

GPIO_InitStruct.Pin = SPI2_EXTI_SYNC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN; //GPIO_NOPULL;
HAL_GPIO_Init(SPI2_EXTI_SYNC_GPIO_Port, &GPIO_InitStruct);

The EXTI input is PA0 and it is driven via a PWM signal from the High resolution timer output pin connected to PA0.

I have verified that I am getting a pulse every 1 us on the EXTI input - however the SPI DMA TX is not being triggered.

Any thoughts on if this is an appropriate way to achieve the desired outcome or am I missing something?

Thanks

Jay

This topic has been closed for replies.

20 replies

DMast.1
Associate III
Nov 26, 2020 5:51 PM UTC

Hi to all, I've implement the synchronization with LPTIM2 to generate ad 1MHz (50% duty) to generate the start conversion signal for AD converte. I was able to synchronize the spi transmission start with the falling edge of conversion start signal but sometimes doesn't get out from MOSI all 3 byte but only two or one.

Did somebody have this issue?

P.S.: the external ADC that I'm using is the LTC2335ILX-16.

Thanks in advance for any suggestion to exit from this situation that cause me spent a lot of time.

DMast.1
Associate III
Nov 27, 2020 5:58 PM UTC

Hi in addition to previus message, here is the initialization code of SPI and DMA:

 SpiHandle.Instance = SPI4;
 SpiHandle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; // Recommended setting to avoid glitches
 SpiHandle.Init.Mode = SPI_MODE_MASTER;
 
 SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; //SPI_BAUDRATEPRESCALER_128,
 SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
 
 SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
 SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
 
 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
 SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
 SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
 
 SpiHandle.Init.NSS = SPI_NSS_HARD_OUTPUT;
 SpiHandle.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
 SpiHandle.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
 
 SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 SpiHandle.Init.CRCPolynomial = 7;
 SpiHandle.Init.CRCLength = SPI_CRC_LENGTH_8BIT;
 
 SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
 
 if(HAL_SPI_Init(&SpiHandle) != HAL_OK)
 {
 // Initialization Error
 while(1){};
 }
 
 /*##-1- Enable peripherals and GPIO Clocks #################################*/
 SPI4_SCK_PORT_CLK_EN(); //PE2: SPI4_SCK
 SPI4_NSS_PORT_CLK_EN(); //PE4: SPI4_NSS
 SPI4_MISO_PORT_CLK_EN(); //PE5: SPI4_MISO
 SPI4_MOSI_PORT_CLK_EN(); //PE6: SPI4_MOSI
 SPI4_SCK_EN(); //Peripheral clock
 
 /*##-2- Configure peripheral GPIO ##########################################*/
 /* SPI SCK GPIO pin configuration */
 GPIO_InitStruct.Pin = SPI4_SCK_PIN;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 GPIO_InitStruct.Alternate = SPI4_SCK_AF;
 HAL_GPIO_Init(SPI4_SCK_GPIO_PORT, &GPIO_InitStruct);
 
 /* SPI NSS GPIO pin configuration */
 GPIO_InitStruct.Pin = SPI4_NSS_PIN;
 GPIO_InitStruct.Alternate = SPI4_NSS_AF;
 HAL_GPIO_Init(SPI4_NSS_GPIO_PORT, &GPIO_InitStruct);
 
 /* SPI MISO GPIO pin configuration */
 GPIO_InitStruct.Pin = SPI4_MISO_PIN;
 GPIO_InitStruct.Alternate = SPI4_MISO_AF;
 HAL_GPIO_Init(SPI4_MISO_GPIO_PORT, &GPIO_InitStruct);
 
 /* SPI MOSI GPIO pin configuration */
 GPIO_InitStruct.Pin = SPI4_MOSI_PIN;
 GPIO_InitStruct.Alternate = SPI4_MOSI_AF;
 HAL_GPIO_Init(SPI4_MOSI_GPIO_PORT, &GPIO_InitStruct);
 
 /*##-3- Configure the DMA ##################################################*/
 /* Enable DMA clock */
 DMA1_CLK_ENABLE();
 
 /* Configure the DMA handler for Transmission process */
 hdma_tx.Instance = SPIx_TX_DMA_STREAM;
 hdma_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;//>>DMA_FIFOMODE_DISABLE;
 hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
 hdma_tx.Init.MemBurst = DMA_MBURST_INC4;//>>DMA_MBURST_SINGLE;//>>DMA_MBURST_INC4;
 hdma_tx.Init.PeriphBurst = DMA_MBURST_INC4;//>>DMA_MBURST_SINGLE;//>>DMA_PBURST_INC4;
 hdma_tx.Init.Request = SPIx_TX_DMA_REQUEST;
 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_PFCTRL;//>>DMA_NORMAL;
 hdma_tx.Init.Priority = DMA_PRIORITY_LOW;
 
 HAL_DMA_Init(&hdma_tx);
 
 /* Configure the DMAMUX with the Synchronization parameters */
 DmaSyncConfig.EventEnable = ENABLE; /* Enable DMAMUX event generation each time RequestNumber are passed from DMAMUX to the DMA */
 DmaSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_FALLING; /* Synchronization edge is Rising */
 DmaSyncConfig.RequestNumber = 3;//3;//4; /* 4 requests are autorized after each edge of the sync signal */
 DmaSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_LPTIM2_OUT; /* Sync signal is LPTIM1_OUT */
 DmaSyncConfig.SyncEnable = ENABLE; /* Synchronization is enabled */
 
 HAL_DMAEx_ConfigMuxSync(&hdma_tx, &DmaSyncConfig);
 
 /* 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 = SPIx_RX_DMA_STREAM;
 
 hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
 hdma_rx.Init.MemBurst = DMA_MBURST_INC4;//>>DMA_MBURST_SINGLE;//>>DMA_MBURST_INC4;
 hdma_rx.Init.PeriphBurst = DMA_MBURST_INC4;//>>DMA_MBURST_SINGLE;//>>DMA_PBURST_INC4;
 hdma_rx.Init.Request = SPIx_RX_DMA_REQUEST;
 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_PFCTRL;//DMA_NORMAL;
 hdma_rx.Init.Priority = DMA_PRIORITY_HIGH;
 
 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 (SPIx_TX) */
 HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, 1, 1);
 HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn);
 
 /* NVIC configuration for DMA transfer complete interrupt (SPIx_RX) */
 HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, 1, 0);
 HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn);
 
 /*##-5- Configure the NVIC for SPI #########################################*/
 /* NVIC configuration for SPI transfer complete interrupt (SPIx) */
 HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
 HAL_NVIC_EnableIRQ(SPIx_IRQn);
 

And defined these interrupts definition

/**
 * @brief This function handles SPIx interrupt request.
 * @param None
 * @retval None
 */
void SPI4_IRQHandler(void)
{
 HAL_SPI_IRQHandler(&SpiHandle);
}
 
/**
 * @brief This function handles DMA Rx interrupt request.
 * @param None
 * @retval None
 */
void SPI4_DMA_RX_IRQHandler(void)
{
 HAL_DMA_IRQHandler(SpiHandle.hdmarx);
}
 
/**
 * @brief This function handles DMA Tx interrupt request.
 * @param None
 * @retval None
 */
void SPI4_DMA_TX_IRQHandler(void)
{
 HAL_DMA_IRQHandler(SpiHandle.hdmatx);
}

And use LPTIM2 to generate the ADC start conversion @1MHz and 50% duty and synchronize the SPI transmission start at LPTIM2 falling edge. At this moment I get only the first packet and there is no way to restart trasmission in LPTIM2 interrupt. I would litke that SPI data streaming with lpt synch continue till I stop the timer.

Any suggestion?

Thanks in advace to anybody who can help me.

DM

waclawek.jan
Super User
Nov 27, 2020 10:31 PM UTC

> I would like that SPI data streaming with lpt synch continue till I stop the timer.

Use circular DMA.

I don't use Cube and don't understand it. If you still need help with this, start a new thread, describing your problem and findings, perhaps with screenshots taken for the waveforms observed on LA. Read out and check/post of relevant timer, SPI, DMAMUX and DMA registers.

JW

fma23
Associate II
Feb 15, 2023 7:22 PM UTC

Would it be possible your share you basic code for DMAMUX SPI transfer. I am having issues using DMAMUX1 to work with LPTIM1 output to do an SP transfer.