cancel
Showing results for 
Search instead for 
Did you mean: 

BUG: DMA Fatal Error - Ethernet in STM32F407 processor

DMårt
Lead

Hi!

Problem:

I found a bug when I enabling the ETH perpherial in the STM32F407 processor. The error is a DMA bus error.

What's happening:

It occurs when the ethernet PHY recieve a message from my router.

How to produce the error:

I do the following steps to reproduce the error.

  1. I start up my PCB board
  2. I let the initialization do its job and I get no error back.
  3. I plugin my ethernet cable
  4. I ping a random device with a random number

Then this call back function HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); will be called.

0693W00000LyBzOQAV.pngThe error code is a DMA error.

/** @defgroup ETH_Error_Code ETH Error Code
  * @{
  */
#define HAL_ETH_ERROR_NONE         ((uint32_t)0x00000000U)   /*!< No error            */
#define HAL_ETH_ERROR_PARAM        ((uint32_t)0x00000001U)   /*!< Busy error          */
#define HAL_ETH_ERROR_BUSY         ((uint32_t)0x00000002U)   /*!< Parameter error     */
#define HAL_ETH_ERROR_TIMEOUT      ((uint32_t)0x00000004U)   /*!< Timeout error       */
#define HAL_ETH_ERROR_DMA          ((uint32_t)0x00000008U)   /*!< DMA transfer error  */
#define HAL_ETH_ERROR_MAC          ((uint32_t)0x00000010U)   /*!< MAC transfer error  */
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
#define HAL_ETH_ERROR_INVALID_CALLBACK ((uint32_t)0x00000020U)    /*!< Invalid Callback error  */
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
/**
  * @}
  */

The DMA error is a DMA bus error.

0693W00000LyC0HQAV.pngThis part of the code creates the DMA error code. See the arrow <---- HERE!

/* ETH DMA Error */
  if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_AIS))
  {
    if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_AISE))
    {
      heth->ErrorCode |= HAL_ETH_ERROR_DMA;
 
      /* if fatal bus error occurred */
      if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_FBES))
      {
        /* Get DMA error code  */
        heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS)); <<--- HERE!
 
        /* Disable all interrupts */
        __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMAIER_NISE | ETH_DMAIER_AISE); 
 
        /* Set HAL state to ERROR */
        heth->gState = HAL_ETH_STATE_ERROR;
      }
      else
      {
        /* Get DMA error status  */
        heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_ETS | ETH_DMASR_RWTS |
                                                              ETH_DMASR_RBUS | ETH_DMASR_AIS));
 
        /* Clear the interrupt summary flag */
        __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMASR_ETS | ETH_DMASR_RWTS |
                                      ETH_DMASR_RBUS | ETH_DMASR_AIS));
      }

 My main function

 
 
/* Private variables ---------------------------------------------------------*/
 
ETH_TxPacketConfig TxConfig;
ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
 
void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth){
	uint32_t errorCode = heth->ErrorCode;
}
 
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FSMC_Init();
  MX_DCMI_Init();
  MX_SPI2_Init();
  MX_TIM1_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  MX_CAN1_Init();
  MX_RTC_Init();
  MX_TIM4_Init();
  MX_UART5_Init();
  MX_ETH_Init();
  /* USER CODE BEGIN 2 */
 
  /* Start up LCD */
  HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_SET);
  LCD_BL_ON();
  lcdInit();
 
  HAL_GPIO_WritePin(ETH_RESET_GPIO_Port, ETH_RESET_Pin, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(ETH_RESET_GPIO_Port, ETH_RESET_Pin, GPIO_PIN_SET);
 
  /* Enable interrupt */
  HAL_ETH_Start_IT(&heth);
 
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
}

Hardware settings

The hardware settings are for RMII for the Ethernet PHY DP83848 .

Yes! The LED D1 flashes when something happen at the network. The pin ACT_LED/COL should go low when something happens. The oscillator is at 50 MHz and very close to the DP83848 chip.

0693W00000LyNQVQA3.png0693W00000LyNQaQAN.pngSoftware settings:

Download my project here:

STM32 project:

https://easyupload.io/xhrn8d

Schematic project (KiCAD):

https://easyupload.io/9x3xig

Why I'm thinking this be a bug?

Because I have not configured ETH DMA and it give me a bug about that when my Ethernet PHY got a message and pass it over to the STM32 processor. I assume that STM32CubeIDE 1.9.0 have some issues then.

What am I 100% sure that I have been constructed the hardware correctly?

The Ethernet PHY address is 0x1 and I have been veryfied that this is correct address. The LED D1 is flashing when activity occurs at the network.

The callback function calls when the LED D1 flashes after initialization.

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer
46 REPLIES 46
AlexFabre
Associate II

​Hi @Daniel Mårtensson​  

Your project is not downloadable anymore, could you re-upload it ?

Could you explain what correction you made to the Rx Descriptors and buffers to make ping work.

Hello @AlexFabre​ 

Here is the project: https://github.com/DanielMartensson/STM32-Ethernet-Camera

I have not touch the RX descriptors. I just use default. See the .ioc file

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

ST... after a month? For them it takes on average a year to fix anything and even then half of the fixes are still flawed. Return to the version before the rewrite (v1.27) - for F4 it was more or less working.

DMårt
Lead

Since STM32CubeIDE 1.10.0, then this issue has been fixed. Thank you.

  1. Use default LwIP settings. You can set a fixed IP adress if you want
  2. Enable the Ethernet PHY BEFORE the C-code run MX_LWIP_Init(); function. E.g set the RESET-pin to HIGH for DP83848 Ethernet phy before MX_LWIP_Init(); runs.
  3. In your C-code main while loop. place the code line MX_LWIP_Process(); there.

Done!

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

So why can I ping right now? I just changed the STM32CubeIDE to next version, and then it works to ping to my PCB board.

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer
KWyss.1
Associate II

@Daniel Mårtensson​ I faced the same issue for a week with theSTM32Cube MCU Package FW 1.27.1 but could finally solve it!!!

1) If you use LwIP CubeMX Configuration you need to set the LWIP_RAM_HEAP_POINTER. Default value points in a memory region witch is not available with F4. This causes the DMA FBES ERROR. See for that the last comment in the following post on stackexchange:

https://electronics.stackexchange.com/questions/612369/stm32-ethernet-and-tcp-issues-with-firmware-1-27-0-and-cubeide-probably-at-sendMX_LWIP_Init

  

2) Further you should include the netif_set_up(&gnetif) function in MX_LWIP_Init() at USER CODE BEGIN 3 section to be shure that the periphery get correct initialized.

Hope this helps you or other in the community they faces this ugly issue.