diff --git a/tools/platformio-build.py b/tools/platformio-build.py
index 06858c446c..b15680bb2a 100644
--- a/tools/platformio-build.py
+++ b/tools/platformio-build.py
@@ -75,7 +75,9 @@ def scons_patched_match_splitext(path, suffixes=None):
         "-U__STRICT_ANSI__",
         "-ffunction-sections",
         "-fdata-sections",
-        "-Wall"
+        "-Wall",
+        "-free",
+        "-fipa-pta"
     ],
 
     CXXFLAGS=[
@@ -279,18 +281,67 @@ def scons_patched_match_splitext(path, suffixes=None):
     env.Append(CPPDEFINES=[current_vtables])
 assert current_vtables
 
-current_mmu_iram_size = None
-for flag in env["CPPDEFINES"]:
-    try:
-        d, val = flag
-        if str(d).startswith("MMU_IRAM_SIZE"):
-            current_mmu_iram_size = "{}={}".format(d, val)
-    except ValueError:
-        continue
-if not current_mmu_iram_size:
-    current_mmu_iram_size = "MMU_IRAM_SIZE=0x8000"
-    env.Append(CPPDEFINES=[current_mmu_iram_size])
-assert current_mmu_iram_size
+#
+# MMU
+#
+
+mmu_flags = []
+required_flags = ("MMU_IRAM_SIZE", "MMU_ICACHE_SIZE")
+if "PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48" in flatten_cppdefines:
+    mmu_flags = [("MMU_IRAM_SIZE", "0xC000"), ("MMU_ICACHE_SIZE", "0x4000")]
+elif "PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED" in flatten_cppdefines:
+    mmu_flags = [
+        ("MMU_IRAM_SIZE", "0xC000"),
+        ("MMU_ICACHE_SIZE", "0x4000"),
+        "MMU_IRAM_HEAP",
+    ]
+elif "PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM32_SECHEAP_NOTSHARED" in flatten_cppdefines:
+    mmu_flags = [
+        ("MMU_IRAM_SIZE", "0x8000"),
+        ("MMU_ICACHE_SIZE", "0x4000"),
+        ("MMU_SEC_HEAP_SIZE", "0x4000"),
+        ("MMU_SEC_HEAP", "0x40108000"),
+    ]
+elif "PIO_FRAMEWORK_ARDUINO_MMU_EXTERNAL_128K" in flatten_cppdefines:
+    mmu_flags = [
+        ("MMU_IRAM_SIZE", "0x8000"),
+        ("MMU_ICACHE_SIZE", "0x8000"),
+        ("MMU_EXTERNAL_HEAP", "128"),
+    ]
+elif "PIO_FRAMEWORK_ARDUINO_MMU_EXTERNAL_1024K" in flatten_cppdefines:
+    mmu_flags = [
+        ("MMU_IRAM_SIZE", "0x8000"),
+        ("MMU_ICACHE_SIZE", "0x8000"),
+        ("MMU_EXTERNAL_HEAP", "256"),
+    ]
+elif "PIO_FRAMEWORK_ARDUINO_MMU_CUSTOM" in flatten_cppdefines:
+    if not all(d in flatten_cppdefines for d in required_flags):
+        print(
+            "Error: Missing custom MMU configuration flags (%s)!"
+            % ", ".join(required_flags)
+        )
+        env.Exit(1)
+
+    for flag in env["CPPDEFINES"]:
+        define = flag
+        if isinstance(flag, (tuple, list)):
+            define, _ = flag
+        if define.startswith("MMU_"):
+            mmu_flags.append(flag)
+# PIO_FRAMEWORK_ARDUINO_MMU_CACHE32_IRAM32 (default)
+else:
+    mmu_flags = [
+        ("MMU_IRAM_SIZE", board.get("build.mmu_iram_size", "0x8000")),
+        ("MMU_ICACHE_SIZE", board.get("build.mmu_icache_size", "0x8000"))]
+    if any(f in flatten_cppdefines for f in required_flags):
+        print(
+            "Warning! Detected custom MMU flags. Please use the "
+            "`-D PIO_FRAMEWORK_ARDUINO_MMU_CUSTOM` option to disable "
+            "the default configuration."
+        )
+
+assert mmu_flags
+env.Append(CPPDEFINES=mmu_flags)
 
 
 # Build the eagle.app.v6.common.ld linker file
@@ -298,8 +349,21 @@ def scons_patched_match_splitext(path, suffixes=None):
     join("$BUILD_DIR", "ld", "local.eagle.app.v6.common.ld"),
     join(FRAMEWORK_DIR, "tools", "sdk", "ld", "eagle.app.v6.common.ld.h"),
     env.VerboseAction(
-        "$CC -CC -E -P -D%s -D%s %s $SOURCE -o $TARGET" % (current_vtables, current_mmu_iram_size, fp_in_irom),
-        "Generating LD script $TARGET"))
+        "$CC -CC -E -P -D%s %s %s $SOURCE -o $TARGET"
+        % (
+            current_vtables,
+            # String representation of MMU flags
+            " ".join(
+                [
+                    "-D%s=%s" % f if isinstance(f, (tuple, list)) else "-D" + f
+                    for f in mmu_flags
+                ]
+            ),
+            fp_in_irom,
+        ),
+        "Generating LD script $TARGET",
+    ),
+)
 env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", app_ld)
 
 if not env.BoardConfig().get("build.ldscript", ""):
@@ -309,6 +373,7 @@ def scons_patched_match_splitext(path, suffixes=None):
 # Dynamic core_version.h for staging builds
 #
 
+
 def platform_txt_version(default):
     with open(join(FRAMEWORK_DIR, "platform.txt"), "r") as platform_txt:
         for line in platform_txt:
@@ -322,6 +387,7 @@ def platform_txt_version(default):
 
     return default
 
+
 if isdir(join(FRAMEWORK_DIR, ".git")):
     cmd = '"$PYTHONEXE" "{script}" -b "$BUILD_DIR" -p "{framework_dir}" -v {version}'
     fmt = {