M .gitmodules => .gitmodules +3 -0
@@ 81,3 81,6 @@
path = test/harness
url = ../QAMuditaHarness.git
shallow = true
+[submodule "module-utils/CrashDebug"]
+ path = module-utils/CrashDebug
+ url = git@github.com:adamgreen/CrashDebug.git
M Target_RT1051.cmake => Target_RT1051.cmake +8 -0
@@ 68,6 68,7 @@ set(TARGET_COMPILE_FEATURES
CACHE INTERNAL "" )
+set_property(SOURCE ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/CrashCatcher_armv7m.S PROPERTY LANGUAGE C)
set(TARGET_SOURCES
${CMAKE_CURRENT_LIST_DIR}/board/rt1051/_exit.c
@@ 77,6 78,11 @@ set(TARGET_SOURCES
${CMAKE_CURRENT_LIST_DIR}/board/rt1051/xip/evkbimxrt1050_flexspi_nor_config.c
${CMAKE_CURRENT_LIST_DIR}/board/rt1051/xip/evkbimxrt1050_sdram_ini_dcd.c
${CMAKE_CURRENT_LIST_DIR}/board/rt1051/xip/fsl_flexspi_nor_boot.c
+ ${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/Core/src/CrashCatcher.c
+ ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/CrashCatcher_armv7m.S
+ ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/crashcatcher_impl.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/crashdumpwriter_vfs.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/board/rt1051/crashdump/consoledump.cpp
CACHE INTERNAL ""
)
@@ 87,6 93,8 @@ set(TARGET_DIR_INCLUDES
set(BOARD_DIR_INCLUDES
${CMAKE_CURRENT_LIST_DIR}/board/rt1051/newlib/include
+ ${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/include
+ ${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/Core/src
)
set(TARGET_LIBRARIES
A board/rt1051/crashdump/CrashCatcher_armv7m.S => board/rt1051/crashdump/CrashCatcher_armv7m.S +142 -0
@@ 0,0 1,142 @@
+/* Copyright (C) 2019 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 "CrashCatcherPriv.h"
+
+/* Implementation of ARMv7-M assembly language code to trap exceptions and call CrashCatcher_Entry(). */
+ .text
+ .syntax unified
+ .arch armv7-m
+
+ /* Called on Hard Fault exception. Stacks important registers and calls CrashCatcher_Entry().
+
+ extern "C" void HardFault_Handler(void);
+ */
+ .global HardFault_Handler
+ .type HardFault_Handler, %function
+ .thumb_func
+HardFault_Handler:
+ /* Push the following onto the stack (see CrashCatcherExceptionRegisters structure). The g_crashCatcherStack buffer
+ is reserved for use as the stack while CrashCatcher is running.
+ msp
+ psp
+ exceptionPSR
+ r4
+ r5
+ r6
+ r7
+ r8
+ r9
+ r10
+ r11
+ exceptionLR */
+ // Prevent double fault
+ ldr r0, = crash_orig_stack
+ ldr r0, [r0]
+ cmp r0, #0
+ bne .
+
+ // Create stack for CrashCatcher
+ mrs r3, xpsr
+ mrs r2, psp
+ mrs r1, msp
+ ldr sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
+ push.w {r1-r11,lr}
+ // Call oryginal 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]
+
+ // Call CrashCatcher_Entry with first argument pointing to registers that were just stacked.
+ mov r0, sp
+ ldr r2,=CrashCatcher_Entry // Stack frame exception return
+ mrs r3, psp
+ str r2, [r3, #0x18]
+ str r0, [r3]
+ orr lr, lr, #4 // Back to user stack
+ orr lr, lr, #8 // Back to user mode
+ bx lr // Return from exception and jump to the CatchCatcher_Entry
+ b .
+
+
+ // Let assembler know that we have hit the end of the HardFault_Handler function.
+ .pool
+ .size HardFault_Handler, .-HardFault_Handler
+
+
+
+ /* 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 & FPSCR).
+
+ void CrashCatcher_CopyAllFloatingPointRegisters(uint32_t* pBuffer);
+ */
+ .global CrashCatcher_CopyAllFloatingPointRegisters
+ .type CrashCatcher_CopyAllFloatingPointRegisters, %function
+ .thumb_func
+CrashCatcher_CopyAllFloatingPointRegisters:
+#if CRASH_CATCHER_WITH_FPU
+ // Grab a copy of FPSCR before issuing any other FP instructions.
+ vmrs r1, fpscr
+
+ // Move s0 - s31 to pBuffer.
+ vstmia.32 r0!, {s0 - s31}
+
+ // Move fpscr to pBuffer.
+ str r1, [r0]
+#endif
+ // Return to caller.
+ bx lr
+
+ .pool
+ .size CrashCatcher_CopyAllFloatingPointRegisters, .-CrashCatcher_CopyAllFloatingPointRegisters
+
+
+
+ /* 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);
+ */
+ .global CrashCatcher_CopyUpperFloatingPointRegisters
+ .type CrashCatcher_CopyUpperFloatingPointRegisters, %function
+ .thumb_func
+CrashCatcher_CopyUpperFloatingPointRegisters:
+#if CRASH_CATCHER_WITH_FPU
+ // Move s16 - s31 to pBuffer.
+ vstmia.32 r0!, {s16 - s31}
+#endif
+ // Return to caller.
+ bx lr
+
+ .pool
+ .size CrashCatcher_CopyUpperFloatingPointRegisters, .-CrashCatcher_CopyUpperFloatingPointRegisters
+
+
+
+ .data
+ crash_orig_stack: .long 0
+
A board/rt1051/crashdump/consoledump.cpp => board/rt1051/crashdump/consoledump.cpp +240 -0
@@ 0,0 1,240 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <log/log.hpp>
+
+#include "consoledump.hpp"
+#include "MIMXRT1051.h"
+
+/// Hard Fault Fault Status Register
+struct __attribute__((packed)) hfsr_t
+{
+ union
+ {
+ uint32_t all;
+ struct
+ {
+ uint32_t rsrvd0 : 1;
+ uint32_t vecttbl : 1;
+ uint32_t rsrvd1 : 28;
+ uint32_t forced : 1;
+ uint32_t debugevt : 1;
+ };
+ };
+};
+
+/// MemManage Fault Status Register
+struct __attribute__((packed)) mmfsr_t
+{
+ union
+ {
+ uint8_t all;
+ struct
+ {
+ uint8_t iaccviol : 1;
+ uint8_t daccviol : 1;
+ uint8_t rsrvd2 : 1;
+ uint8_t munstkerr : 1;
+ uint8_t mstkerr : 1;
+ uint8_t mlsperr : 1;
+ uint8_t rsrvd6 : 1;
+ uint8_t mmarvalid : 1;
+ };
+ };
+};
+
+/// BusFault Status Register
+struct __attribute__((packed)) bfsr_t
+{
+ union
+ {
+ uint8_t all;
+ struct
+ {
+ uint8_t ibuserr : 1;
+ uint8_t preciserr : 1;
+ uint8_t impreciserr : 1;
+ uint8_t unstkerr : 1;
+ uint8_t stkerr : 1;
+ uint8_t lsperr : 1;
+ uint8_t rsrvd6 : 1;
+ uint8_t bfarvalid : 1;
+ };
+ };
+};
+
+/// UsageFault Status Register
+struct __attribute__((packed)) ufsr_t
+{
+ union
+ {
+ uint16_t all;
+ struct
+ {
+ uint8_t undefinstr : 1;
+ uint8_t invstate : 1;
+ uint8_t invpc : 1;
+ uint8_t nocp : 1;
+ uint8_t rsrvd4_7 : 3;
+ uint8_t unaligned : 1;
+ uint8_t divbyzero : 1;
+ uint8_t rsrvd10_15 : 6;
+ };
+ };
+};
+
+/// Configurable Fault Status Register
+struct __attribute__((packed)) cfsr_t
+{
+ union
+ {
+ uint32_t all;
+ struct
+ {
+ mmfsr_t mmfsr;
+ bfsr_t bfsr;
+ ufsr_t ufsr;
+ };
+ };
+};
+
+/// Auxiliary Bus Fault Status register
+struct __attribute__((packed)) abfsr_t
+{
+ union
+ {
+ uint32_t all;
+ struct
+ {
+ uint32_t itcm : 1;
+ uint32_t dtcm : 1;
+ uint32_t ahbp : 1;
+ uint32_t axim : 1;
+ uint32_t eppb : 1;
+ uint32_t rsrvd5_7 : 3;
+ uint32_t aximtype : 2;
+ uint32_t rsrvd10_31 : 1;
+ };
+ };
+};
+
+struct __attribute__((packed)) syslog_t
+{
+ syslog_exception_stack_frame_t stackFrame;
+ struct
+ {
+ hfsr_t hfsr; /// Hard Fault Fault Status Register
+ cfsr_t cfsr; /// Configurable Fault Status Register
+ uint32_t mmfar; /// MemManage Fault Address Register
+ uint32_t bfar; /// BusFault Address Register
+ abfsr_t abfsr; /// Auxiliary Bus Fault Status register
+ uint32_t exc_return; /// EXC_RETURN value for the exception being serviced
+ } registers;
+};
+
+namespace
+{
+ static void printHardFaultInfo(const syslog_t &syslog)
+ {
+ LOG_FATAL("!!! HardFault Detected !!!");
+ LOG_FATAL("* Stack Frame:");
+ LOG_FATAL("R0 = 0x%0" PRIX32, syslog.stackFrame.r0);
+ LOG_FATAL("R1 = 0x%0" PRIX32, syslog.stackFrame.r1);
+ LOG_FATAL("R2 = 0x%0" PRIX32, syslog.stackFrame.r2);
+ LOG_FATAL("R3 = 0x%0" PRIX32, syslog.stackFrame.r3);
+ LOG_FATAL("R12 = 0x%0" PRIX32, syslog.stackFrame.r12);
+ LOG_FATAL("LR = 0x%0" PRIX32, syslog.stackFrame.lr);
+ LOG_FATAL("PC = 0x%0" PRIX32, syslog.stackFrame.pc);
+ LOG_FATAL("PSR = 0x%0" PRIX32, syslog.stackFrame.psr);
+
+ LOG_FATAL("* Fault Status Registers:");
+ LOG_FATAL("SCB->HFSR = 0x%0" PRIX32, syslog.registers.hfsr.all);
+ LOG_FATAL("SCB->CFSR = 0x%0" PRIX32, syslog.registers.cfsr.all);
+ LOG_FATAL("SCB->MMAR = 0x%0" PRIX32, syslog.registers.mmfar);
+ LOG_FATAL("SCB->BFAR = 0x%0" PRIX32, syslog.registers.bfar);
+ LOG_FATAL("SCB->ABFSR = 0x%0" PRIX32, syslog.registers.abfsr.all);
+ LOG_FATAL("EXC_RETURN = 0x%0" PRIX32, syslog.registers.exc_return);
+
+ LOG_FATAL("* Details of Fault Status Registers:");
+ hfsr_t hfsr = syslog.registers.hfsr;
+ LOG_FATAL("SCB->HFSR = 0x%0" PRIX32 " - HardFault Status Register", hfsr.all);
+ if (hfsr.debugevt)
+ LOG_FATAL(" - DEBUGEVT: Hard fault caused by debug event");
+ if (hfsr.forced)
+ LOG_FATAL(" - FORCED: Hard fault caused by bus/memory management/usage fault");
+ if (hfsr.vecttbl)
+ LOG_FATAL(" - VECTBL: BusFault on vector table read");
+
+ cfsr_t cfsr = syslog.registers.cfsr;
+ LOG_FATAL("SCB->CFSR = 0x%0" PRIX32 " - Configurable Fault Status Register", cfsr.all);
+ mmfsr_t mmfsr = cfsr.mmfsr;
+ LOG_FATAL("> SCB->MMFSR = 0x%0" PRIX8 " Memory Management Fault Status Register", mmfsr.all);
+ if (mmfsr.mmarvalid)
+ LOG_FATAL(" - MMARVALID: MMAR is valid");
+ if (mmfsr.mlsperr)
+ LOG_FATAL(" - MLSPERR: A MemManage fault occurred during floating-point lazy state preservation");
+ if (mmfsr.mstkerr)
+ LOG_FATAL(" - MSTKERR: MemManage fault on stacking for exception entry");
+ if (mmfsr.munstkerr)
+ LOG_FATAL(" - MUNSTKERR: MemManage fault on unstacking for a return from exception:");
+ if (mmfsr.daccviol)
+ LOG_FATAL(" - DACCVIOL: Data access violation");
+ if (mmfsr.iaccviol)
+ LOG_FATAL(" - IACCVIOL: Instruction access violation");
+
+ bfsr_t bfsr = cfsr.bfsr;
+ LOG_FATAL("> SCB->BFSR = 0x%0" PRIX8 " - Bus Fault Status Register ", bfsr.all);
+ if (bfsr.bfarvalid)
+ LOG_FATAL(" - BFARVALID: BFAR is valid ");
+ if (bfsr.lsperr)
+ LOG_FATAL(" - LSPERR: A bus fault occurred during floating-point lazy state preservation");
+ if (bfsr.stkerr)
+ LOG_FATAL(" - STKERR: Stacking error");
+ if (bfsr.unstkerr)
+ LOG_FATAL(" - UNSTKERR: Unstacking error");
+ if (bfsr.impreciserr)
+ LOG_FATAL(" - IMPREISERR: Imprecise data bus error");
+ if (bfsr.preciserr)
+ LOG_FATAL(" - PRECISERR: Precise data bus error");
+ if (bfsr.ibuserr)
+ LOG_FATAL(" - IBUSERR: Instruction bus error");
+
+ ufsr_t ufsr = cfsr.ufsr;
+ LOG_FATAL("> SCB->UFSR = 0x%0" PRIX16 " - Usage Fault Status Register", ufsr.all);
+ if (ufsr.divbyzero)
+ LOG_FATAL(" - DIVBYZERO: Divide by zero UsageFault");
+ if (ufsr.unaligned)
+ LOG_FATAL(" - UNALIGNED: Unaligned access UsageFault");
+ if (ufsr.nocp)
+ LOG_FATAL(" - NOCP: Attempt to execute a coprocessor instruction");
+ if (ufsr.invpc)
+ LOG_FATAL(" - INVPC: Invalid PC load UsageFault");
+ if (ufsr.invstate)
+ LOG_FATAL(" - INVSTATE: Invalid state UsageFault");
+ if (ufsr.undefinstr)
+ LOG_FATAL(" - UNDEFINSTR: Undefined instruction UsageFault");
+
+ abfsr_t abfsr = syslog.registers.abfsr;
+ LOG_FATAL("SCB->ABFSR = 0x%0" PRIX32 " - Auxiliary Bus Fault Status register", abfsr.all);
+ if (abfsr.itcm)
+ LOG_FATAL(" - ITCM: Asynchronous fault on ITCM interface");
+ if (abfsr.dtcm)
+ LOG_FATAL(" - DTCM: Asynchronous fault on DTCM interface.");
+ if (abfsr.ahbp)
+ LOG_FATAL(" - AHBP: Asynchronous fault on AHBP interface");
+ if (abfsr.eppb)
+ LOG_FATAL(" - EPPB: Asynchronous fault on EPPB interface");
+ }
+} // namespace
+
+extern "C" void crashCatcherExtPrintConsoleHF(uint32_t sp)
+{
+ 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);
+}
A board/rt1051/crashdump/consoledump.hpp => board/rt1051/crashdump/consoledump.hpp +22 -0
@@ 0,0 1,22 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <cstdint>
+
+// Exception Stack Frame
+typedef struct __attribute__((packed))
+{
+ 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;
A board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +56 -0
@@ 0,0 1,56 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma GCC optimize("Og")
+
+#include <CrashCatcher.h>
+
+#include <log/log.hpp>
+#include <module-utils/date/include/date/date.h>
+#include "crashdumpwriter.hpp"
+
+const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
+{
+ // board/rt1051/ldscripts/memory.ld
+ static const CrashCatcherMemoryRegion regions[] = {
+ // SRAM_OC
+ {0x20200000, 0x20210000, CRASH_CATCHER_BYTE},
+ // SRAM_DTC
+ {0x20000000, 0x20070000, CRASH_CATCHER_BYTE},
+ // intentionally skip text section
+ // BOARD_SDRAM_HEAP
+ {0x80620000, 0x81000000, CRASH_CATCHER_BYTE},
+ // end tag
+ {0xFFFFFFFF, 0xFFFFFFFF, CRASH_CATCHER_BYTE},
+ };
+
+ return regions;
+}
+
+void CrashCatcher_DumpStart(const CrashCatcherInfo *pInfo)
+{
+ crashdump::CrashDumpWriter::instance().openDump();
+}
+
+void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elementSize, size_t elementCount)
+{
+ switch (elementSize) {
+ case CRASH_CATCHER_BYTE:
+ crashdump::CrashDumpWriter::instance().writeBytes(static_cast<const std::uint8_t *>(pvMemory), elementCount);
+ break;
+ case CRASH_CATCHER_HALFWORD:
+ crashdump::CrashDumpWriter::instance().writeHalfWords(static_cast<const std::uint16_t *>(pvMemory),
+ elementCount);
+ break;
+ case CRASH_CATCHER_WORD:
+ crashdump::CrashDumpWriter::instance().writeWords(static_cast<const std::uint32_t *>(pvMemory), elementCount);
+ break;
+ }
+}
+
+CrashCatcherReturnCodes CrashCatcher_DumpEnd(void)
+{
+ crashdump::CrashDumpWriter::instance().saveDump();
+ abort();
+ return CRASH_CATCHER_EXIT;
+}
A board/rt1051/crashdump/crashdumpwriter.hpp => board/rt1051/crashdump/crashdumpwriter.hpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <cstdint>
+
+namespace crashdump
+{
+ class CrashDumpWriter
+ {
+ public:
+ static CrashDumpWriter &instance();
+
+ virtual ~CrashDumpWriter() = default;
+
+ virtual void openDump() = 0;
+ virtual void saveDump() = 0;
+
+ virtual void writeBytes(const std::uint8_t *buff, std::size_t size) = 0;
+ virtual void writeHalfWords(const std::uint16_t *buff, std::size_t size) = 0;
+ virtual void writeWords(const std::uint32_t *buff, std::size_t size) = 0;
+ };
+
+} // namespace crashdump
A board/rt1051/crashdump/crashdumpwriter_vfs.cpp => board/rt1051/crashdump/crashdumpwriter_vfs.cpp +56 -0
@@ 0,0 1,56 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "crashdumpwriter_vfs.hpp"
+
+#include <log/log.hpp>
+#include <fcntl.h>
+#include "purefs/vfs_subsystem.hpp"
+
+namespace crashdump
+{
+ void CrashDumpWriterVFS::openDump()
+ {
+ std::array<char, 64> crashDumpFileName;
+ formatCrashDumpFileName(crashDumpFileName);
+
+ vfs = purefs::subsystem::vfs_core();
+ dumpFd = vfs->open(crashDumpFileName.data(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+ if (dumpFd < 0) {
+ LOG_FATAL("Failed to open crash dump file [%s]. Won't be able to save crash info.",
+ crashDumpFileName.data());
+ }
+ }
+
+ void CrashDumpWriterVFS::saveDump()
+ {
+ vfs->close(dumpFd);
+ }
+
+ void CrashDumpWriterVFS::writeBytes(const uint8_t *buff, std::size_t size)
+ {
+ vfs->write(dumpFd, reinterpret_cast<const char *>(buff), size);
+ }
+
+ void CrashDumpWriterVFS::writeHalfWords(const uint16_t *buff, std::size_t size)
+ {
+ for (std::size_t n = 0; n < size; ++n) {
+ writeBytes(reinterpret_cast<const uint8_t *>(buff + n), sizeof(uint16_t));
+ }
+ }
+
+ void CrashDumpWriterVFS::writeWords(const uint32_t *buff, std::size_t size)
+ {
+ for (std::size_t n = 0; n < size; ++n) {
+ writeBytes(reinterpret_cast<const uint8_t *>(buff + n), sizeof(uint32_t));
+ }
+ }
+
+ CrashDumpWriter &CrashDumpWriter::instance()
+ {
+ static CrashDumpWriterVFS writer;
+ return writer;
+ }
+
+} // namespace crashdump
A board/rt1051/crashdump/crashdumpwriter_vfs.hpp => board/rt1051/crashdump/crashdumpwriter_vfs.hpp +44 -0
@@ 0,0 1,44 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "crashdumpwriter.hpp"
+
+#include <array>
+#include <ctime>
+#include <memory>
+
+namespace purefs::fs
+{
+ class filesystem;
+}
+
+namespace crashdump
+{
+ constexpr inline auto CrashDumpFileNameFormat = "/sys/user/crashdump-%FT%TZ.hex";
+
+ class CrashDumpWriterVFS : public CrashDumpWriter
+ {
+ public:
+ void openDump() override;
+ void saveDump() override;
+
+ void writeBytes(const std::uint8_t *buff, std::size_t size) override;
+ void writeHalfWords(const std::uint16_t *buff, std::size_t size) override;
+ void writeWords(const std::uint32_t *buff, std::size_t size) override;
+
+ private:
+ template <std::size_t N> void formatCrashDumpFileName(std::array<char, N> &name)
+ {
+ std::time_t now;
+ std::time(&now);
+ std::strftime(name.data(), name.size(), CrashDumpFileNameFormat, gmtime(&now));
+ }
+
+ int dumpFd{-1};
+
+ std::shared_ptr<purefs::fs::filesystem> vfs;
+ };
+
+} // namespace crashdump
M board/rt1051/ldscripts/memory.ld => board/rt1051/ldscripts/memory.ld +6 -0
@@ 10,6 10,12 @@
*/
MEMORY
{
+ /******************************** WARNING *******************************/
+ /* */
+ /* must be kept in sync with 'board/rt1051/crashdump/crashcatcher_impl.cpp' */
+ /* */
+ /****************************************************************************/
+
/* Define each memory region */
SRAM_OC (rwx) : ORIGIN = 0x20200000, LENGTH = 0x10000 /* 64K bytes (alias RAM) */
/*SRAM_ITC (rwx) : ORIGIN = 0x0, LENGTH = 0x0*/ /* 0K bytes (alias RAM2) */
A debug_crash_dump.sh => debug_crash_dump.sh +93 -0
@@ 0,0 1,93 @@
+#!/bin/bash
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+BUILD_DIR=
+CRASH_DUMP=
+PURE_ELF=
+GDB=${GDB:-arm-none-eabi-gdb}
+
+function perror()
+{
+ echo "Error:" $@ >&2
+}
+
+function print_usage()
+{
+ echo "debug_crash_dump: This utility uses the CrashDebug stub to load the"
+ echo "crash dumps generated by the CrashCatcher fault handler library."
+ echo "The dump must be in the CrashCatcher hex dump format. This format is"
+ echo "different from the standard core dump file format and this utility"
+ echo "won't load standard core files."
+ echo
+ echo "Usage: [OPTIONS] <builddir> <crashdump>"
+ echo
+ echo "Options:"
+ echo " -e|--elf The elf file that generated the crash dump (full path)."
+ echo " '<builddir>/PurePhone.elf' by default."
+ echo
+ echo "ENV vars:"
+ echo " GDB The gdb executable used to load the crash dump."
+ echo " 'arm-none-eabi-gdb' by default."
+}
+
+function parse_args()
+{
+ local PARAMS=""
+ while (( "$#" )); do
+ case "$1" in
+ -h|--help)
+ print_usage
+ exit
+ ;;
+ -e|--elf)
+ if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
+ PURE_ELF="$2"
+ shift 2
+ else
+ perror "Argument missing for '$1'."
+ print_usage
+ exit 1
+ fi
+ ;;
+ -*|--*=) # unsupported flags
+ perror "Unsupported flag: '$1'."
+ exit 1
+ ;;
+ *) # preserve positional arguments
+ PARAMS="$PARAMS $1"
+ shift
+ ;;
+ esac
+ done
+
+ eval set -- "$PARAMS"
+
+ if [[ $# != 2 ]]; then
+ perror "Bad number of arguments."
+ print_usage
+ exit 1
+ fi
+
+ BUILD_DIR="$1"
+ CRASH_DUMP="$2"
+ PURE_ELF="${PURE_ELF:-$BUILD_DIR/PurePhone.elf}"
+}
+
+function exec_gdb()
+{
+ local CRASH_DEBUG="$BUILD_DIR/host-tools/crashdebug/CrashDebug"
+
+ exec "$GDB" "$PURE_ELF" \
+ -ex "set target-charset ASCII" \
+ -ex "target remote | \"$CRASH_DEBUG\" --elf \"$PURE_ELF\" --dump \"$CRASH_DUMP\""
+}
+
+function main()
+{
+ parse_args $@
+ exec_gdb
+}
+
+main $@
+
M host-tools/CMakeLists.txt => host-tools/CMakeLists.txt +7 -0
@@ 1,6 1,13 @@
if (CMAKE_CROSSCOMPILING)
# Littlefs fuse is needed in rt1051 and Linux for manipulate images
# genlittlefs is needed only on the Linux image for generate emulator target image
+ set(CRASH_DEBUG_DIR "${CMAKE_SOURCE_DIR}/module-utils/CrashDebug")
+ add_custom_target(
+ crashdebug ALL
+ COMMAND make -C ${CRASH_DEBUG_DIR} CrashDebug
+ COMMAND ${CMAKE_COMMAND} -E make_directory crashdebug
+ COMMAND ${CMAKE_COMMAND} -E copy ${CRASH_DEBUG_DIR}/bins/lin64/CrashDebug crashdebug
+ )
add_custom_target(
lfsfuse ALL
COMMAND ${CMAKE_COMMAND}
M module-bsp/board/rt1051/common/board.cpp => module-bsp/board/rt1051/common/board.cpp +2 -0
@@ 173,6 173,8 @@ namespace bsp
/* Enable MPU */
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
+ SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk);
+
/* Enable I cache and D cache */
SCB_EnableDCache();
SCB_EnableICache();
M module-bsp/board/rt1051/common/startup_mimxrt1052.cpp => module-bsp/board/rt1051/common/startup_mimxrt1052.cpp +3 -346
@@ 1,3 1,6 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
//*****************************************************************************
// MIMXRT1052 startup code for use with MCUXpresso IDE
//
@@ 776,352 779,6 @@ WEAK_AV void SysTick_Handler(void)
while (1) {}
}
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
- // Exception Stack Frame
- typedef struct __attribute__((packed))
- {
- 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;
-
- /// Hard Fault Fault Status Register
- struct __attribute__((packed)) hfsr_t
- {
- union
- {
- uint32_t all;
- struct
- {
- uint32_t rsrvd0 : 1;
- uint32_t vecttbl : 1;
- uint32_t rsrvd1 : 28;
- uint32_t forced : 1;
- uint32_t debugevt : 1;
- };
- };
- };
-
- /// MemManage Fault Status Register
- struct __attribute__((packed)) mmfsr_t
- {
- union
- {
- uint8_t all;
- struct
- {
- uint8_t iaccviol : 1;
- uint8_t daccviol : 1;
- uint8_t rsrvd2 : 1;
- uint8_t munstkerr : 1;
- uint8_t mstkerr : 1;
- uint8_t mlsperr : 1;
- uint8_t rsrvd6 : 1;
- uint8_t mmarvalid : 1;
- };
- };
- };
-
- /// BusFault Status Register
- struct __attribute__((packed)) bfsr_t
- {
- union
- {
- uint8_t all;
- struct
- {
- uint8_t ibuserr : 1;
- uint8_t preciserr : 1;
- uint8_t impreciserr : 1;
- uint8_t unstkerr : 1;
- uint8_t stkerr : 1;
- uint8_t lsperr : 1;
- uint8_t rsrvd6 : 1;
- uint8_t bfarvalid : 1;
- };
- };
- };
-
- /// UsageFault Status Register
- struct __attribute__((packed)) ufsr_t
- {
- union
- {
- uint16_t all;
- struct
- {
- uint8_t undefinstr : 1;
- uint8_t invstate : 1;
- uint8_t invpc : 1;
- uint8_t nocp : 1;
- uint8_t rsrvd4_7 : 3;
- uint8_t unaligned : 1;
- uint8_t divbyzero : 1;
- uint8_t rsrvd10_15 : 6;
- };
- };
- };
-
- /// Configurable Fault Status Register
- struct __attribute__((packed)) cfsr_t
- {
- union
- {
- uint32_t all;
- struct
- {
- mmfsr_t mmfsr;
- bfsr_t bfsr;
- ufsr_t ufsr;
- };
- };
- };
-
- /// Auxiliary Bus Fault Status register
- struct __attribute__((packed)) abfsr_t
- {
- union
- {
- uint32_t all;
- struct
- {
- uint32_t itcm : 1;
- uint32_t dtcm : 1;
- uint32_t ahbp : 1;
- uint32_t axim : 1;
- uint32_t eppb : 1;
- uint32_t rsrvd5_7 : 3;
- uint32_t aximtype : 2;
- uint32_t rsrvd10_31 : 1;
- };
- };
- };
-
- struct __attribute__((packed)) syslog_t
- {
- syslog_exception_stack_frame_t stackFrame;
- struct
- {
- hfsr_t hfsr; /// Hard Fault Fault Status Register
- cfsr_t cfsr; /// Configurable Fault Status Register
- uint32_t mmfar; /// MemManage Fault Address Register
- uint32_t bfar; /// BusFault Address Register
- abfsr_t abfsr; /// Auxiliary Bus Fault Status register
- uint32_t exc_return; /// EXC_RETURN value for the exception being serviced
- } registers;
- };
-
-#define DEBUG_PRINT_HARD_FAULT_INFO 1
-#define DEBUG_DETAILED_HARD_FAULT_INFO 1
-
- static void printHardFaultInfo(const syslog_t &syslog)
- {
-#if (DEBUG_PRINT_HARD_FAULT_INFO == 1)
- LOG_FATAL("!!! HardFault Detected !!!");
- LOG_FATAL("* Stack Frame:");
- LOG_FATAL("R0 = 0x%0" PRIX32, syslog.stackFrame.r0);
- LOG_FATAL("R1 = 0x%0" PRIX32, syslog.stackFrame.r1);
- LOG_FATAL("R2 = 0x%0" PRIX32, syslog.stackFrame.r2);
- LOG_FATAL("R3 = 0x%0" PRIX32, syslog.stackFrame.r3);
- LOG_FATAL("R12 = 0x%0" PRIX32, syslog.stackFrame.r12);
- LOG_FATAL("LR = 0x%0" PRIX32, syslog.stackFrame.lr);
- LOG_FATAL("PC = 0x%0" PRIX32, syslog.stackFrame.pc);
- LOG_FATAL("PSR = 0x%0" PRIX32, syslog.stackFrame.psr);
-
- LOG_FATAL("* Fault Status Registers:");
- LOG_FATAL("SCB->HFSR = 0x%0" PRIX32, syslog.registers.hfsr.all);
- LOG_FATAL("SCB->CFSR = 0x%0" PRIX32, syslog.registers.cfsr.all);
- LOG_FATAL("SCB->MMAR = 0x%0" PRIX32, syslog.registers.mmfar);
- LOG_FATAL("SCB->BFAR = 0x%0" PRIX32, syslog.registers.bfar);
- LOG_FATAL("SCB->ABFSR = 0x%0" PRIX32, syslog.registers.abfsr.all);
- LOG_FATAL("EXC_RETURN = 0x%0" PRIX32, syslog.registers.exc_return);
-
-#if (DEBUG_DETAILED_HARD_FAULT_INFO == 1)
- LOG_FATAL("* Details of Fault Status Registers:");
- hfsr_t hfsr = syslog.registers.hfsr;
- LOG_FATAL("SCB->HFSR = 0x%0" PRIX32 " - HardFault Status Register", hfsr.all);
- if (hfsr.debugevt)
- LOG_FATAL(" - DEBUGEVT: Hard fault caused by debug event");
- if (hfsr.forced)
- LOG_FATAL(" - FORCED: Hard fault caused by bus/memory management/usage fault");
- if (hfsr.vecttbl)
- LOG_FATAL(" - VECTBL: BusFault on vector table read");
-
- cfsr_t cfsr = syslog.registers.cfsr;
- LOG_FATAL("SCB->CFSR = 0x%0" PRIX32 " - Configurable Fault Status Register", cfsr.all);
- mmfsr_t mmfsr = cfsr.mmfsr;
- LOG_FATAL("> SCB->MMFSR = 0x%0" PRIX8 " Memory Management Fault Status Register", mmfsr.all);
- if (mmfsr.mmarvalid)
- LOG_FATAL(" - MMARVALID: MMAR is valid");
- if (mmfsr.mlsperr)
- LOG_FATAL(" - MLSPERR: A MemManage fault occurred during floating-point lazy state preservation");
- if (mmfsr.mstkerr)
- LOG_FATAL(" - MSTKERR: MemManage fault on stacking for exception entry");
- if (mmfsr.munstkerr)
- LOG_FATAL(" - MUNSTKERR: MemManage fault on unstacking for a return from exception:");
- if (mmfsr.daccviol)
- LOG_FATAL(" - DACCVIOL: Data access violation");
- if (mmfsr.iaccviol)
- LOG_FATAL(" - IACCVIOL: Instruction access violation");
-
- bfsr_t bfsr = cfsr.bfsr;
- LOG_FATAL("> SCB->BFSR = 0x%0" PRIX8 " - Bus Fault Status Register ", bfsr.all);
- if (bfsr.bfarvalid)
- LOG_FATAL(" - BFARVALID: BFAR is valid ");
- if (bfsr.lsperr)
- LOG_FATAL(" - LSPERR: A bus fault occurred during floating-point lazy state preservation");
- if (bfsr.stkerr)
- LOG_FATAL(" - STKERR: Stacking error");
- if (bfsr.unstkerr)
- LOG_FATAL(" - UNSTKERR: Unstacking error");
- if (bfsr.impreciserr)
- LOG_FATAL(" - IMPREISERR: Imprecise data bus error");
- if (bfsr.preciserr)
- LOG_FATAL(" - PRECISERR: Precise data bus error");
- if (bfsr.ibuserr)
- LOG_FATAL(" - IBUSERR: Instruction bus error");
-
- ufsr_t ufsr = cfsr.ufsr;
- LOG_FATAL("> SCB->UFSR = 0x%0" PRIX16 " - Usage Fault Status Register", ufsr.all);
- if (ufsr.divbyzero)
- LOG_FATAL(" - DIVBYZERO: Divide by zero UsageFault");
- if (ufsr.unaligned)
- LOG_FATAL(" - UNALIGNED: Unaligned access UsageFault");
- if (ufsr.nocp)
- LOG_FATAL(" - NOCP: Attempt to execute a coprocessor instruction");
- if (ufsr.invpc)
- LOG_FATAL(" - INVPC: Invalid PC load UsageFault");
- if (ufsr.invstate)
- LOG_FATAL(" - INVSTATE: Invalid state UsageFault");
- if (ufsr.undefinstr)
- LOG_FATAL(" - UNDEFINSTR: Undefined instruction UsageFault");
-
- abfsr_t abfsr = syslog.registers.abfsr;
- LOG_FATAL("SCB->ABFSR = 0x%0" PRIX32 " - Auxiliary Bus Fault Status register", abfsr.all);
- if (abfsr.itcm)
- LOG_FATAL(" - ITCM: Asynchronous fault on ITCM interface");
- if (abfsr.dtcm)
- LOG_FATAL(" - DTCM: Asynchronous fault on DTCM interface.");
- if (abfsr.ahbp)
- LOG_FATAL(" - AHBP: Asynchronous fault on AHBP interface");
- if (abfsr.eppb)
- LOG_FATAL(" - EPPB: Asynchronous fault on EPPB interface");
-#endif // (DEBUG_DETAILED_HARD_FAULT_INFO == 1)
-#endif //(DEBUG_PRINT_HARD_FAULT_INFO == 1)
- }
-
- WEAK_AV void HardFault_Handler_C(syslog_exception_stack_frame_t *frame __attribute__((unused)),
- uint32_t lr_value __attribute__((unused)))
- {
- static syslog_t syslog = {};
- syslog.stackFrame = *frame;
- 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);
-
- abort();
- }
-
- WEAK_AV void MemManage_Handler_C(syslog_exception_stack_frame_t *frame __attribute__((unused)),
- uint32_t lr __attribute__((unused)))
- {
- abort();
- }
-
-#if defined(__cplusplus)
-}
-#endif
-
-WEAK_AV void MemManage_Handler(void)
-{
-#if 1
- asm volatile(" tst lr,#4 \n"
- " ite eq \n"
- " mrseq r0,msp \n"
- " mrsne r0,psp \n"
- " mov r1,lr \n"
- " ldr r2,=MemManage_Handler_C \n"
- " bx r2"
-
- : /* Outputs */
- : /* Inputs */
- : /* Clobbers */
- );
-#endif
-}
-
-[[gnu::naked]] WEAK_AV void HardFault_Handler(void)
-{
- asm volatile(" tst lr,#4 \n"
- " ite eq \n"
- " mrseq r0,msp \n"
- " mrsne r0,psp \n"
- " mov r1,lr \n"
- " ldr r2,=HardFault_Handler_C \n"
- " bx r2"
-
- : /* Outputs */
- : /* Inputs */
- : /* Clobbers */
- );
-}
-
-WEAK_AV void BusFault_Handler(void)
-{
-
-#if 0
- asm volatile(
- " tst lr,#4 \n"
- " ite eq \n"
- " mrseq r0,msp \n"
- " mrsne r0,psp \n"
- " mov r1,lr \n"
- " ldr r2,=BusFault_Handler_C \n"
- " bx r2"
-
- : /* Outputs */
- : /* Inputs */
- : /* Clobbers */
- );
-#endif
-}
-
-WEAK_AV void UsageFault_Handler(void)
-{
-
-#if 0
- asm volatile(
- " tst lr,#4 \n"
- " ite eq \n"
- " mrseq r0,msp \n"
- " mrsne r0,psp \n"
- " mov r1,lr \n"
- " ldr r2,=UsageFault_Handler_C \n"
- " bx r2"
-
- : /* Outputs */
- : /* Inputs */
- : /* Clobbers */
- );
-#endif
-}
-
//*****************************************************************************
// Processor ends up here if an unexpected interrupt occurs or a specific
// handler is not present in the application code.
A module-utils/CrashDebug => module-utils/CrashDebug +1 -0
@@ 0,0 1,1 @@
+Subproject commit 0104eb5480d9213d9fe944f13958f785a311a191
M module-vfs/drivers/src/thirdparty/littlefs/lfs_glue.cpp => module-vfs/drivers/src/thirdparty/littlefs/lfs_glue.cpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <littlefs/volume_mapper.hpp>
#include <littlefs/lfs.h>
M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
M tools/gdb_crash_extend.py => tools/gdb_crash_extend.py +1 -1
@@ 1,4 1,4 @@
-# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from __future__ import print_function