2019-06-27 07:09 AM
STM32F746/Atollic
I want to receive periodically a certain number of bytes from an ADC via SPI using DMA.
Since there is no Tx line, I thought it would be correct to set the SPI at SPI_DIRECTION_2LINES_RXONLY and to program a DMA for Rx. I called this DMA with HAL_SPI_Receive_DMA(&hspi3, SplRxBuff, 33) and expected to receive 33 bytes in SplRxBuff.
My buffer actually receives the 33 bytes but the SPI generates additional clocks which I want to avoid.
In this forum I got the advice to use SPI_DIRECTION_2LINES instead of SPI_DIRECTION_2LINES_RXONLY and to add a Tx DMA even if there is no GPIO for Tx.
I tried to do this but I don't receive any data. What could be wrong?
Here the DMAS for Rx and Tx are set:
/*DMA 1 / channel 0 / stream 0 transfers data from external ADC to sample registers*/
__HAL_RCC_DMA1_CLK_ENABLE(); /*DMA clock*/
hdma_spi3_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; /*from SPI to memory*/
hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; /*no increment on SPI side*/
hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; /*increment sample memory address*/
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi3_rx.Init.Mode = DMA_NORMAL;
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi3_rx.Init.MemBurst = DMA_PBURST_SINGLE;
hdma_spi3_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_spi3_rx.Instance = DMA1_Stream0;
HAL_DMA_Init(&hdma_spi3_rx);
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); /*highest priority for DMA interrupt*/
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); /*enable DMA interrupt*/
__HAL_LINKDMA(hspi, hdmarx, hdma_spi3_rx); /*link DMA1 to SPI3 Rx*/
/*DMA 2 / channel 0 / stream 0 sends data to SPI (no GPIO pin existent, only needed for clocking in right number of bytes)*/
__HAL_RCC_DMA2_CLK_ENABLE(); /*DMA clock*/
hdma_spi3_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; /*from memory to SPI*/
hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE; /*no increment on SPI side*/
hdma_spi3_tx.Init.MemInc = DMA_MINC_DISABLE; /*no increment sample memory address*/
hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi3_tx.Init.Mode = DMA_NORMAL;
hdma_spi3_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi3_tx.Init.MemBurst = DMA_PBURST_SINGLE;
hdma_spi3_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_spi3_tx.Instance = DMA2_Stream0;
HAL_DMA_Init(&hdma_spi3_tx);
__HAL_LINKDMA(hspi, hdmatx, hdma_spi3_tx); /*link DMA2 to SPI3 Tx*/
The DMAs are called here:
/*Data ready interrupt (/ADC_/DRDY) of external ADCs*/
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); /*clear interrupt*/
HAL_SPI_Transmit_DMA(&hspi3, NULL, 33); /*send dummy bytes via SPI*/
HAL_SPI_Receive_DMA(&hspi3, SplRxBuff, 33); /*get ADC data*/
}
and the DMA interrupt is never reached:
/*DMA1 stream0 global interrupt (Rx of external ADCs complete)*/
void SPI_DMA_Rx_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi3_tx);
HAL_DMA_IRQHandler(&hdma_spi3_rx);
Sampling();
}
Solved! Go to Solution.
2019-06-27 10:16 PM
You can't pull DMA channel/stream numbers out of thin air, the DMA triggers in 'F7 are hardwired and Cube/HAL can't magically reassign them.
JW
2019-06-27 10:16 PM
You can't pull DMA channel/stream numbers out of thin air, the DMA triggers in 'F7 are hardwired and Cube/HAL can't magically reassign them.
JW
2019-06-28 12:39 AM
It works! I had missed that.