2026-03-10 2:32 PM - last edited on 2026-03-12 4:42 AM by Andrew Neil
Hi, I'm working on the STM32H750B-DK discovery board and need to combine two key functionalities:
1. Ethernet connectivity based on the LwIP stack (using the example from the `stm32-hotspot/STM32H7-LwIP-Examples` repository).
2. A TouchGFX GUI that stores its assets (images, fonts) in the external QSPI flash (`MT25TL01G`) due to the limited internal flash (128KB).
I have both components working **individually**: - The **standalone Ethernet example** (STM32H750_Disco_ETH) works perfectly – I can ping the board at `192.168.1.10`.
- The **standalone TouchGFX application** works when the external flash is properly initialized via a bootloader, and assets are loaded from `0x90200000`.
The challenge is to merge them into a single project where the application code runs from internal flash (the `APP_FLASH` region) and the Ethernet stack functions correctly alongside the TouchGFX GUI. ### **Current Memory Map (Linker Script)** I am using the following memory partition to accommodate both: `
MEMORY
{
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
SDRAM (xrw) : ORIGIN = 0xD0000000, LENGTH = 8M
ASSETS_FLASH (r) : ORIGIN = 0x90200000, LENGTH = 126M
/* Partition internal flash */
BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* Reserve 32KB for bootloader */
APP_FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 96K /* Remaining 96KB for app */
}### **The Problem** When I attempt to merge the two, I encounter a "Load failed" error during debugging because the debugger cannot write to the external QSPI flash at `0x90200000` without an external loader. More importantly, the Ethernet stack often fails to initialize (ping timeout) or the system hard-faults, likely due to the QSPI not being initialized early enough for code that may be inadvertently placed in external flash.
My Approach & Questions
1. **Bootloader Role:** The bootloader at `0x08000000` initializes the QSPI in memory-mapped mode and then jumps to the application at `0x08008000`. Is this the correct sequence to ensure the external flash is ready before the main application (including LwIP) starts?
2. **Linker Script Placement:** How can I ensure that **all code and initialized data for LwIP and the core application** are placed strictly in internal flash (`APP_FLASH`) and **not** in external `ASSETS_FLASH`? The `ASSETS_FLASH` region should only contain read-only GUI assets, not executable code.
3. **MPU Configuration:** The Ethernet example uses specific MPU regions for the LwIP heap (`0x30020000`, non-cacheable) and descriptors (`0x30040000`, non-cacheable, shareable). Do I need an additional MPU region for the external QSPI flash address range (e.g., `0x90000000` or `0x90200000`) to make it cacheable for performance, or will that interfere with Ethernet DMA?
4. **Debugging with External Flash:** What is the recommended workflow for debugging such a project? I have used STM32CubeProgrammer with the `MT25TL01G_STM32H750B-DISCO.stldr` loader to flash the image manually, but it breaks the seamless debug-test cycle in CubeIDE. Is there a way to configure the IDE to use the external loader automatically?
Request
Has anyone successfully integrated the `STM32H750_Disco_ETH` LwIP example with a TouchGFX project that relies on external QSPI flash? Could you share a working linker script snippet, the necessary MPU settings, and your approach to debugging?
Any guidance or examples would be immensely helpful. Thank you!
Solved! Go to Solution.
2026-04-03 10:28 AM
I have re-added it now, but unfortuantely still "Request timed out". If this leads to the conclusion of hardware failure. I have in my disposal MAX485 and USB-RS485 converter, may it be an alternative to implement modbus
2026-04-03 11:46 PM
On a second thought, I rule out hardware failure, because LwiP only application: https://github.com/STMicroelectronics/STM32CubeH7/tree/master/Projects/STM32H750B-DK/Templates/ExtMem_Boot/STM32CubeIDE works fine, no problem:
C:\Windows\System32>ping 192.168.1.10 -t
Pinging 192.168.1.10 with 32 bytes of data:
Reply from 192.168.1.10: bytes=32 time=1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time=5ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Reply from 192.168.1.10: bytes=32 time<1ms TTL=255
Ping statistics for 192.168.1.10:
Packets: Sent = 18, Received = 18, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 5ms, Average = 0ms
Control-C
^C
C:\Windows\System32>
2026-04-06 1:40 AM
Hello @ksale.1,
Could you please attach your project so I can review it? If the project is private, feel free to send me a message privately so i can provide a secure line for you to upload the project.
Best regards,
2026-04-06 10:55 AM - edited 2026-04-06 11:47 PM
2026-04-07 2:44 AM - edited 2026-04-07 2:44 AM
Hello @ksale.1,
I've analyzed your project, fixed the issues, and attached the corrected version below. Here’s what I found:
1. The names of the memory sections dedicated to the descriptors in the linker file don’t match those declared inside the ethernetif.c file.
In ethernetif.c, the section names are RxDescripSection and TxDescripSection (with an "s"):
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDescripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDescripSection"))); /* Ethernet Tx DMA Descriptors */
However, in your linker file, the sections are declared as RxDecripSection and TxDecripSection (without the "s"). In the project I attached, these names match the declarations in ethernetif.c. This mismatch was causing the issue, so please ensure the names are consistent.
Here is the relevant linker section:
.lwip_sec (NOLOAD) :
{
. = ABSOLUTE(0x30040000);
*(.RxDecripSection)
. = ABSOLUTE(0x30040100);
*(.TxDecripSection)
. = ABSOLUTE(0x30040200);
*(.Rx_PoolSection)
} >RAM_D2
2. Regarding the netmask issue, in CubeMX configuration, after typing the netmask, make sure to press Enter so the value change takes effect. If it still didn't work, change it manually in lwip.c.
I didn’t need to change anything else. Please let me know if this resolves the problem, as I tested it on my side and it worked.
Best regards,