cancel
Showing results for 
Search instead for 
Did you mean: 

How to avoid unnecessary clocks when receiving data (simplex) from SPI with DMA?

Jan1
Associate II

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();
}

1 ACCEPTED SOLUTION

Accepted Solutions

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.

0690X000009XgB3QAK.png

JW

View solution in original post

2 REPLIES 2

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.

0690X000009XgB3QAK.png

JW

Jan1
Associate II

It works! I had missed that.