Ethernet not working on STM32H7x3
- July 23, 2018
- 10 replies
- 76413 views
The Ethernet peripheral on STM32H7x3 is not sending, or receiving data correctly. Or, the IP stack is not able to establish connection to other devices.
What could be the problem?
In most cases, the problem is related to memory layout and Memory Protection Unit (MPU) configuration.
Solution
It is strongly recommended to follow the same configuration as in examples provided in STM32CubeH7 package:
e.g. Projects\STM32H743ZI-Nucleo\Applications\LwIP\LwIP_HTTP_Server_Netconn_RTOS.
The following conditions should be met:
- All data passed to Ethernet peripheral (ETH) must NOT be stored in DTCM RAM, since the ETH DMA can't access DTCM RAM (starting at 0x20000000)
- Projects generated with STM32CubeMX can put variables by default to DTCM RAM. The solution is to place them to D1 SRAM (starting at 0x24000000)
- TX and RX DMA descriptors (defined in ethernetif.c file) are recommended to be in D2 SRAM and be configured by MPU as Device memory or Strongly-ordered type.
- These should be set by default by CubeMX for IAR and Keil IDEs. For GCC, you need to modify the linkerscript (please see the examples.
- MPU configuration can be found in main.c file in the example
- RX buffer (defined in ethernetif.c file) is recommended to be located in D2 SRAM and must not be configured as Device memory type (because IP stacks like LwIP can access the received data unaligned).
- This is also set by default by CubeMX for Keil and IAR IDEs. Again For GCC, you need to modify the linkerscript (please see the examples).
- Shouldn't be placed in MPU region of TX and RX DMA descriptors
- Should be configured as non-cacheable memory, or write-through
- This is required for HAL library version 1.2.0 and might not be implemented in the library examples
The example MPU configuration can look like (please see attached file) for the MPU configuration code
- 256 bytes at 0x30040000 configured as Shared Device, MPU region 2 (required for overlapping)
- This is for RX and TX DMA descriptors
- 16 kb at 0x30044000 configured as write-through, MPU region 1
- This is for TX buffers allocated by LwIP
- 16 kb at 0x30040000 configured as non-cacheable, MPU region 0 (required for overlapping)
- This is for RX buffer used by the Ethernet driver
This is how it is implemented in STM32CubeH7 examples, and it works with the current implementation of the library (v1.2.0). Other configurations (e.g. MPU) might also work, but might also fail with specific compiler options (especially with optimization flags).
Explanation
The data are managed by the dedicated DMA in the Ethernet peripheral. This means that:
- Receive and transmit buffers must be accessible by DMA
- All data (including DMA descriptors) must be effectively written to the SRAM before triggering/enabling the DMA
The Cortex-M7 can perform accesses to Normal memory type out-of-order. So if we have sequence write to SRAM (Normal type by default), then write to Ethernet register (Device by default), those two operations can be switched by the CPU. And this actually happens in some cases.
So the TX and RX DMA descriptors should be configured to Device or Strongly-ordered type, since:
- accesses to Device type must be performed in-order compared to other Device type accesses
- accesses to Strongly-ordered type must be executed in-order to all other types (Strongly-ordered access acts as memory barrier).
The RX buffer should be non-cacheable or write-through, because at some cases the RX buffer can be reused as TX buffer inside the LwIP stack. E.g. when pinging the device. So sometimes the valid data would be in cache (TX) and sometimes in SRAM (RX). The write-through configuration can solve this issue, but requires cache invalidation during the data reception.
