Sanify the MCU linker scripts

We now have SRAM_L and SRAM_U split apart. Otherwise, it's just a matter
of time before the linker splits something across them which the
compiler tries accessing with ldrd or something and causes mysterious
problems at runtime.

Also, the new arrangement has the stack grow off the end of RAM, so
instead of clobbering the heap you'll just get a hard fault if you
overflow the stack.

Change-Id: I3c18ac665b48ddc0456e0a1ef34213dcac8e9c85
diff --git a/motors/NOTES.md b/motors/NOTES.md
index a822d79..884ad11 100644
--- a/motors/NOTES.md
+++ b/motors/NOTES.md
@@ -1,14 +1,14 @@
 * Teensy 3.5 has a MK64FX512VMD12 (Freescale Kinetis K64 sub-family)
     * It's a Cortex-M4F, which means it has an FPU and DSP instructions.
     * 512 KB of flash
-    * 192 KB SRAM (64 KB SRAM\_L, 128 KB SRAM\_U)
+    * 256 KB SRAM (64 KB SRAM\_L, 192 KB SRAM\_U)
     * Up to 120 MHz
     * [datasheet](http://cache.freescale.com/files/microcontrollers/doc/data_sheet/K64P144M120SF5.pdf)
     * [errata](https://www.nxp.com/docs/en/errata/Kinetis_K_1N83J.pdf)
         * TODO(Brian): Are all of our parts this revision?
     * [K64 reference manual](http://cache.nxp.com/assets/documents/data/en/reference-manuals/K64P144M120SF5RM.pdf)
     * [schematic](https://www.pjrc.com/teensy/schematic.html).
-* [actual docs on the bit banding](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/Behcjiic.html)
+* [actual docs on the bit-banding](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/Behcjiic.html)
 * [ARM Cortex-M Programming Guide to Memory Barrier Instructions](https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf)
 * [Cortex-M4 instruction timings](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/CHDDIGAC.html)
 * [Optimizing Performance on Kinetis K-series MCUs](https://www.nxp.com/docs/en/application-note/AN4745.pdf)
@@ -30,6 +30,9 @@
     * [datasheet](https://www.nxp.com/docs/en/data-sheet/K22P64M120SF5V2.pdf)
     * [reference manual](https://www.nxp.com/docs/en/reference-manual/K22P64M120SF5V2RM.pdf)
 * [ARMv7-M Architecture Reference Manual](https://static.docs.arm.com/ddi0403/eb/DDI0403E_B_armv7m_arm.pdf)
+* TODO(Brian): Turn the cache on. Writethrough caching for the flash would be useful.
+  https://www.nxp.com/docs/en/application-note/AN4745.pdf "Cache initialization"
+  has steps.
 
 ### Clocking
 * Running the core clock at its maximum of 120 MHz
diff --git a/motors/core/BUILD b/motors/core/BUILD
index 6e08dd4..092c540 100644
--- a/motors/core/BUILD
+++ b/motors/core/BUILD
@@ -3,8 +3,9 @@
 filegroup(
     name = "linkerscripts",
     srcs = [
-        "kinetis_128k.ld",
-        "kinetis_192k.ld",
+        "kinetis_512_128.ld",
+        "kinetis_512_256.ld",
+        "kinetis_sections.ld",
     ],
     visibility = ["//tools/cpp:__pkg__"],
 )
diff --git a/motors/core/kinetis_128k.ld b/motors/core/kinetis_128k.ld
deleted file mode 100644
index bde65b5..0000000
--- a/motors/core/kinetis_128k.ld
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Teensyduino Core Library
- * http://www.pjrc.com/teensy/
- * Copyright (c) 2017 PJRC.COM, LLC.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * 1. The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * 2. If the Software is incorporated into a build system that allows
- * selection among a list of target devices, then similar target
- * devices manufactured by PJRC.COM must be included in the list of
- * target devices and selectable in the same manner.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* TODO(Brian): De-duplicate with the version for 192K SRAM. */
-/* TODO(Brian): Split out SRAM_L and SRAM_U intelligently. */
-MEMORY
-{
-  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
-  RAM  (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 128K
-}
-
-ENTRY(_VectorsFlash);
-
-SECTIONS
-{
-  .text : {
-    . = 0;
-    KEEP(*(.vectors))
-    *(.startup*)
-    . = 0x400;
-    KEEP(*(.flashconfig*))
-    *(SORT_BY_ALIGNMENT(.text*))
-    *(SORT_BY_ALIGNMENT(.rodata*))
-    . = ALIGN(4);
-    KEEP(*(.init))
-    . = ALIGN(4);
-    __preinit_array_start = .;
-    KEEP (*(.preinit_array))
-    __preinit_array_end = .;
-    __init_array_start = .;
-    KEEP (*(SORT(.init_array.*)))
-    KEEP (*(.init_array))
-    __init_array_end = .;
-  } > FLASH = 0xFF
-
-  .ARM.exidx : {
-    __exidx_start = .;
-    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-    __exidx_end = .;
-  } > FLASH
-
-  /* Deliberately putting .bss before .data because we end up with some things
-   * in here that have large alignments, so this minimizes padding.
-   */
-  .bss : {
-    . = ALIGN(4);
-    __bss_ram_start__ = .;
-    *(SORT_BY_ALIGNMENT(.bss*))
-    /* Stupid precompiled libc has common symbols, so stick them in. */
-    */libc_nano.a:*(COMMON)
-    . = ALIGN(4);
-    __bss_ram_end__ = .;
-  } > RAM
-
-  .data : {
-    . = ALIGN(4);
-    __data_ram_start__ = .;
-    *(SORT_BY_ALIGNMENT(.data*))
-    . = ALIGN(4);
-    __data_ram_end__ = .;
-  } > RAM AT>FLASH
-
-  __data_flash_start__ = LOADADDR(.data);
-
-  . = ALIGN(8);
-  __heap_start__ = .;
-
-  /* We don't want any common symbols, so just don't include them which results
-   * in linker errors if any do show up somehow.
-   * Contrary to sanity, even with --orphan-handling=error the linker will still
-   * do normal orphan section handling with COMMON... */
-  /DISCARD/ : {
-    *(COMMON);
-  }
-
-  __stack_end__ = ORIGIN(RAM) + LENGTH(RAM);
-}
diff --git a/motors/core/kinetis_192k.ld b/motors/core/kinetis_192k.ld
deleted file mode 100644
index c266f3d..0000000
--- a/motors/core/kinetis_192k.ld
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Teensyduino Core Library
- * http://www.pjrc.com/teensy/
- * Copyright (c) 2017 PJRC.COM, LLC.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * 1. The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * 2. If the Software is incorporated into a build system that allows
- * selection among a list of target devices, then similar target
- * devices manufactured by PJRC.COM must be included in the list of
- * target devices and selectable in the same manner.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/* TODO(Brian): De-duplicate with the version for 128K SRAM. */
-/* TODO(Brian): Split out SRAM_L and SRAM_U intelligently. */
-MEMORY
-{
-  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
-  RAM  (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 192K
-}
-
-ENTRY(_VectorsFlash);
-
-SECTIONS
-{
-  .text : {
-    . = 0;
-    KEEP(*(.vectors))
-    *(.startup*)
-    . = 0x400;
-    KEEP(*(.flashconfig*))
-    *(SORT_BY_ALIGNMENT(.text*))
-    *(SORT_BY_ALIGNMENT(.rodata*))
-    . = ALIGN(4);
-    KEEP(*(.init))
-    . = ALIGN(4);
-    __preinit_array_start = .;
-    KEEP (*(.preinit_array))
-    __preinit_array_end = .;
-    __init_array_start = .;
-    KEEP (*(SORT(.init_array.*)))
-    KEEP (*(.init_array))
-    __init_array_end = .;
-  } > FLASH = 0xFF
-
-  .ARM.exidx : {
-    __exidx_start = .;
-    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-    __exidx_end = .;
-  } > FLASH
-
-  /* Deliberately putting .bss before .data because we end up with some things
-   * in here that have large alignments, so this minimizes padding.
-   */
-  .bss : {
-    . = ALIGN(4);
-    __bss_ram_start__ = .;
-    *(SORT_BY_ALIGNMENT(.bss*))
-    /* Stupid precompiled libc has common symbols, so stick them in. */
-    */libc_nano.a:*(COMMON)
-    . = ALIGN(4);
-    __bss_ram_end__ = .;
-  } > RAM
-
-  .data : {
-    . = ALIGN(4);
-    __data_ram_start__ = .;
-    *(SORT_BY_ALIGNMENT(.data*))
-    . = ALIGN(4);
-    __data_ram_end__ = .;
-  } > RAM AT>FLASH
-
-  __data_flash_start__ = LOADADDR(.data);
-
-  . = ALIGN(8);
-  __heap_start__ = .;
-
-  /* We don't want any common symbols, so just don't include them which results
-   * in linker errors if any do show up somehow.
-   * Contrary to sanity, even with --orphan-handling=error the linker will still
-   * do normal orphan section handling with COMMON... */
-  /DISCARD/ : {
-    *(COMMON);
-  }
-
-  __stack_end__ = ORIGIN(RAM) + LENGTH(RAM);
-}
diff --git a/motors/core/kinetis_512_128.ld b/motors/core/kinetis_512_128.ld
new file mode 100644
index 0000000..983c5b4
--- /dev/null
+++ b/motors/core/kinetis_512_128.ld
@@ -0,0 +1,6 @@
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
+  SRAM_L (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 64K
+  SRAM_U (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
+}
diff --git a/motors/core/kinetis_512_256.ld b/motors/core/kinetis_512_256.ld
new file mode 100644
index 0000000..39d1348
--- /dev/null
+++ b/motors/core/kinetis_512_256.ld
@@ -0,0 +1,6 @@
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
+  SRAM_L (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 64K
+  SRAM_U (rwx) : ORIGIN = 0x20000000, LENGTH = 192K
+}
diff --git a/motors/core/kinetis_sections.ld b/motors/core/kinetis_sections.ld
new file mode 100644
index 0000000..15e7cf9
--- /dev/null
+++ b/motors/core/kinetis_sections.ld
@@ -0,0 +1,145 @@
+/* This file originally started as, and has now been extensively modified from:
+ * Teensyduino Core Library
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2017 PJRC.COM, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * 1. The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 2. If the Software is incorporated into a build system that allows
+ * selection among a list of target devices, then similar target
+ * devices manufactured by PJRC.COM must be included in the list of
+ * target devices and selectable in the same manner.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+[Optimizing Performance on Kinetis K-series MCUs](https://www.nxp.com/docs/en/application-note/AN4745.pdf)
+is helpful for deciding what to do here. Basically,
+code or data accesses to SRAM_L (almost) always take a single cycle, but SRAM_U
+instruction accesses take two cycles. SRAM_U data accesses are still a single
+cycle. Also, a non-core master can simultaneously access either one while the
+core is accessing the other one.
+
+However, https://community.nxp.com/thread/329666#comment-431005 reports some
+conflicting results from actual experimentation.
+
+Also, at least some of SRAM_U is in one of the bit-banding regions.
+
+In the end, putting the stack in SRAM_L so we get faults instead of corruption
+for overflowing the end of it makes the most sense.
+*/
+
+ENTRY(_VectorsFlash);
+
+SECTIONS
+{
+  .text : {
+    . = 0;
+    KEEP(*(.vectors))
+    *(.startup*)
+    . = 0x400;
+    KEEP(*(.flashconfig*))
+    *(SORT_BY_ALIGNMENT(.text*))
+    *(SORT_BY_ALIGNMENT(.rodata*))
+    . = ALIGN(4);
+    __preinit_array_start = .;
+    KEEP (*(.preinit_array))
+    __preinit_array_end = .;
+    __init_array_start = .;
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*)))
+    KEEP (*(.init_array))
+    __init_array_end = .;
+    KEEP (*(.init))
+    KEEP (*(.fini))
+  } > FLASH = 0xFF
+
+  .ARM.exidx : {
+    __exidx_start = .;
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    __exidx_end = .;
+  } > FLASH
+
+  /* Currently, we hard-code the sizes of everything that goes in .sram_l here.
+   * The alternative is linking twice (first time to determine the size, second
+   * to actually do it). */
+  . = ORIGIN(SRAM_L) + LENGTH(SRAM_L) - 0x8008 /* The tables in //motors:math */;
+  __stack_end__ = .;
+
+  .sram_l_data ALIGN(4) : ALIGN(4) {
+    ASSERT(. == ALIGN(4), "Alignment failed");
+    __data_sram_l_start__ = .;
+    *(SORT_BY_ALIGNMENT(.sram_l))
+    /* We want to grab smaller versions of the int tables here. When the int
+     * tables get larger, they won't fit in SRAM_L, but we only use the larger
+     * versions on parts with more SRAM_U. */
+    *(SORT_BY_ALIGNMENT(*512EE20static_sin_int_tableE))
+    *(SORT_BY_ALIGNMENT(*512EE20static_cos_int_tableE))
+    *(SORT_BY_ALIGNMENT(*1024EE20static_sin_int_tableE))
+    *(SORT_BY_ALIGNMENT(*1024EE20static_cos_int_tableE))
+    *(SORT_BY_ALIGNMENT(*2048EE20static_sin_int_tableE))
+    *(SORT_BY_ALIGNMENT(*2048EE20static_cos_int_tableE))
+    . = ALIGN(4);
+    __data_sram_l_end__ = .;
+  } > SRAM_L AT>FLASH
+
+  __sram_l_flash_start__ = LOADADDR(.data);
+  . = ALIGN(8);
+
+  /* Deliberately putting .bss before .data because we end up with some things
+   * in here that have large alignments, so this minimizes padding. */
+  .bss : {
+    . = ALIGN(4);
+    __bss_ram_start__ = .;
+    *(SORT_BY_ALIGNMENT(.bss*))
+    /* Stupid precompiled libc has common symbols, so stick them in. */
+    */libc_nano.a:*(COMMON)
+    . = ALIGN(4);
+    __bss_ram_end__ = .;
+  } > SRAM_U
+
+  .data ALIGN(4) : ALIGN(4) {
+    ASSERT(. == ALIGN(4), "Alignment failed");
+    __data_ram_start__ = .;
+    *(SORT_BY_ALIGNMENT(.data*))
+    . = ALIGN(4);
+    __data_ram_end__ = .;
+  } > SRAM_U AT>FLASH
+  __data_flash_start__ = LOADADDR(.data);
+
+  . = ALIGN(8);
+  __heap_start__ = .;
+  __heap_end__ = ORIGIN(SRAM_U) + LENGTH(SRAM_U);
+
+  .dummy_asserts : {
+    /* Annoyingly, these have to be in some section, so stick them here. */
+    ASSERT(__data_flash_start__ == ALIGN(__data_flash_start__, 4), "Flash data must be aligned");
+    ASSERT(__stack_end__ == ALIGN(__stack_end__, 8), "Stack must be aligned");
+    ASSERT(__sram_l_flash_start__ == ALIGN(__sram_l_flash_start__, 4), "Flash data must be aligned");
+  }
+
+
+  /* We don't want any common symbols, so just don't include them which results
+   * in linker errors if any do show up somehow.
+   * Contrary to sanity, even with --orphan-handling=error the linker will still
+   * do normal orphan section handling with COMMON... */
+  /DISCARD/ : {
+    *(COMMON);
+  }
+}
diff --git a/motors/core/mk20dx128.c b/motors/core/mk20dx128.c
index 495ace6..1f09569 100644
--- a/motors/core/mk20dx128.c
+++ b/motors/core/mk20dx128.c
@@ -42,12 +42,8 @@
   ((0 << 2) /* NMI always blocked */ | (0 << 1) /* EzPort disabled */ | \
    (1 << 0) /* Normal (not low-power) boot */)
 
-extern uint32_t __bss_ram_start__[];
-extern uint32_t __bss_ram_end__[];
-extern uint32_t __data_ram_start__[];
-extern uint32_t __data_ram_end__[];
-extern uint32_t __data_flash_start__[];
 extern uint32_t __heap_start__[];
+extern uint32_t __heap_end__[];
 extern uint32_t __stack_end__[];
 
 extern int main(void);
@@ -538,15 +534,28 @@
   SMC_PMPROT = SMC_PMPROT_AVLP | SMC_PMPROT_ALLS | SMC_PMPROT_AVLLS;
 
   {
-    uint32_t *src = __data_flash_start__;
-    uint32_t *dest = __data_ram_start__;
-    while (dest < __data_ram_end__) {
+    uint32_t *src, *dest, *end;
+    __asm__("ldr %0, =__data_flash_start__" :"=r"(src));
+    __asm__("ldr %0, =__data_ram_start__" :"=r"(dest));
+    __asm__("ldr %0, =__data_ram_end__" :"=r"(end));
+    while (dest < end) {
       *dest++ = *src++;
     }
   }
   {
-    uint32_t *dest = __bss_ram_start__;
-    while (dest < __bss_ram_end__) {
+    uint32_t *src, *dest, *end;
+    __asm__("ldr %0, =__sram_l_flash_start__" :"=r"(src));
+    __asm__("ldr %0, =__data_sram_l_start__" :"=r"(dest));
+    __asm__("ldr %0, =__data_sram_l_end__" :"=r"(end));
+    while (dest < end) {
+      *dest++ = *src++;
+    }
+  }
+  {
+    uint32_t *dest, *end;
+    __asm__("ldr %0, =__bss_ram_start__" :"=r"(dest));
+    __asm__("ldr %0, =__bss_ram_end__" :"=r"(end));
+    while (dest < end) {
       *dest++ = 0;
     }
   }
@@ -654,27 +663,12 @@
 
 char *__brkval = (char *)__heap_start__;
 
-#ifndef STACK_MARGIN
-#if defined(__MKL26Z64__)
-#define STACK_MARGIN 512
-#elif defined(__MK20DX128__)
-#define STACK_MARGIN 1024
-#elif defined(__MK20DX256__)
-#define STACK_MARGIN 4096
-#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__MK22FX512__)
-#define STACK_MARGIN 8192
-#else
-#error
-#endif
-#endif
-
 void *_sbrk(int incr) {
-  char *prev, *stack;
+  char *prev;
 
   prev = __brkval;
   if (incr != 0) {
-    __asm__ volatile("mov %0, sp" : "=r"(stack)::);
-    if (prev + incr >= stack - STACK_MARGIN) {
+    if (prev + incr >= (char *)__heap_end__) {
       errno = ENOMEM;
       return (void *)-1;
     }
@@ -683,8 +677,6 @@
   return prev;
 }
 
-#undef STACK_MARGIN
-
 __attribute__((weak)) int _read(int file, char *ptr, int len) {
   (void)file;
   (void)ptr;
diff --git a/motors/math.cc b/motors/math.cc
index 3f505bc..574ef9a 100644
--- a/motors/math.cc
+++ b/motors/math.cc
@@ -6,8 +6,10 @@
 namespace motors {
 namespace math_internal {
 
-float sin_float_table[SinCosFloatTableSize() + 1];
-float cos_float_table[SinCosFloatTableSize() + 1];
+float sin_float_table[SinCosFloatTableSize() + 1]
+    __attribute__((section(".sram_l")));
+float cos_float_table[SinCosFloatTableSize() + 1]
+    __attribute__((section(".sram_l")));
 
 ::std::array<GenericInitializer *, 10> global_initializers{};
 
diff --git a/tools/cpp/CROSSTOOL b/tools/cpp/CROSSTOOL
index 0b1223e..c015eaa 100644
--- a/tools/cpp/CROSSTOOL
+++ b/tools/cpp/CROSSTOOL
@@ -910,7 +910,8 @@
   linker_flag: "-lstdc++_nano"
   linker_flag: "-lm"
   linker_flag: "-lc_nano"
-  linker_flag: "-Tmotors/core/kinetis_192k.ld"
+  linker_flag: "-Tmotors/core/kinetis_512_256.ld"
+  linker_flag: "-Tmotors/core/kinetis_sections.ld"
   objcopy_embed_flag: "-I"
   objcopy_embed_flag: "binary"
   compilation_mode_flags {
@@ -1112,7 +1113,8 @@
   linker_flag: "-lstdc++_nano"
   linker_flag: "-lm"
   linker_flag: "-lc_nano"
-  linker_flag: "-Tmotors/core/kinetis_128k.ld"
+  linker_flag: "-Tmotors/core/kinetis_512_128.ld"
+  linker_flag: "-Tmotors/core/kinetis_sections.ld"
   objcopy_embed_flag: "-I"
   objcopy_embed_flag: "binary"
   compilation_mode_flags {
diff --git a/tools/cpp/cortex_m4f_crosstool.pb b/tools/cpp/cortex_m4f_crosstool.pb
index cd854fd..867e8b0 100644
--- a/tools/cpp/cortex_m4f_crosstool.pb
+++ b/tools/cpp/cortex_m4f_crosstool.pb
@@ -141,6 +141,7 @@
   linker_flag: "-lm"
   linker_flag: "-lc_nano"
   linker_flag: "-T%LINKER_SCRIPT%"
+  linker_flag: "-Tmotors/core/kinetis_sections.ld"
 
   compiler_flag: "-fmessage-length=80"
   compiler_flag: "-fmax-errors=20"
diff --git a/tools/cpp/gen_crosstool.py b/tools/cpp/gen_crosstool.py
index 547faf0..ec70e11 100644
--- a/tools/cpp/gen_crosstool.py
+++ b/tools/cpp/gen_crosstool.py
@@ -47,13 +47,16 @@
       '%NAME%': 'cortex-m4f',
       '%CPU%': '__MK64FX512__',
       '%F_CPU%': '120000000',
-      '%LINKER_SCRIPT%': 'motors/core/kinetis_192k.ld',
+      '%LINKER_SCRIPT%': 'motors/core/kinetis_512_256.ld',
       })
+  # TODO(Brian): The parts we actually use have 1M of FLASH. Do we want to take
+  # advantage, or maintain compatibility with alternative parts that use some
+  # of it for EEPROM/FlexMem/etc?
   add_m4f_toolchain(crosstool_proto.toolchain.add(), m4f_proto, {
       '%NAME%': 'cortex-m4f-k22',
       '%CPU%': '__MK22FX512__',
       '%F_CPU%': '120000000',
-      '%LINKER_SCRIPT%': 'motors/core/kinetis_128k.ld',
+      '%LINKER_SCRIPT%': 'motors/core/kinetis_512_128.ld',
       })
 
   with open(args[2], 'w') as f: