M CMakeLists.txt => CMakeLists.txt +0 -2
@@ 113,8 113,6 @@ add_subdirectory(third-party)
if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
add_subdirectory(board/linux/libiosyscalls)
-elseif(${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
- add_subdirectory(board/rt1051)
endif()
add_subdirectory(source)
D board/rt1051/CMakeLists.txt => board/rt1051/CMakeLists.txt +0 -13
@@ 1,13 0,0 @@
-add_library(CrashCatcherARM STATIC)
-
-target_sources(CrashCatcherARM
- PRIVATE
- crashdump/CrashCatcher_armv7m.S
-)
-
-set_source_files_properties(crashdump/CrashCatcher_armv7m.S PROPERTIES LANGUAGE C)
-
-target_link_libraries(CrashCatcherARM
- PRIVATE
- CrashCatcher::CrashCatcher
-)
M board/rt1051/crashdump/consoledump.cpp => board/rt1051/crashdump/consoledump.cpp +23 -13
@@ 120,7 120,7 @@ struct __attribute__((packed)) abfsr_t
struct __attribute__((packed)) syslog_t
{
- syslog_exception_stack_frame_t stackFrame;
+ CrashCatcherStackedRegisters stackFrame;
struct
{
hfsr_t hfsr; /// Hard Fault Fault Status Register
@@ 134,9 134,9 @@ struct __attribute__((packed)) syslog_t
namespace
{
- static void printHardFaultInfo(const syslog_t &syslog)
+ void printCrashInfo(const syslog_t &syslog)
{
- LOG_FATAL("!!! HardFault Detected !!!");
+ LOG_FATAL("!!! Crash Occured !!!");
LOG_FATAL("* Stack Frame:");
LOG_FATAL("R0 = 0x%0" PRIX32, syslog.stackFrame.r0);
LOG_FATAL("R1 = 0x%0" PRIX32, syslog.stackFrame.r1);
@@ 225,16 225,26 @@ namespace
if (abfsr.eppb)
LOG_FATAL(" - EPPB: Asynchronous fault on EPPB interface");
}
+
+ syslog_t syslogFrom(const CrashCatcherInfo *info)
+ {
+ syslog_t syslog;
+
+ syslog.stackFrame = *info->pSP;
+ syslog.registers.hfsr.all = SCB->HFSR;
+ syslog.registers.cfsr.all = SCB->CFSR;
+ syslog.registers.mmfar = SCB->MMFAR;
+ syslog.registers.bfar = SCB->BFAR;
+ syslog.registers.abfsr.all = SCB->ABFSR;
+
+ return syslog;
+ }
} // namespace
-extern "C" void crashCatcherExtPrintConsoleHF(uint32_t sp)
+namespace crashdump
{
- static syslog_t syslog = {};
- syslog.stackFrame = *(reinterpret_cast<syslog_exception_stack_frame_t *>(sp));
- syslog.registers.hfsr.all = SCB->HFSR;
- syslog.registers.cfsr.all = SCB->CFSR;
- syslog.registers.mmfar = SCB->MMFAR;
- syslog.registers.bfar = SCB->BFAR;
- syslog.registers.abfsr.all = SCB->ABFSR;
- printHardFaultInfo(syslog);
-}
+ void printCrashInfo(const CrashCatcherInfo *info)
+ {
+ ::printCrashInfo(syslogFrom(info));
+ }
+} // namespace crashdump
M board/rt1051/crashdump/consoledump.hpp => board/rt1051/crashdump/consoledump.hpp +5 -15
@@ 3,20 3,10 @@
#pragma once
-#include <cstdint>
+#include <CrashCatcher/CrashCatcher.h>
-// Exception Stack Frame
-typedef struct __attribute__((packed))
+namespace crashdump
{
- uint32_t r0;
- uint32_t r1;
- uint32_t r2;
- uint32_t r3;
- uint32_t r12;
- uint32_t lr;
- uint32_t pc;
- uint32_t psr;
-#if defined(__ARM_ARCH_7EM__)
- uint32_t s[16];
-#endif
-} syslog_exception_stack_frame_t;
+ void printCrashInfo(const CrashCatcherInfo *info);
+
+} // namespace crashdump
M board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +3 -1
@@ 3,11 3,12 @@
#pragma GCC optimize("Og")
-#include <CrashCatcher.h>
+#include <CrashCatcher/CrashCatcher.h>
#include <log.hpp>
#include <date/date.h>
#include "crashdumpwriter.hpp"
+#include "consoledump.hpp"
const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
{
@@ 33,6 34,7 @@ const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
void CrashCatcher_DumpStart(const CrashCatcherInfo *pInfo)
{
+ crashdump::printCrashInfo(pInfo);
crashdump::CrashDumpWriter::instance().openDump();
}
M products/PurePhone/CMakeLists.txt => products/PurePhone/CMakeLists.txt +0 -1
@@ 73,7 73,6 @@ target_link_libraries(PurePhone
${LWIP_LIBRARIES}
"$<$<STREQUAL:${PROJECT_TARGET},TARGET_Linux>:iosyscalls>"
"$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:CrashCatcher::CrashCatcher>"
- "$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:CrashCatcherARM>"
)
target_link_options(PurePhone PUBLIC ${TARGET_LINK_OPTIONS})
M third-party/CrashDebug/CMakeLists.txt => third-party/CrashDebug/CMakeLists.txt +1 -10
@@ 7,13 7,4 @@ ExternalProject_Add(CrashDebug
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/bin && ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/src/bins/lin64/CrashDebug ${CMAKE_CURRENT_BINARY_DIR}/bin
)
-add_library(CrashCatcher INTERFACE)
-add_library(CrashCatcher::CrashCatcher ALIAS CrashCatcher)
-
-target_include_directories(CrashCatcher
- INTERFACE
- src/CrashCatcher/include
- src/CrashCatcher/Core/src
-)
-
-target_sources(CrashCatcher INTERFACE src/CrashCatcher/Core/src/CrashCatcher.c)
+add_subdirectory(CrashCatcher)
A third-party/CrashDebug/CrashCatcher/CMakeLists.txt => third-party/CrashDebug/CrashCatcher/CMakeLists.txt +32 -0
@@ 0,0 1,32 @@
+add_library(CrashCatcher OBJECT)
+add_library(CrashCatcher::CrashCatcher ALIAS CrashCatcher)
+
+# These files were copied from 'third-party/CrashDebug/src/CrashCatcher' and modified.
+#
+# Reasons for modification:
+# * CrashCatcher_armv7m.S: need to enter MCU user mode in order to create a file dump.
+#
+# * CrashCatcherPriv.h
+# CrashCatcher.c
+# CrashCatcher.h : need to expose MCU registers' state for console dump.
+
+target_sources(
+ CrashCatcher
+ PRIVATE
+ CrashCatcherPriv.h
+ CrashCatcher.c
+ CrashCatcher_armv7m.S
+ PUBLIC
+ include/CrashCatcher/CrashCatcher.h
+)
+
+set_source_files_properties(
+ CrashCatcher_armv7m.S
+ PROPERTIES LANGUAGE C
+)
+
+target_include_directories(
+ CrashCatcher
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+)
A third-party/CrashDebug/CrashCatcher/CrashCatcher.c => third-party/CrashDebug/CrashCatcher/CrashCatcher.c +284 -0
@@ 0,0 1,284 @@
+/* Copyright (C) 2018 Adam Green (https://github.com/adamgreen)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+#include <CrashCatcher/CrashCatcher.h>
+#include "CrashCatcherPriv.h"
+#include <string.h>
+
+
+/* Test harness will define this value on 64-bit machine to provide upper 32-bits of pointer addresses. */
+CRASH_CATCHER_TEST_WRITEABLE uint64_t g_crashCatcherTestBaseAddress;
+
+/* The unit tests can point the core to a fake location for the SCB->CPUID register. */
+CRASH_CATCHER_TEST_WRITEABLE uint32_t* g_pCrashCatcherCpuId = (uint32_t*)0xE000ED00;
+
+/* The unit tests can point the core to a fake location for the fault status registers. */
+CRASH_CATCHER_TEST_WRITEABLE uint32_t* g_pCrashCatcherFaultStatusRegisters = (uint32_t*)0xE000ED28;
+
+/* The unit tests can point the core to a fake location for the Coprocessor Access Control Register. */
+CRASH_CATCHER_TEST_WRITEABLE uint32_t* g_pCrashCatcherCoprocessorAccessControlRegister = (uint32_t*)0xE000ED88;
+
+
+/* Fault handler will switch MSP to use this area as the stack while CrashCatcher code is running.
+ NOTE: If you change the size of this buffer, it also needs to be changed in the HardFault_Handler (in
+ FaultHandler_arm*.S) when initializing the stack pointer. */
+uint32_t g_crashCatcherStack[CRASH_CATCHER_STACK_WORD_COUNT];
+
+
+typedef struct
+{
+ const CrashCatcherExceptionRegisters* pExceptionRegisters;
+ uint32_t flags;
+ CrashCatcherInfo info;
+} Object;
+
+
+static Object initStackPointers(const CrashCatcherExceptionRegisters* pExceptionRegisters);
+static uint32_t getAddressOfExceptionStack(const CrashCatcherExceptionRegisters* pExceptionRegisters);
+static void* uint32AddressToPointer(uint32_t address);
+static void advanceStackPointerToValueBeforeException(Object* pObject);
+static int areFloatingPointRegistersAutoStacked(const Object* pObject);
+static void initFloatingPointFlag(Object* pObject);
+static int areFloatingPointCoprocessorsEnabled(void);
+static void initIsBKPT(Object* pObject);
+static int isBKPT(uint16_t instruction);
+static void setStackSentinel(void);
+static void dumpSignature(void);
+static void dumpFlags(const Object* pObject);
+static void dumpR0toR3(const Object* pObject);
+static void dumpR4toR11(const Object* pObject);
+static void dumpR12(const Object* pObject);
+static void dumpSP(const Object* pObject);
+static void dumpLR_PC_PSR(const Object* pObject);
+static void dumpMSPandPSPandExceptionPSR(const Object* pObject);
+static void dumpFloatingPointRegisters(const Object* pObject);
+static void dumpMemoryRegions(const CrashCatcherMemoryRegion* pRegion);
+static void checkStackSentinelForStackOverflow(void);
+static int isARMv6MDevice(void);
+static void dumpFaultStatusRegisters(void);
+static void advanceProgramCounterPastHardcodedBreakpoint(const Object* pObject);
+
+
+void CrashCatcher_Entry(const CrashCatcherExceptionRegisters* pExceptionRegisters)
+{
+ Object object = initStackPointers(pExceptionRegisters);
+ advanceStackPointerToValueBeforeException(&object);
+ initFloatingPointFlag(&object);
+ initIsBKPT(&object);
+
+ do
+ {
+ setStackSentinel();
+ CrashCatcher_DumpStart(&object.info);
+ dumpSignature();
+ dumpFlags(&object);
+ dumpR0toR3(&object);
+ dumpR4toR11(&object);
+ dumpR12(&object);
+ dumpSP(&object);
+ dumpLR_PC_PSR(&object);
+ dumpMSPandPSPandExceptionPSR(&object);
+ if (object.flags & CRASH_CATCHER_FLAGS_FLOATING_POINT)
+ dumpFloatingPointRegisters(&object);
+ dumpMemoryRegions(CrashCatcher_GetMemoryRegions());
+ if (!isARMv6MDevice())
+ dumpFaultStatusRegisters();
+ checkStackSentinelForStackOverflow();
+ }
+ while (CrashCatcher_DumpEnd() == CRASH_CATCHER_TRY_AGAIN);
+
+ advanceProgramCounterPastHardcodedBreakpoint(&object);
+}
+
+static Object initStackPointers(const CrashCatcherExceptionRegisters* pExceptionRegisters)
+{
+ Object object;
+ object.pExceptionRegisters = pExceptionRegisters;
+ object.info.sp = getAddressOfExceptionStack(pExceptionRegisters);
+ object.info.pSP = uint32AddressToPointer(object.info.sp);
+ object.flags = 0;
+ return object;
+}
+
+static uint32_t getAddressOfExceptionStack(const CrashCatcherExceptionRegisters* pExceptionRegisters)
+{
+ if (pExceptionRegisters->exceptionLR & LR_PSP)
+ return pExceptionRegisters->psp;
+ else
+ return pExceptionRegisters->msp;
+}
+
+static void* uint32AddressToPointer(uint32_t address)
+{
+ if (sizeof(uint32_t*) == 8)
+ return (void*)(unsigned long)((uint64_t)address | g_crashCatcherTestBaseAddress);
+ else
+ return (void*)(unsigned long)address;
+}
+
+static void advanceStackPointerToValueBeforeException(Object* pObject)
+{
+ /* Cortex-M processor always push 8 integer registers on the stack. */
+ pObject->info.sp += 8 * sizeof(uint32_t);
+ /* ARMv7-M processors can also push 16 single-precision floating point registers, FPSCR and a padding word. */
+ if (areFloatingPointRegistersAutoStacked(pObject))
+ pObject->info.sp += (16 + 1 + 1) * sizeof(uint32_t);
+ /* Cortex-M processor may also have had to force 8-byte alignment before auto stacking registers. */
+ pObject->info.sp |= (pObject->info.pSP->psr & PSR_STACK_ALIGN) ? 4 : 0;
+}
+
+static int areFloatingPointRegistersAutoStacked(const Object* pObject)
+{
+ return 0 == (pObject->pExceptionRegisters->exceptionLR & LR_FLOAT);
+}
+
+static void initFloatingPointFlag(Object* pObject)
+{
+ if (areFloatingPointCoprocessorsEnabled())
+ pObject->flags |= CRASH_CATCHER_FLAGS_FLOATING_POINT;
+}
+
+static int areFloatingPointCoprocessorsEnabled(void)
+{
+ static const uint32_t coProcessor10and11EnabledBits = 5 << 20;
+ uint32_t coprocessorAccessControl = *g_pCrashCatcherCoprocessorAccessControlRegister;
+
+ return (coprocessorAccessControl & (coProcessor10and11EnabledBits)) == coProcessor10and11EnabledBits;
+}
+
+static void initIsBKPT(Object* pObject)
+{
+ const uint16_t *pInstruction = uint32AddressToPointer(pObject->info.pSP->pc);
+
+ pObject->info.isBKPT = isBKPT(*pInstruction);
+}
+
+static int isBKPT(uint16_t instruction)
+{
+ return (instruction & 0xFF00) == 0xBE00;
+}
+
+static void setStackSentinel(void)
+{
+ g_crashCatcherStack[0] = CRASH_CATCHER_STACK_SENTINEL;
+}
+
+static void dumpSignature(void)
+{
+ static const uint8_t signature[4] = {CRASH_CATCHER_SIGNATURE_BYTE0,
+ CRASH_CATCHER_SIGNATURE_BYTE1,
+ CRASH_CATCHER_VERSION_MAJOR,
+ CRASH_CATCHER_VERSION_MINOR};
+
+ CrashCatcher_DumpMemory(signature, CRASH_CATCHER_BYTE, sizeof(signature));
+}
+
+static void dumpFlags(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->flags, CRASH_CATCHER_BYTE, sizeof(pObject->flags));
+}
+
+static void dumpR0toR3(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->info.pSP->r0, CRASH_CATCHER_BYTE, 4 * sizeof(uint32_t));
+}
+
+static void dumpR4toR11(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->pExceptionRegisters->r4, CRASH_CATCHER_BYTE, (11 - 4 + 1) * sizeof(uint32_t));
+}
+
+static void dumpR12(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->info.pSP->r12, CRASH_CATCHER_BYTE, sizeof(uint32_t));
+}
+
+static void dumpSP(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->info.sp, CRASH_CATCHER_BYTE, sizeof(uint32_t));
+}
+
+static void dumpLR_PC_PSR(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->info.pSP->lr, CRASH_CATCHER_BYTE, 3 * sizeof(uint32_t));
+}
+
+static void dumpMSPandPSPandExceptionPSR(const Object* pObject)
+{
+ CrashCatcher_DumpMemory(&pObject->pExceptionRegisters->msp, CRASH_CATCHER_BYTE, 3 * sizeof(uint32_t));
+}
+
+static void dumpFloatingPointRegisters(const Object* pObject)
+{
+ uint32_t allFloatingPointRegisters[32 + 1];
+ if (areFloatingPointRegistersAutoStacked(pObject))
+ {
+ /* Copy the upper floats first as that will cause a lazy copy of the auto-stacked registers. */
+ CrashCatcher_CopyUpperFloatingPointRegisters(&allFloatingPointRegisters[16]);
+ memcpy(&allFloatingPointRegisters[0], &pObject->info.pSP->floats, sizeof(pObject->info.pSP->floats));
+ allFloatingPointRegisters[32] = pObject->info.pSP->fpscr;
+ }
+ else
+ {
+ CrashCatcher_CopyAllFloatingPointRegisters(allFloatingPointRegisters);
+ }
+ CrashCatcher_DumpMemory(allFloatingPointRegisters, CRASH_CATCHER_BYTE, sizeof(allFloatingPointRegisters));
+}
+
+static void dumpMemoryRegions(const CrashCatcherMemoryRegion* pRegion)
+{
+ while (pRegion && pRegion->startAddress != 0xFFFFFFFF)
+ {
+ /* Just dump the two addresses in pRegion. The element size isn't required. */
+ CrashCatcher_DumpMemory(pRegion, CRASH_CATCHER_BYTE, 2 * sizeof(uint32_t));
+ CrashCatcher_DumpMemory(uint32AddressToPointer(pRegion->startAddress),
+ pRegion->elementSize,
+ (pRegion->endAddress - pRegion->startAddress) / pRegion->elementSize);
+ pRegion++;
+ }
+}
+
+static void checkStackSentinelForStackOverflow(void)
+{
+ if (g_crashCatcherStack[0] != CRASH_CATCHER_STACK_SENTINEL)
+ {
+ uint8_t value[4] = {0xAC, 0xCE, 0x55, 0xED};
+ CrashCatcher_DumpMemory(value, CRASH_CATCHER_BYTE, sizeof(value));
+ }
+}
+
+static int isARMv6MDevice(void)
+{
+ static const uint32_t armv6mArchitecture = 0xC << 16;
+ uint32_t cpuId = *g_pCrashCatcherCpuId;
+ uint32_t architecture = cpuId & (0xF << 16);
+
+ return (architecture == armv6mArchitecture);
+}
+
+static void dumpFaultStatusRegisters(void)
+{
+ uint32_t faultStatusRegistersAddress = (uint32_t)(unsigned long)g_pCrashCatcherFaultStatusRegisters;
+ CrashCatcherMemoryRegion faultStatusRegion[] = { {faultStatusRegistersAddress,
+ faultStatusRegistersAddress + 5 * sizeof(uint32_t),
+ CRASH_CATCHER_WORD},
+ {0xFFFFFFFF, 0xFFFFFFFF, CRASH_CATCHER_BYTE} };
+ dumpMemoryRegions(faultStatusRegion);
+}
+
+static void advanceProgramCounterPastHardcodedBreakpoint(const Object* pObject)
+{
+ if (pObject->info.isBKPT)
+ pObject->info.pSP->pc += 2;
+}
A third-party/CrashDebug/CrashCatcher/CrashCatcherPriv.h => third-party/CrashDebug/CrashCatcher/CrashCatcherPriv.h +84 -0
@@ 0,0 1,84 @@
+/* Copyright (C) 2017 Adam Green (https://github.com/adamgreen)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+/* Private header file shared with unit tests. */
+#ifndef _CRASH_CATCHER_PRIV_H_
+#define _CRASH_CATCHER_PRIV_H_
+
+
+/* Definitions used by assembly language and C code. */
+#define CRASH_CATCHER_STACK_WORD_COUNT 125
+
+/* Does this device support THUMB instructions for FPU access? */
+#ifdef __ARM_ARCH_7EM__
+#define CRASH_CATCHER_WITH_FPU 1
+#else
+#define CRASH_CATCHER_WITH_FPU 0
+#endif
+
+
+/* Definitions only required from C code. */
+#if !defined(__ASSEMBLER__) || (!__ASSEMBLER__)
+
+#include <stdint.h>
+
+
+/* Bit in LR to indicate whether PSP was used for automatic stacking of registers during exception entry. */
+#define LR_PSP (1 << 2)
+
+/* Bit in LR set to 0 when automatic stacking of floating point registers occurs during exception handling. */
+#define LR_FLOAT (1 << 4)
+
+
+/* Bit in auto stacked xPSR which indicates whether stack was force 8-byte aligned. */
+#define PSR_STACK_ALIGN (1 << 9)
+
+/* This structure is filled in by the Hard Fault exception handler (or unit test) and then passed in as a parameter to
+ CrashCatcher_Entry(). */
+typedef struct
+{
+ uint32_t msp;
+ uint32_t psp;
+ uint32_t exceptionPSR;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t exceptionLR;
+} CrashCatcherExceptionRegisters;
+
+/* This is the area of memory that would normally be used for the stack when running on an actual Cortex-M
+ processor. Unit tests can write to this buffer to simulate stack overflow. */
+extern uint32_t g_crashCatcherStack[CRASH_CATCHER_STACK_WORD_COUNT];
+
+
+/* The main entry point into CrashCatcher. Is called from the HardFault exception handler and unit tests. */
+void CrashCatcher_Entry(const CrashCatcherExceptionRegisters* pExceptionRegisters);
+
+/* Called from CrashCatcher core to copy all floating point registers to supplied buffer. The supplied buffer must be
+ large enough to contain 33 32-bit values (S0-S31 & FPCSR). */
+void CrashCatcher_CopyAllFloatingPointRegisters(uint32_t* pBuffer);
+
+/* Called from CrashCatcher core to copy upper 16 floating point registers to supplied buffer. The supplied buffer must be
+ large enough to contain 16 32-bit values (S16-S31). */
+void CrashCatcher_CopyUpperFloatingPointRegisters(uint32_t* pBuffer);
+
+#endif // #if !defined(__ASSEMBLER__) || (!__ASSEMBLER__)
+
+
+#endif /* _CRASH_CATCHER_PRIV_H_ */
R board/rt1051/crashdump/CrashCatcher_armv7m.S => third-party/CrashDebug/CrashCatcher/CrashCatcher_armv7m.S +2 -11
@@ 53,21 53,12 @@ HardFault_Handler:
mrs r1, msp
ldr sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
push.w {r1-r11,lr}
- // Call oryginal console dump
+
+ // Call original console dump
ldr r0,=crash_orig_stack
str sp, [r0]
mov sp, r1
- // Call console crash handler
- mrs r0, msp
- mov sp, r0
- tst lr, #4
- ite eq
- mrseq r0,msp
- mrsne r0,psp
- push {lr}
- bl crashCatcherExtPrintConsoleHF
- pop {lr}
ldr r0,=crash_orig_stack
ldr sp, [r0]
A third-party/CrashDebug/CrashCatcher/include/CrashCatcher/CrashCatcher.h => third-party/CrashDebug/CrashCatcher/include/CrashCatcher/CrashCatcher.h +176 -0
@@ 0,0 1,176 @@
+/* Copyright (C) 2018 Adam Green (https://github.com/adamgreen)
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+#ifndef _CRASH_CATCHER_H_
+#define _CRASH_CATCHER_H_
+
+
+#include <stdint.h>
+#include <stdlib.h>
+
+
+#define TRUE 1
+#define FALSE 0
+
+
+/* The crash dump start with a four byte header. The first two bytes are "cC", the third byte is the major version
+ number, and the fourth bytes is the minor version number. */
+#define CRASH_CATCHER_SIGNATURE_BYTE0 'c'
+#define CRASH_CATCHER_SIGNATURE_BYTE1 'C'
+#define CRASH_CATCHER_VERSION_MAJOR 3
+#define CRASH_CATCHER_VERSION_MINOR 0
+
+/* The second word of the dump contains flags. These are the allowed flags. */
+/* Flag to indicate that 32 single-precision floating point registers and FPSCR will follow integer registers. */
+#define CRASH_CATCHER_FLAGS_FLOATING_POINT (1 << 0)
+
+
+/* This magic value will be found as the last word in a crash dump if the fault handler overflowed the stack while
+ generating the crash dump. */
+#define CRASH_CATCHER_STACK_SENTINEL 0xACCE55ED
+
+/* This structure contains the integer registers that are automatically stacked by Cortex-M processor when it enters
+ an exception handler. */
+typedef struct
+{
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r12;
+ uint32_t lr;
+ uint32_t pc;
+ uint32_t psr;
+ /* The following floating point registers are only stacked when the LR_FLOAT bit is set in exceptionLR. */
+ uint32_t floats[16];
+ uint32_t fpscr;
+ uint32_t reserved; /* keeps 8-byte alignment */
+} CrashCatcherStackedRegisters;
+
+/* Particulars of crash provided to CrashCatcher_DumpStart(). */
+typedef struct
+{
+ /* The SP, Stack Pointer, contained this value at the time of the fault. */
+ uint32_t sp;
+ CrashCatcherStackedRegisters *pSP;
+ /* Was this fault actually just a hardcoded breakpoint from which it is safe to continue. */
+ int isBKPT;
+} CrashCatcherInfo;
+
+
+/* The crash dump will have one of these entries for each memory region included in the dump file. */
+typedef struct
+{
+ uint32_t startAddress;
+ uint32_t endAddress;
+} CrashCatcherMemoryRegionInfo;
+
+/* Supported element sizes to be used with CrashCatcher_DumpMemory calls. */
+typedef enum
+{
+ CRASH_CATCHER_BYTE = 1,
+ CRASH_CATCHER_HALFWORD = 2,
+ CRASH_CATCHER_WORD = 4
+} CrashCatcherElementSizes;
+
+
+/* Codes to be returned from an implementation's CrashCathcer_DumpEnd() handler. */
+typedef enum
+{
+ /* Crash Catcher should loop around and try dumping again incase user missed it previous time. */
+ CRASH_CATCHER_TRY_AGAIN = 0,
+ /* Crash Catcher should exit and return to caller. This is used during unit testing or if the crash cause was
+ actually a hardcoded breakpoint that should be logged and then execution continued. */
+ CRASH_CATCHER_EXIT
+} CrashCatcherReturnCodes;
+
+
+/* An array of these structures is returned from CrashCatcher_GetMemoryRegions() to indicate what regions of memory
+ should be dumped as part of the crash dump. The last entry should contain a starting address of 0xFFFFFFFF to
+ indicate that the end of the list has been encountered. */
+typedef struct
+{
+ /* The first address of the element to be dumped for this region of memory. */
+ /* The last region in the array return from CrashCatcher_GetMemoryRegions() must set this to 0xFFFFFFFF */
+ uint32_t startAddress;
+ /* Stop dumping the region once this address is encountered. The dump isn't inclusive of this address. */
+ /* It must be greater than startAddress. */
+ uint32_t endAddress;
+ /* This should be set to CRASH_CATCHER_BYTE except for peripheral registers which don't support 8-bit reads. */
+ CrashCatcherElementSizes elementSize;
+} CrashCatcherMemoryRegion;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* The following functions must be provided by a specific dumping implementation. The Core CrashCatcher calls these
+ routines to have an implementation dump the bytes associated with the current crash. */
+
+/* Called at the beginning of crash dump. You should provide an implementation which prepares for the dump by opening
+ a dump file, prompting the user to begin a crash dump, or whatever makes sense for your scenario. */
+void CrashCatcher_DumpStart(const CrashCatcherInfo* pInfo);
+
+/* Called to obtain an array of regions in memory that should be dumped as part of the crash. This will typically
+ be all RAM regions that contain volatile data. For some crash scenarios, a user may decide to also add peripheral
+ registers of interest (ie. dump some ethernet registers when you are encountering crashes in the network stack.)
+ If NULL is returned from this function, the core will only dump the registers. */
+const CrashCatcherMemoryRegion* CrashCatcher_GetMemoryRegions(void);
+
+/* Called to dump the next chunk of memory to the dump (this memory may point to register contents which has been copied
+ to memory by CrashCatcher already. The element size will be 8-bits, 16-bits, or 32-bits. The implementation should
+ use reads of the specified size since some memory locations may only support the indicated size. */
+void CrashCatcher_DumpMemory(const void* pvMemory, CrashCatcherElementSizes elementSize, size_t elementCount);
+
+/* Called at the end of crash dump. You should provide an implementation which cleans up at the end of dump. This could
+ include closing a dump file, blinking LEDs, infinite looping, and/or returning CRASH_CATCHER_TRY_AGAIN if
+ CrashCatcher should prepare to dump again incase user missed the first attempt. */
+CrashCatcherReturnCodes CrashCatcher_DumpEnd(void);
+
+
+/* The following functions must be provided by a hex dumping implementation. Such implementations will also have to
+ implement the core CrashCatcher_GetMemoryRegions() API as well. The HexDump version of CrashCatcher calls these
+ routines to have an implementation query the user when they are ready for the dump to start and actually dump the
+ hex data to the user a character at a time. */
+
+/* Called to receive a character of data from the user. Typically this is in response to a "Press any key" type of
+ prompt to the user. This function should be blocking. */
+int CrashCatcher_getc(void);
+
+/* Called to send a character of hex dump data to the user. */
+void CrashCatcher_putc(int c);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* Macros which can generate a few forms of crashes. */
+#define CRASH_CATCHER_READ_FAULT() (*(volatile unsigned int*)0xFFFFFFF0)
+#define CRASH_CATCHER_WRITE_FAULT() (*(volatile unsigned int*)0xFFFFFFF0 = 0x0)
+#define CRASH_CATCHER_INVALID_INSTRUCTION() { __asm volatile (".word 0xDE00"); }
+
+/* Macro used to insert hardcoded breakpoint into user's code. */
+#define CRASH_CATCHER_BREAKPOINT() { __asm volatile ("bkpt #0"); }
+
+/* Macro used to make some globals writeable from unit tests but constant when running on ARM processors. */
+#ifdef RUNNING_HOST_TESTS
+ #define CRASH_CATCHER_TEST_WRITEABLE
+#else
+ #define CRASH_CATCHER_TEST_WRITEABLE static const
+#endif
+
+
+#endif /* _CRASH_CATCHER_H_ */