Skip to main content
JShro
Associate III
December 30, 2019
Question

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

  • December 30, 2019
  • 20 replies
  • 8117 views

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
November 26, 2020

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
November 27, 2020

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
November 27, 2020

> 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
February 15, 2023

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.