2018-09-19 10:03 AM
Hello. This is a question about possibilities of STM32F7 or STM32H7 MCU series.
I have a sensor connected to the SPI bus interface. I need to periodically poll it with more or less constant period (which is 250 us). Using any interrupts is forbidden.
The question is: does F7 or H7 hardware have the ability to trigger the DMA operation(s) (from/to SRAM to/from SPI peripheral) via the signal from the timer? If yes, what are the keywords to look for in the Reference Manual?
2018-09-19 10:26 AM
Yes, the TIM+DMA can occur without interrupts, the connectivity of the DMA trigger is an independent path. The RM should allow you to associate TIM UP, CC1..CC4 with specific DMA units, streams and channels.
Generating SPI traffic by using DMA to load a value into the SPI transmit registers, a secondary DMA can get triggered by an SPI RXNE signal to recover the data received.
2018-09-20 03:04 AM
Yes. Ofcourse, you can do as suggested by @Community member .
Giving you glimpse of DMAing SPI data based on TIMER. I am assuming that you already know basic. I would prefer that you first try it with UART rather than SPI. Transfer data to console on per second tick and this will give you confidence and eventually, you just need to replace UART with SPI. THE WORLD OF STM32 IS SIMPLY AWESOME !! :)
File: lptim.c
/* LPTIM1 init function */
void MX_LPTIM1_Init(void)
{
hlptim1.Instance = LPTIM1;
hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_ULPTIM;
hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1;
hlptim1.Init.UltraLowPowerClock.Polarity = LPTIM_CLOCKPOLARITY_RISING;
hlptim1.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION;
hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
hlptim1.Init.UpdateMode = LPTIM_UPDATE_ENDOFPERIOD;
hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_EXTERNAL;
hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;
hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;
if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_LPTIM_TimeOut_Start_IT(&hlptim1, 1000, 0) != HAL_OK)
{
Error_Handler();
}
}
File: SPI.c
/* SPI4 init function */
void MX_SPI4_Init(void)
{
hspi4.Instance = SPI4;
hspi4.Init.Mode = SPI_MODE_MASTER;
hspi4.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi4.Init.NSS = SPI_NSS_SOFT;
hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi4.Init.CRCPolynomial = 7;
hspi4.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi4.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi4.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
HAL_DMA_MuxSyncConfigTypeDef pSyncConfig;
if(spiHandle->Instance==SPI4)
{
/* USER CODE BEGIN SPI4_MspInit 0 */
/* USER CODE END SPI4_MspInit 0 */
/* SPI4 clock enable */
__HAL_RCC_SPI4_CLK_ENABLE();
/**SPI4 GPIO Configuration
PE2 ------> SPI4_SCK
PE14 ------> SPI4_MOSI
*/
GPIO_InitStruct.Pin = SPI4_CLK_Pin|SPI4_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* SPI4 DMA Init */
/* SPI4_TX Init */
hdma_spi4_tx.Instance = DMA1_Stream0;
hdma_spi4_tx.Init.Request = DMA_REQUEST_SPI4_TX;
hdma_spi4_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi4_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi4_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi4_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi4_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi4_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi4_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi4_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_spi4_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi4_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi4_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Init(&hdma_spi4_tx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
pSyncConfig.SyncSignalID = HAL_DMAMUX1_SYNC_LPTIM1_OUT;
pSyncConfig.SyncPolarity = HAL_DMAMUX_SYNC_RISING;
pSyncConfig.SyncEnable = ENABLE;
pSyncConfig.EventEnable = ENABLE;
pSyncConfig.RequestNumber = 5;
if (HAL_DMAEx_ConfigMuxSync(&hdma_spi4_tx, &pSyncConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(spiHandle,hdmatx,hdma_spi4_tx);
/* SPI4 interrupt Init */
HAL_NVIC_SetPriority(SPI4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI4_IRQn);
/* USER CODE BEGIN SPI4_MspInit 1 */
/* USER CODE END SPI4_MspInit 1 */
}
}
File: dma.c
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
/* DMAMUX1_OVR_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMAMUX1_OVR_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMAMUX1_OVR_IRQn);
}
File: stm32h7xx_it.c
/**
* @brief This function handles DMA1 stream0 global interrupt.
*/
void DMA1_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream0_IRQn 0 */
/* USER CODE END DMA1_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi4_tx);
/* USER CODE BEGIN DMA1_Stream0_IRQn 1 */
/* USER CODE END DMA1_Stream0_IRQn 1 */
}
/**
* @brief This function handles SPI4 global interrupt.
*/
void SPI4_IRQHandler(void)
{
/* USER CODE BEGIN SPI4_IRQn 0 */
/* USER CODE END SPI4_IRQn 0 */
HAL_SPI_IRQHandler(&hspi4);
/* USER CODE BEGIN SPI4_IRQn 1 */
/* USER CODE END SPI4_IRQn 1 */
}