From 749f19e5027b126dc8cb0e36c12512641ea528ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eduardo=20Jos=C3=A9=20Tagle?= <ejtagle@hotmail.com>
Date: Wed, 28 Mar 2018 15:13:20 -0300
Subject: [PATCH] [2.0.x] Move backtrace to a shared location (#10237)

- And implement the `backtrace()` function call
---
 Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp   |  66 ++--
 Marlin/src/backtrace/backtrace.cpp            | 102 ++++++
 Marlin/src/backtrace/backtrace.h              |  29 ++
 .../unwarm.c => backtrace/unwarm.cpp}         |   3 +-
 .../src/{HAL/HAL_DUE => }/backtrace/unwarm.h  |  10 +-
 .../unwarm_arm.c => backtrace/unwarm_arm.cpp} |   8 +-
 .../unwarm_thumb.cpp}                         | 290 +++++++++---------
 .../unwarmbytab.cpp}                          |   6 +-
 .../{HAL/HAL_DUE => }/backtrace/unwarmbytab.h |   8 -
 .../unwarmmem.c => backtrace/unwarmmem.cpp}   |   2 +-
 .../{HAL/HAL_DUE => }/backtrace/unwarmmem.h   |   8 -
 .../unwinder.c => backtrace/unwinder.cpp}     |   6 +-
 .../{HAL/HAL_DUE => }/backtrace/unwinder.h    |   9 -
 Marlin/src/backtrace/unwmemaccess.cpp         | 136 ++++++++
 Marlin/src/backtrace/unwmemaccess.h           |  26 ++
 15 files changed, 469 insertions(+), 240 deletions(-)
 create mode 100644 Marlin/src/backtrace/backtrace.cpp
 create mode 100644 Marlin/src/backtrace/backtrace.h
 rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarm.c => backtrace/unwarm.cpp} (99%)
 rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwarm.h (98%)
 rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarm_arm.c => backtrace/unwarm_arm.cpp} (98%)
 rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarm_thumb.c => backtrace/unwarm_thumb.cpp} (85%)
 rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarmbytab.c => backtrace/unwarmbytab.cpp} (98%)
 rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwarmbytab.h (94%)
 rename Marlin/src/{HAL/HAL_DUE/backtrace/unwarmmem.c => backtrace/unwarmmem.cpp} (98%)
 rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwarmmem.h (94%)
 rename Marlin/src/{HAL/HAL_DUE/backtrace/unwinder.c => backtrace/unwinder.cpp} (93%)
 rename Marlin/src/{HAL/HAL_DUE => }/backtrace/unwinder.h (98%)
 create mode 100644 Marlin/src/backtrace/unwmemaccess.cpp
 create mode 100644 Marlin/src/backtrace/unwmemaccess.h

diff --git a/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp b/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
index cd00165bcc..849ee89f94 100644
--- a/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/DebugMonitor_Due.cpp
@@ -24,7 +24,8 @@
 
 #include "../../inc/MarlinConfig.h"
 #include "../../Marlin.h"
-#include "backtrace/unwinder.h"
+#include "../../backtrace/unwinder.h"
+#include "../../backtrace/unwmemaccess.h"
 
 // Debug monitor that dumps to the Programming port all status when
 // an exception or WDT timeout happens - And then resets the board
@@ -112,45 +113,6 @@ static void TXDec(uint32_t v) {
   } while (p != &nbrs[0]);
 }
 
-/* Validate address */
-static bool validate_addr(uint32_t addr) {
-
-  // Address must be in SRAM (0x20070000 - 0x20088000)
-  if (addr >= 0x20070000 && addr < 0x20088000)
-    return true;
-
-  // Or in FLASH (0x00080000 - 0x00100000)
-  if (addr >= 0x00080000 && addr < 0x00100000)
-    return true;
-
-  return false;
-}
-
-static bool UnwReadW(const uint32_t a, uint32_t *v) {
-  if (!validate_addr(a))
-    return false;
-
-  *v = *(uint32_t *)a;
-  return true;
-}
-
-static bool UnwReadH(const uint32_t a, uint16_t *v) {
-  if (!validate_addr(a))
-    return false;
-
-  *v = *(uint16_t *)a;
-  return true;
-}
-
-static bool UnwReadB(const uint32_t a, uint8_t *v) {
-  if (!validate_addr(a))
-    return false;
-
-  *v = *(uint8_t *)a;
-  return true;
-}
-
-
 // Dump a backtrace entry
 static bool UnwReportOut(void* ctx, const UnwReport* bte) {
   int* p = (int*)ctx;
@@ -270,7 +232,8 @@ void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause
 }
 
 __attribute__((naked)) void NMI_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -282,7 +245,8 @@ __attribute__((naked)) void NMI_Handler(void) {
 }
 
 __attribute__((naked)) void HardFault_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -294,7 +258,8 @@ __attribute__((naked)) void HardFault_Handler(void) {
 }
 
 __attribute__((naked)) void MemManage_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -306,7 +271,8 @@ __attribute__((naked)) void MemManage_Handler(void) {
 }
 
 __attribute__((naked)) void BusFault_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -318,7 +284,8 @@ __attribute__((naked)) void BusFault_Handler(void) {
 }
 
 __attribute__((naked)) void UsageFault_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -330,7 +297,8 @@ __attribute__((naked)) void UsageFault_Handler(void) {
 }
 
 __attribute__((naked)) void DebugMon_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -343,7 +311,8 @@ __attribute__((naked)) void DebugMon_Handler(void) {
 
 /* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
 __attribute__((naked)) void WDT_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
@@ -355,7 +324,8 @@ __attribute__((naked)) void WDT_Handler(void) {
 }
 
 __attribute__((naked)) void RSTC_Handler(void) {
-  __asm volatile (
+  __asm__ __volatile__ (
+    ".syntax unified        \n"
     " tst lr, #4            \n"
     " ite eq                \n"
     " mrseq r0, msp         \n"
diff --git a/Marlin/src/backtrace/backtrace.cpp b/Marlin/src/backtrace/backtrace.cpp
new file mode 100644
index 0000000000..fab68416a6
--- /dev/null
+++ b/Marlin/src/backtrace/backtrace.cpp
@@ -0,0 +1,102 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "backtrace.h"
+
+#if defined(__arm__) || defined(__thumb__)
+
+#include "unwinder.h"
+#include "unwmemaccess.h"
+#include "../Marlin.h"
+
+// Dump a backtrace entry
+static bool UnwReportOut(void* ctx, const UnwReport* bte) {
+  int* p = (int*)ctx;
+
+  (*p)++;
+
+  SERIAL_CHAR('#'); SERIAL_PRINT(*p,DEC); SERIAL_ECHOPGM(" : ");
+  SERIAL_ECHOPGM(bte->name?bte->name:"unknown"); SERIAL_ECHOPGM("@0x"); SERIAL_PRINT(bte->function,HEX);
+  SERIAL_CHAR('+'); SERIAL_PRINT(bte->address - bte->function,DEC);
+  SERIAL_ECHOPGM(" PC:"); SERIAL_PRINT(bte->address,HEX); SERIAL_CHAR('\n');
+  return true;
+}
+
+#if defined(UNW_DEBUG)
+void UnwPrintf(const char* format, ...) {
+  char dest[256];
+  va_list argptr;
+  va_start(argptr, format);
+  vsprintf(dest, format, argptr);
+  va_end(argptr);
+  TX(&dest[0]);
+}
+#endif
+
+/* Table of function pointers for passing to the unwinder */
+static const UnwindCallbacks UnwCallbacks = {
+  UnwReportOut,
+  UnwReadW,
+  UnwReadH,
+  UnwReadB
+#if defined(UNW_DEBUG)
+ ,UnwPrintf
+#endif
+};
+
+void backtrace(void) {
+
+  UnwindFrame btf;
+  uint32_t sp,lr,pc;
+
+  // Capture the values of the registers to perform the traceback
+  __asm__ __volatile__ (
+    " mov %[lrv],lr\n"
+    " mov %[spv],sp\n"
+    " mov %[pcv],pc\n"
+    : [spv]"+r"( sp ),
+      [lrv]"+r"( lr ),
+      [pcv]"+r"( pc )
+    ::
+  );
+
+  // Fill the traceback structure
+  btf.sp = sp;
+  btf.fp = btf.sp;
+  btf.lr = lr;
+  btf.pc = pc | 1; // Force Thumb, as CORTEX only support it
+
+  // Perform a backtrace
+  SERIAL_ERROR_START();
+  SERIAL_ERRORLNPGM("Backtrace:");
+  int ctr = 0;
+  UnwindStart(&btf, &UnwCallbacks, &ctr);
+}
+
+#else
+
+void backtrace(void) {}
+
+#endif
+
+
+
diff --git a/Marlin/src/backtrace/backtrace.h b/Marlin/src/backtrace/backtrace.h
new file mode 100644
index 0000000000..c2761b9f5a
--- /dev/null
+++ b/Marlin/src/backtrace/backtrace.h
@@ -0,0 +1,29 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _BACKTRACE_H_
+#define _BACKTRACE_H_
+
+// Perform a backtrace to the serial port
+void backtrace(void);
+
+#endif
\ No newline at end of file
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.c b/Marlin/src/backtrace/unwarm.cpp
similarity index 99%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm.c
rename to Marlin/src/backtrace/unwarm.cpp
index 9da3be4e05..1229e7a731 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.c
+++ b/Marlin/src/backtrace/unwarm.cpp
@@ -12,12 +12,11 @@
  * File Description: Utility functions and glue for ARM unwinding sub-modules.
  **************************************************************************/
 
-#ifdef ARDUINO_ARCH_SAM
+#if defined(__arm__) || defined(__thumb__)
 
 #define MODULE_NAME "UNWARM"
 
 #include <stdint.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.h b/Marlin/src/backtrace/unwarm.h
similarity index 98%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm.h
rename to Marlin/src/backtrace/unwarm.h
index 23c1f96c2c..4e4e07e332 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm.h
+++ b/Marlin/src/backtrace/unwarm.h
@@ -54,7 +54,7 @@ typedef struct {
   /** The origin of the register value.
    * This is used to track how the value in the register was loaded.
    */
-  RegValOrigin o;
+  int o; /* (RegValOrigin) */
 } RegData;
 
 
@@ -131,10 +131,6 @@ typedef struct {
  *  Function Prototypes
  **************************************************************************/
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 UnwResult UnwStartArm(UnwState * const state);
 UnwResult UnwStartThumb(UnwState * const state);
 void UnwInvalidateRegisterFile(RegData *regFile);
@@ -144,10 +140,6 @@ bool UnwMemWriteRegister(UnwState * const state, const uint32_t addr, const RegD
 bool UnwMemReadRegister(UnwState * const state, const uint32_t addr, RegData * const reg);
 void UnwMemHashGC(UnwState * const state);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* UNWARM_H */
 
 /* END OF FILE */
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_arm.c b/Marlin/src/backtrace/unwarm_arm.cpp
similarity index 98%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm_arm.c
rename to Marlin/src/backtrace/unwarm_arm.cpp
index 9170534b54..faf3523bec 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_arm.c
+++ b/Marlin/src/backtrace/unwarm_arm.cpp
@@ -12,7 +12,7 @@
  * File Description: Abstract interpreter for ARM mode.
  **************************************************************************/
 
-#ifdef ARDUINO_ARCH_SAM
+#if defined(__arm__) || defined(__thumb__)
 
 #define MODULE_NAME "UNWARM_ARM"
 
@@ -180,7 +180,7 @@ UnwResult UnwStartArm(UnwState * const state) {
       uint8_t        rd = (instr & 0x0000f000) >> 12;
       uint16_t operand2 = (instr & 0x00000fff);
       uint32_t        op2val;
-      RegValOrigin op2origin;
+      int             op2origin;
 
       switch(opcode) {
         case  0: UnwPrintd4("AND%s r%d,r%d,", S ? "S" : "", rd, rn); break;
@@ -344,7 +344,7 @@ UnwResult UnwStartArm(UnwState * const state) {
           }
           else {
             state->regData[rd].o = state->regData[rn].o;
-            state->regData[rd].o |= op2origin;
+            state->regData[rd].o = (RegValOrigin)(state->regData[rd].o | op2origin);
           }
           break;
 
@@ -363,7 +363,7 @@ UnwResult UnwStartArm(UnwState * const state) {
 
         case 13: /* MOV: Rd:= Op2 */
         case 15: /* MVN: Rd:= NOT Op2 */
-          state->regData[rd].o = op2origin;
+          state->regData[rd].o = (RegValOrigin) op2origin;
           break;
       }
 
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_thumb.c b/Marlin/src/backtrace/unwarm_thumb.cpp
similarity index 85%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarm_thumb.c
rename to Marlin/src/backtrace/unwarm_thumb.cpp
index 38f091e521..8c14f6ecd9 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarm_thumb.c
+++ b/Marlin/src/backtrace/unwarm_thumb.cpp
@@ -12,7 +12,7 @@
  * File Description: Abstract interpretation for Thumb mode.
  **************************************************************************/
 
-#ifdef ARDUINO_ARCH_SAM
+#if defined(__arm__) || defined(__thumb__)
 
 #define MODULE_NAME "UNWARM_THUMB"
 
@@ -243,40 +243,40 @@ UnwResult UnwStartThumb(UnwState * const state) {
 
         UnwPrintd3("  r%d = 0x%08x\n", r, state->regData[r].v);
       }
-			/*
-			 * TBB / TBH
-			 */
-			else if ((instr & 0xfff0) == 0xe8d0 && (instr2 & 0xffe0) == 0xf000) {
-				/* We are only interested in 
-				 * the forms 
-				 *	TBB [PC, ...]
-				 *  TBH [PC, ..., LSL #1]
-				 * as those are used by the C compiler to implement
-				 * the switch clauses
-				 */
-				uint8_t rn = instr & 0xf;
-				uint8_t rm = instr2 & 0xf;
-				bool H = (instr2 & 0x10) ? true : false;
-				
-				UnwPrintd5("TB%c [r%d,r%d%s]\n", H ? 'H' : 'B', rn, rm, H ? ",LSL #1" : "");				
-				
-				// We are only interested if the RN is the PC. Let´s choose the 1st destination
-				if (rn == 15) {
-					if (H) {
-						uint16_t rv;
-						if(!state->cb->readH((state->regData[15].v & (~1)) + 2, &rv)) {
-							return UNWIND_DREAD_H_FAIL;
-						}
-						state->regData[15].v += rv * 2;
-					} else {
-						uint8_t rv;
-						if(!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv)) {
-							return UNWIND_DREAD_B_FAIL;
-						}
-						state->regData[15].v += rv * 2;
-					}
-				}
-			}
+      /*
+       * TBB / TBH
+       */
+      else if ((instr & 0xfff0) == 0xe8d0 && (instr2 & 0xffe0) == 0xf000) {
+        /* We are only interested in
+         * the forms
+         *  TBB [PC, ...]
+         *  TBH [PC, ..., LSL #1]
+         * as those are used by the C compiler to implement
+         * the switch clauses
+         */
+        uint8_t rn = instr & 0xf;
+        uint8_t rm = instr2 & 0xf;
+        bool H = (instr2 & 0x10) ? true : false;
+
+        UnwPrintd5("TB%c [r%d,r%d%s]\n", H ? 'H' : 'B', rn, rm, H ? ",LSL #1" : "");
+
+        // We are only interested if the RN is the PC. Let´s choose the 1st destination
+        if (rn == 15) {
+          if (H) {
+            uint16_t rv;
+            if(!state->cb->readH((state->regData[15].v & (~1)) + 2, &rv)) {
+              return UNWIND_DREAD_H_FAIL;
+            }
+            state->regData[15].v += rv * 2;
+          } else {
+            uint8_t rv;
+            if(!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv)) {
+              return UNWIND_DREAD_B_FAIL;
+            }
+            state->regData[15].v += rv * 2;
+          }
+        }
+      }
       /*
        * Unconditional branch
        */
@@ -408,118 +408,118 @@ UnwResult UnwStartThumb(UnwState * const state) {
           UnwPrintd2(" New PC=%x", state->regData[15].v + 2);
         }
       }
-			/*
-			 * PC-relative load
+      /*
+       * PC-relative load
        *  LDR Rd,[PC, #+/-imm]
        */
-			else if((instr & 0xff7f) == 0xf85f) {
-				uint8_t  rt    = (instr2 & 0xf000) >> 12;
-				uint8_t  imm12 = (instr2 & 0x0fff);
-				bool     A     = (instr  & 0x80) ? true : false;
-				uint32_t address;
-
-				/* Compute load address, adding a word to account for prefetch */
-				address = (state->regData[15].v & (~0x3)) + 4;
-				if (A) address += imm12;
-				else address -= imm12;
-
-				UnwPrintd4("LDR r%d,[PC #%c0x%08x]", rt, A?'+':'-', address);
-
-				if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
-					return UNWIND_DREAD_W_FAIL;
-				}
-			}
-			/*
-			 * LDR immediate. 
-			 *  We are only interested when destination is PC.
-			 *  LDR Rt,[Rn , #n]
-			 */
-			else if ((instr & 0xfff0) == 0xf8d0) {
-				uint8_t     rn = (instr  & 0xf);
-				uint8_t     rt = (instr2 & 0xf000) >> 12;
-				uint16_t imm12 = (instr2 & 0xfff);
-				
-				/* If destination is PC and we don't know the source value, then fail */
-				if (!M_IsOriginValid(state->regData[rn].o)) {
-					state->regData[rt].o = state->regData[rn].o;
-				} else {
-					uint32_t address = state->regData[rn].v + imm12;
-					if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
-						return UNWIND_DREAD_W_FAIL;
-					}
-				}
-			}
-			/*
-			 * LDR immediate
-			 *  We are only interested when destination is PC.
-			 *  LDR Rt,[Rn , #-n]
-			 *  LDR Rt,[Rn], #+/-n]
-			 *  LDR Rt,[Rn, #+/-n]!
-			 */
-			else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0800) == 0x0800) {
-				uint8_t     rn = (instr  & 0xf);
-				uint8_t     rt = (instr2 & 0xf000) >> 12;
-				uint16_t  imm8 = (instr2 & 0xff);
-				bool         P = (instr2 & 0x400) ? true : false;
-				bool         U = (instr2 & 0x200) ? true : false;
-				bool         W = (instr2 & 0x100) ? true : false;
-				
-				if (!M_IsOriginValid(state->regData[rn].o)) {
-					state->regData[rt].o = state->regData[rn].o;
-				} else {
-					uint32_t offaddress = state->regData[rn].v + imm8;
-					if (U) offaddress += imm8;
-					else offaddress -= imm8;
-					
-					uint32_t address;
-					if (P) {
-						address = offaddress;
-					} else {
-						address = state->regData[rn].v;
-					}
-					
-					if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
-						return UNWIND_DREAD_W_FAIL;
-					}
-					
-					if (W) {
-						state->regData[rn].v = offaddress;
-					}
-				}
-			}
-			/*
-			 * LDR (register).
-			 *  We are interested in the form
-			 *   ldr	Rt, [Rn, Rm, lsl #x]
-			 *  Where Rt is PC, Rn value is known, Rm is not known or unknown
-			 */
-			else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0fc0) == 0x0000) {
-				uint8_t   rn = (instr  & 0xf);
-				uint8_t   rt = (instr2 & 0xf000) >> 12;
-				uint8_t   rm = (instr2 & 0xf);
-				uint8_t imm2 = (instr2 & 0x30) >> 4;
-				
-				if (!M_IsOriginValid(state->regData[rn].o) ||
-						!M_IsOriginValid(state->regData[rm].o)) {
-						
-					/* If Rt is PC, and Rn is known, then do an exception and assume
-					   Rm equals 0 => This takes the first case in a switch() */
-					if (rt == 15 && M_IsOriginValid(state->regData[rn].o)) {
-						uint32_t address = state->regData[rn].v;
-						if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
-							return UNWIND_DREAD_W_FAIL;
-						}
-					} else {
-						/* Propagate unknown value */
-						state->regData[rt].o = state->regData[rn].o;
-					}
-				} else {
-					uint32_t address = state->regData[rn].v + (state->regData[rm].v << imm2);
-					if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
-						return UNWIND_DREAD_W_FAIL;
-					}
-				}
-			}
+      else if((instr & 0xff7f) == 0xf85f) {
+        uint8_t  rt    = (instr2 & 0xf000) >> 12;
+        uint8_t  imm12 = (instr2 & 0x0fff);
+        bool     A     = (instr  & 0x80) ? true : false;
+        uint32_t address;
+
+        /* Compute load address, adding a word to account for prefetch */
+        address = (state->regData[15].v & (~0x3)) + 4;
+        if (A) address += imm12;
+        else address -= imm12;
+
+        UnwPrintd4("LDR r%d,[PC #%c0x%08x]", rt, A?'+':'-', address);
+
+        if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
+          return UNWIND_DREAD_W_FAIL;
+        }
+      }
+      /*
+       * LDR immediate.
+       *  We are only interested when destination is PC.
+       *  LDR Rt,[Rn , #n]
+       */
+      else if ((instr & 0xfff0) == 0xf8d0) {
+        uint8_t     rn = (instr  & 0xf);
+        uint8_t     rt = (instr2 & 0xf000) >> 12;
+        uint16_t imm12 = (instr2 & 0xfff);
+
+        /* If destination is PC and we don't know the source value, then fail */
+        if (!M_IsOriginValid(state->regData[rn].o)) {
+          state->regData[rt].o = state->regData[rn].o;
+        } else {
+          uint32_t address = state->regData[rn].v + imm12;
+          if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
+            return UNWIND_DREAD_W_FAIL;
+          }
+        }
+      }
+      /*
+       * LDR immediate
+       *  We are only interested when destination is PC.
+       *  LDR Rt,[Rn , #-n]
+       *  LDR Rt,[Rn], #+/-n]
+       *  LDR Rt,[Rn, #+/-n]!
+       */
+      else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0800) == 0x0800) {
+        uint8_t     rn = (instr  & 0xf);
+        uint8_t     rt = (instr2 & 0xf000) >> 12;
+        uint16_t  imm8 = (instr2 & 0xff);
+        bool         P = (instr2 & 0x400) ? true : false;
+        bool         U = (instr2 & 0x200) ? true : false;
+        bool         W = (instr2 & 0x100) ? true : false;
+
+        if (!M_IsOriginValid(state->regData[rn].o)) {
+          state->regData[rt].o = state->regData[rn].o;
+        } else {
+          uint32_t offaddress = state->regData[rn].v + imm8;
+          if (U) offaddress += imm8;
+          else offaddress -= imm8;
+
+          uint32_t address;
+          if (P) {
+            address = offaddress;
+          } else {
+            address = state->regData[rn].v;
+          }
+
+          if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
+            return UNWIND_DREAD_W_FAIL;
+          }
+
+          if (W) {
+            state->regData[rn].v = offaddress;
+          }
+        }
+      }
+      /*
+       * LDR (register).
+       *  We are interested in the form
+       *   ldr  Rt, [Rn, Rm, lsl #x]
+       *  Where Rt is PC, Rn value is known, Rm is not known or unknown
+       */
+      else if ((instr & 0xfff0) == 0xf850 && (instr2 & 0x0fc0) == 0x0000) {
+        uint8_t   rn = (instr  & 0xf);
+        uint8_t   rt = (instr2 & 0xf000) >> 12;
+        uint8_t   rm = (instr2 & 0xf);
+        uint8_t imm2 = (instr2 & 0x30) >> 4;
+
+        if (!M_IsOriginValid(state->regData[rn].o) ||
+            !M_IsOriginValid(state->regData[rm].o)) {
+
+          /* If Rt is PC, and Rn is known, then do an exception and assume
+             Rm equals 0 => This takes the first case in a switch() */
+          if (rt == 15 && M_IsOriginValid(state->regData[rn].o)) {
+            uint32_t address = state->regData[rn].v;
+            if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
+              return UNWIND_DREAD_W_FAIL;
+            }
+          } else {
+            /* Propagate unknown value */
+            state->regData[rt].o = state->regData[rn].o;
+          }
+        } else {
+          uint32_t address = state->regData[rn].v + (state->regData[rm].v << imm2);
+          if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
+            return UNWIND_DREAD_W_FAIL;
+          }
+        }
+      }
       else {
         UnwPrintd1("???? (32)");
 
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.c b/Marlin/src/backtrace/unwarmbytab.cpp
similarity index 98%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.c
rename to Marlin/src/backtrace/unwarmbytab.cpp
index 3346546019..9827f25f65 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.c
+++ b/Marlin/src/backtrace/unwarmbytab.cpp
@@ -11,7 +11,7 @@
  * for exceptions for debugging purposes in 2018 by Eduardo José Tagle.
  */
 
-#ifdef ARDUINO_ARCH_SAM
+#if defined(__arm__) || defined(__thumb__)
 
 #include "unwarmbytab.h"
 
@@ -19,8 +19,8 @@
 #include <string.h>
 
 /* These symbols point to the unwind index and should be provide by the linker script */
-extern const UnwTabEntry __exidx_start[];
-extern const UnwTabEntry __exidx_end[];
+extern "C" const UnwTabEntry __exidx_start[];
+extern "C" const UnwTabEntry __exidx_end[];
 
 /* This prevents the linking of libgcc unwinder code */
 void __aeabi_unwind_cpp_pr0(void) {};
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.h b/Marlin/src/backtrace/unwarmbytab.h
similarity index 94%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.h
rename to Marlin/src/backtrace/unwarmbytab.h
index cdf114c513..a17a6f7d66 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmbytab.h
+++ b/Marlin/src/backtrace/unwarmbytab.h
@@ -29,16 +29,8 @@ typedef struct {
   uint32_t insn;
 } UnwTabEntry;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 UnwResult UnwindByTableStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
 
 /* END OF FILE */
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.c b/Marlin/src/backtrace/unwarmmem.cpp
similarity index 98%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.c
rename to Marlin/src/backtrace/unwarmmem.cpp
index 57fb011fe1..bac3c89897 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.c
+++ b/Marlin/src/backtrace/unwarmmem.cpp
@@ -12,7 +12,7 @@
  * File Description: Implementation of the memory tracking sub-system.
  **************************************************************************/
 
-#ifdef ARDUINO_ARCH_SAM
+#if defined(__arm__) || defined(__thumb__)
 #define MODULE_NAME "UNWARMMEM"
 
 #include <stdio.h>
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.h b/Marlin/src/backtrace/unwarmmem.h
similarity index 94%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.h
rename to Marlin/src/backtrace/unwarmmem.h
index 107286b828..f30846b34c 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwarmmem.h
+++ b/Marlin/src/backtrace/unwarmmem.h
@@ -17,17 +17,9 @@
 
 #include "unwarm.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 bool UnwMemHashRead(MemData * const memData, uint32_t addr, uint32_t * const data, bool * const tracked);
 bool UnwMemHashWrite(MemData * const memData, uint32_t addr, uint32_t val, bool valValid);
 void UnwMemHashGC(UnwState * const state);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
 
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.c b/Marlin/src/backtrace/unwinder.cpp
similarity index 93%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwinder.c
rename to Marlin/src/backtrace/unwinder.cpp
index a6e5721868..88a61ee640 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.c
+++ b/Marlin/src/backtrace/unwinder.cpp
@@ -12,7 +12,7 @@
  * File Description: Implementation of the interface into the ARM unwinder.
  **************************************************************************/
 
-#ifdef ARDUINO_ARCH_SAM
+#if defined(__arm__) || defined(__thumb__)
 
 #define MODULE_NAME "UNWINDER"
 
@@ -23,8 +23,8 @@
 #include "unwarmbytab.h"
 
 /* These symbols point to the unwind index and should be provide by the linker script */
-extern const UnwTabEntry __exidx_start[];
-extern const UnwTabEntry __exidx_end[];
+extern "C" const UnwTabEntry __exidx_start[];
+extern "C" const UnwTabEntry __exidx_end[];
 
 // Detect if unwind information is present or not
 static int HasUnwindTableInfo(void) {
diff --git a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.h b/Marlin/src/backtrace/unwinder.h
similarity index 98%
rename from Marlin/src/HAL/HAL_DUE/backtrace/unwinder.h
rename to Marlin/src/backtrace/unwinder.h
index 8ff80ebc8b..683a29e336 100644
--- a/Marlin/src/HAL/HAL_DUE/backtrace/unwinder.h
+++ b/Marlin/src/backtrace/unwinder.h
@@ -17,7 +17,6 @@
 #define UNWINDER_H
 
 #include <stdint.h>
-#include <stdbool.h>
 
 /** \def UNW_DEBUG
  * If this define is set, additional information will be produced while
@@ -161,10 +160,6 @@ typedef struct {
   uint32_t pc;
 } UnwindFrame;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /** Start unwinding the current stack.
  * This will unwind the stack starting at the PC value supplied to in the
  * link register (i.e. not a normal register) and the stack pointer value
@@ -177,8 +172,4 @@ extern "C" {
  */
 UnwResult UnwindStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* UNWINDER_H */
diff --git a/Marlin/src/backtrace/unwmemaccess.cpp b/Marlin/src/backtrace/unwmemaccess.cpp
new file mode 100644
index 0000000000..f7041d52d6
--- /dev/null
+++ b/Marlin/src/backtrace/unwmemaccess.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk
+ * Updated, adapted and several bug fixes on 2018 by Eduardo José Tagle
+ *
+ * This program is PUBLIC DOMAIN.
+ * This means that there is no copyright and anyone is able to take a copy
+ * for free and use it as they wish, with or without modifications, and in
+ * any context, commercially or otherwise. The only limitation is that I
+ * don't guarantee that the software is fit for any purpose or accept any
+ * liability for it's use or misuse - this software is without warranty.
+ ***************************************************************************
+ * File Description: Utility functions to access memory
+ **************************************************************************/
+
+#if defined(__arm__) || defined(__thumb__)
+
+#include "unwmemaccess.h"
+
+/* Validate address */
+
+#ifdef ARDUINO_ARCH_SAM
+// For DUE, valid address ranges are
+//  SRAM  (0x20070000 - 0x20088000) (96kb)
+//  FLASH (0x00080000 - 0x00100000) (512kb)
+//
+#define START_SRAM_ADDR   0x20070000
+#define END_SRAM_ADDR     0x20088000
+#define START_FLASH_ADDR  0x00080000
+#define END_FLASH_ADDR    0x00100000
+#endif
+
+#ifdef TARGET_LPC1768
+// For LPC1769:
+//  SRAM  (0x10000000 - 0x10008000) (32kb)
+//  FLASH (0x00000000 - 0x00080000) (512kb)
+//
+#define START_SRAM_ADDR   0x10000000
+#define END_SRAM_ADDR     0x10008000
+#define START_FLASH_ADDR  0x00000000
+#define END_FLASH_ADDR    0x00080000
+#endif
+
+#if 0
+// For STM32F103CBT6
+//  SRAM  (0x20000000 - 0x20005000) (20kb)
+//  FLASH (0x00000000 - 0x00020000) (128kb)
+//
+#define START_SRAM_ADDR   0x20000000
+#define END_SRAM_ADDR     0x20005000
+#define START_FLASH_ADDR  0x00000000
+#define END_FLASH_ADDR    0x00020000
+#endif
+
+#ifdef __STM32F1__
+// For STM32F103ZET6/STM32F103VET6
+//  SRAM  (0x20000000 - 0x20010000) (64kb)
+//  FLASH (0x00000000 - 0x00080000) (512kb)
+//
+#define START_SRAM_ADDR   0x20000000
+#define END_SRAM_ADDR     0x20010000
+#define START_FLASH_ADDR  0x00000000
+#define END_FLASH_ADDR    0x00080000
+#endif
+
+#ifdef STM32F7
+// For STM32F765 in BORG
+//  SRAM  (0x20000000 - 0x20080000) (512kb)
+//  FLASH (0x08000000 - 0x08100000) (1024kb)
+//
+#define START_SRAM_ADDR   0x20000000
+#define END_SRAM_ADDR     0x20080000
+#define START_FLASH_ADDR  0x08000000
+#define END_FLASH_ADDR    0x08100000
+#endif
+
+#ifdef __MK64FX512__
+// For MK64FX512 in TEENSY 3.5
+//  SRAM  (0x1FFF0000 - 0x20020000) (192kb)
+//  FLASH (0x00000000 - 0x00080000) (512kb)
+//
+#define START_SRAM_ADDR   0x1FFF0000
+#define END_SRAM_ADDR     0x20020000
+#define START_FLASH_ADDR  0x00000000
+#define END_FLASH_ADDR    0x00080000
+#endif
+
+#ifdef __MK66FX1M0__
+// For MK66FX1M0 in TEENSY 3.6
+//  SRAM  (0x1FFF0000 - 0x20030000) (256kb)
+//  FLASH (0x00000000 - 0x00140000) (1.25Mb)
+//
+#define START_SRAM_ADDR   0x1FFF0000
+#define END_SRAM_ADDR     0x20030000
+#define START_FLASH_ADDR  0x00000000
+#define END_FLASH_ADDR    0x00140000
+#endif
+
+static bool validate_addr(uint32_t addr) {
+
+  // Address must be in SRAM range
+  if (addr >= START_SRAM_ADDR && addr < END_SRAM_ADDR)
+    return true;
+
+  // Or in FLASH range
+  if (addr >= START_FLASH_ADDR && addr < END_FLASH_ADDR)
+    return true;
+
+  return false;
+}
+
+bool UnwReadW(const uint32_t a, uint32_t *v) {
+  if (!validate_addr(a))
+    return false;
+
+  *v = *(uint32_t *)a;
+  return true;
+}
+
+bool UnwReadH(const uint32_t a, uint16_t *v) {
+  if (!validate_addr(a))
+    return false;
+
+  *v = *(uint16_t *)a;
+  return true;
+}
+
+bool UnwReadB(const uint32_t a, uint8_t *v) {
+  if (!validate_addr(a))
+    return false;
+
+  *v = *(uint8_t *)a;
+  return true;
+}
+
+#endif
+
diff --git a/Marlin/src/backtrace/unwmemaccess.h b/Marlin/src/backtrace/unwmemaccess.h
new file mode 100644
index 0000000000..5405f3a673
--- /dev/null
+++ b/Marlin/src/backtrace/unwmemaccess.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+ * ARM Stack Unwinder, Michael.McTernan.2001@cs.bris.ac.uk
+ * Updated, adapted and several bug fixes on 2018 by Eduardo José Tagle
+ *
+ * This program is PUBLIC DOMAIN.
+ * This means that there is no copyright and anyone is able to take a copy
+ * for free and use it as they wish, with or without modifications, and in
+ * any context, commerically or otherwise. The only limitation is that I
+ * don't guarantee that the software is fit for any purpose or accept any
+ * liablity for it's use or misuse - this software is without warranty.
+ ***************************************************************************
+ * File Description: Utility functions to access memory
+ **************************************************************************/
+
+#ifndef UNWMEMACCESS_H
+#define UNWMEMACCESS_H
+
+#include "unwarm.h"
+#include <stdint.h>
+
+bool UnwReadW(const uint32_t a, uint32_t *v);
+bool UnwReadH(const uint32_t a, uint16_t *v);
+bool UnwReadB(const uint32_t a, uint8_t *v);
+
+#endif
+
-- 
GitLab