The RM does not talk about LwIP memory configurations.
My "brief" overview about MPU and why it is needed for the LwIP stack:
MPU is not just a "Memory Protection Unit" (sure, you can configure that some regions are not writeable, or not possible to execute code from there) - the important thing here for LwIP is: it configures also which region is cached, what the cache policy is, or a region not cached!
LwIP uses the ETH drivers. And the ETH interface is DMA based. For DMAs you have descriptors sitting in the RAM as well as the buffers where the transfer is done from/to. A DMA needs "instructions" (descriptors). And these have to be updated by MCU before you kick off a DMA (which is like another "master", another "core").
It comes to the "cache coherency" topic:
- A DMA engine, e.g. in the ETH device, needs descriptors sitting in the RAM ("instructions").
- But the MCU can write/update such descriptors by writing through its data cache.
- It means: the final memory is still not yet written/updated, all sits still in the cache of the MCU (not in memory).
- But the DMA engine of the ETH device reads only from memory - it would not see any updates on DMA descriptors (ETH DMA has no clue what sits in the MCU cache).
- BTW: the same for data buffers:
If MCU writes a new ETH package, but it sits just in Data Cache, the ETH device would send from memory old data. Or vice versa: the ETH DMA has placed new data in RAM, but the MCU does not know that its cache is not updated (not invalidated, see "cache clear" and "cache invalidate" functions).
Therefore, in combination with DMAs, esp. the LwIP DMA - the MPU is used to define regions in order:
- To specify a region which is not cached (or at least a "write-through" policy), so that DMA can see what the MCU has written as new "instructions".
- For my understanding: at least the DMA descriptors for the ETH have to sit in an "un-cached" (at least "write-through") region. Here is the MPU config used for: specify the "cache behavior" (for a region).
- It can be also the case for the transfer buffers: when ETH DMA and MCU want to access the "latest" data in memory - the memory region might be needed to be excluded from the entire cached RAM.
- Configuring regions as "un-cached" via MPU saves a lot of function calls, e.g. clear or invalidate the MCU cache.
Without MPU configured, the entire RAM can be (is!) enabled for DCache. The MPU regions define now an exception as: "this region has a different cache policy, or even this region is never cached."
Otherwise, the DMA (not being aware of MCU caches) and the MCU (with using DCache) would never be "up-to-date" (not in sync, not cache coherent between MCU and DMA as "two different master cores").
So, in case of LwIP, the MPU is mainly configured to "control" the cache functionality, esp. to "disable" a region as a cached region. Otherwise, MCU and DMA would not "understand" each other, because MCU "looks through" its DCache but ETH DMA just directly on memories (and the content can be not (yet) updated properly).
Suggestion:
compare the MPU regions with some __attribute__ used in LwIP stack (to use a dedicated piece of memory), the linker script, where also sections are defined, e.g. where the ETH DMA should have its descriptors, or where the ETH transfer buffers are located. All is "cross-connected": you should find somewhere else a "reservation" of specific memory regions and locations which are reflected also on the MPU region definitions (start addresses and size, plus cache policy). All must be matching: changing just one config will break all: source code (e.g. with __attribute__ to specify on which memory address), linker script (see sections for DMA descriptors, buffers) as well as the MPU region config must match.