AnsweredAssumed Answered

STM32f427 - SPI with DMA problem (HardFault)

Question asked by astier.maxence on Oct 19, 2015
Latest reply on Oct 19, 2015 by astier.maxence
Hello all,

I work with a STM32F427 and the HAL libraries, and i want tu use the SPI with DMA.

Configuration : The chip is in slave mode and receive datas from an ADC converter. The Clock and NSS are generated by two timers, and I can watch the datas on an scope.

PS : I tried to use the SPI in polling mode and it works fine.

So, here is my problem:

When I try tu use the SPI with DMA, several interruptions occure (I put an incrementing variable in the callback) and after that (kinda randomly) I have a HardFault.
After a long time of debugg and looking for solutions on forum and documentation I hope someone have a clue here.

I let here the part of my code concerning the DMA and SPI so, perhaps you can see something wrong:

Declarations:
SPI_HandleTypeDef  spi4Handle;
uint16_t buf_rx[6]; // SPI4

SPI Init :
void Start_SPI4()
{
          spi4Handle.Instance           = SPI4;
          spi4Handle.Init.BaudRatePrescaler     = 0;
          spi4Handle.Init.Direction             = SPI_DIRECTION_2LINES_RXONLY;
          spi4Handle.Init.CLKPhase              = SPI_PHASE_1EDGE;
          spi4Handle.Init.CLKPolarity           = SPI_POLARITY_HIGH;
          spi4Handle.Init.CRCCalculation        = SPI_CRCCALCULATION_DISABLE;
          spi4Handle.Init.CRCPolynomial         = 1;
          spi4Handle.Init.DataSize              = SPI_DATASIZE_16BIT;
          spi4Handle.Init.FirstBit              = SPI_FIRSTBIT_MSB;
          spi4Handle.Init.TIMode                = SPI_TIMODE_DISABLE;
          spi4Handle.Init.Mode          = SPI_MODE_SLAVE;
          spi4Handle.Init.NSS           = SPI_NSS_HARD_INPUT;
 
 
          if(HAL_SPI_Init(&spi4Handle) != HAL_OK)
          {
              Error_Handler();
          }
 
 
          if(HAL_SPI_Receive_DMA(&spi4Handle,(uint8_t*)buf_rx,buf_rx_size) != HAL_OK)
          {
              Error_Handler();
          }
 
  #ifdef DEBUG_USR
          trace_printf("\n SPI4 enabled");
  #endif
 
}

SPI MspInit & DMA Init:

void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI4) {
        GPIO_InitTypeDef GPIO_InitStruct;
 
        __HAL_RCC_SPI4_CLK_ENABLE();
        __GPIOE_CLK_ENABLE();
 
 
        DMA_HandleTypeDef hdma_rx;
        __HAL_RCC_DMA2_CLK_ENABLE();
 
 
        // SCK PIN
        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLDOWN;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
 
        HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
        // MOSI PIN
        GPIO_InitStruct.Pin = GPIO_PIN_6;
 
        HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
        // MISO PIN
        GPIO_InitStruct.Pin = GPIO_PIN_5;
 
        HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
        // NSS PIN
        GPIO_InitStruct.Pin = GPIO_PIN_4;
 
        HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
        // Configure the DMA handler for Transmission process
 
        hdma_rx.Instance = DMA2_Stream0;
        hdma_rx.Init.Channel = DMA_CHANNEL_4;
        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_HALFWORD;
        hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
        hdma_rx.Init.Mode = DMA_CIRCULAR;
        hdma_rx.Init.Priority = DMA_PRIORITY_HIGH;
        hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
        hdma_rx.Init.MemBurst = DMA_MBURST_SINGLE;
        hdma_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
 
        HAL_DMA_Init(&hdma_rx);
 
        // Associate the initalized DMA handle to the the SPI handle
        __HAL_LINKDMA(hspi, hdmarx, hdma_rx);
 
        // NVIC configuration for DMA transfer complete interrupt
        HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
    }
 
}

Callback:
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *spi)
{
    if(spi->Instance == SPI4)
    {
        voie1 = buf_rx[0];
        voie2 = buf_rx[1];
        voie3 = buf_rx[2];
        voie4 = buf_rx[3];
        voie5 = buf_rx[4];
        voie6 = buf_rx[5];
        if( (cpt++) > 10000 ) cpt = 0;  // Debug variable
    }
 
}

IRQHandler :

void DMA2_Stream0_IRQHandler(void)
{
 HAL_NVIC_ClearPending(DMA2_Stream0_IRQn);

 HAL_DMA_IRQHandler(spi4Handle.hdmarx);
}

Error Handler (Just to show that it does nothing):
void Error_Handler()
{
    //TODO
}


If it can be usefull I let you a screenshot of the Hard Fault :

[url=http://imgshare.free.fr/][img]http://imgshare.free.fr/uploads/cff65565a9.png[/img][/url]


Tell me if something is unclear or if you need more informations.

Thank you, and sorry for my English.

Maxence.

Outcomes