~aleteoryx/muditaos

79b3c32842459fa72db6357e20ff7e892cc365f6 — Maciej Gibowicz 2 years ago 61ebc08
[BH-1757] Fix Hard Fault handling

Added a critical section when handling Hard Faults
co-author @Lefucjusz
M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 20,6 20,7 @@
* Fixed problem with sounds in relaxation and power nap applications
* Fixed the logic in onboarding screens
* Fixed issues with file uploads with low disk space.
* Fixed hard fault handling

### Added


M pure_changelog.md => pure_changelog.md +1 -0
@@ 29,6 29,7 @@
* Fixed diacritics in translations
* Fixed issues with file uploads with low disk space.
* Fixed data losing because switching tethering via tethering popup
* Fixed hard fault handling

## [1.7.2 2023-07-28]


M third-party/CrashDebug/CrashCatcher/CrashCatcher.c => third-party/CrashDebug/CrashCatcher/CrashCatcher.c +21 -0
@@ 69,9 69,30 @@ static int isARMv6MDevice(void);
static void dumpFaultStatusRegisters(void);
static void advanceProgramCounterPastHardcodedBreakpoint(const Object* pObject);

/* See FreeRTOSConfig.h */
#define configPRIO_BITS 4
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

static inline void __attribute__((always_inline)) CrashCatcher_EnterCritical(void)
{
    uint32_t ulNewBASEPRI;

    __asm__ __volatile__
    (
        "mov %0, %1\n"
        "cpsid i\n"
        "msr basepri, %0\n"
        "isb\n"
        "dsb\n"
        "cpsie i\n"
        : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
    );
}

void CrashCatcher_Entry(const CrashCatcherExceptionRegisters* pExceptionRegisters)
{
    CrashCatcher_EnterCritical();
    Object object = initStackPointers(pExceptionRegisters);
    advanceStackPointerToValueBeforeException(&object);
    initFloatingPointFlag(&object);

M third-party/CrashDebug/CrashCatcher/CrashCatcher_armv7m.S => third-party/CrashDebug/CrashCatcher/CrashCatcher_armv7m.S +85 -89
@@ 12,6 12,7 @@
   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(). */


@@ 19,28 20,32 @@
    .syntax unified
    .arch armv7-m

    /* Called on Hard Fault exception.  Stacks important registers and calls CrashCatcher_Entry().
    /*
     * Called on Hard Fault exception.
     * Stacks important registers and calls CrashCatcher_Entry().
     */

        extern "C" void HardFault_Handler(void);
    */
    /* 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 */
    /* 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]


@@ 53,126 58,117 @@ HardFault_Handler:
    mrs     r1, msp
    ldr     sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
    push.w  {r1-r11,lr}
    // Call original console dump
    ldr r0,=crash_orig_stack
    str sp, [r0]
    mov sp, r1

    ldr r0,=crash_orig_stack
    ldr sp, [r0]
    // Preserve current CrashCatcher's stack pointer value
    ldr r0, =crash_orig_stack
    str 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
    mov r0, sp                      // Set CrashCatcher's stack as first argument to CrashCatcher_Entry
    ldr r2, =CrashCatcher_Entry     // Stack frame exception return function
    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 .

    str r2, [r3, #0x18]             // Overwrite existing return address with CrashCatcher_Entry address
    str r0, [r3]                    // Switch PSP to CrashCatcher's stack
    orr lr, lr, #4                  // Use PSP after return
    orr lr, lr, #8                  // Switch to thread mode upon returning
    bx lr                           // Return from exception
    b .                             // Just in case

    // Let assembler know that we have hit the end of the HardFault_Handler function.
    .pool
    .size   HardFault_Handler, .-HardFault_Handler


    .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).
    /*
     * 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);
    */
    /* 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]
    vmrs        r1, fpscr       // Grab a copy of FPSCR before issuing any other FP instructions.
    vstmia.32   r0!, {s0 - s31} // Move s0 - s31 to pBuffer.
    str         r1, [r0]        // Move fpscr to pBuffer.
#endif
    // Return to caller.
    bx          lr

    bx          lr              // Return to caller.
    .pool
    .size   CrashCatcher_CopyAllFloatingPointRegisters, .-CrashCatcher_CopyAllFloatingPointRegisters
    .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).
     */

    /* 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);
    */
    /* 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}
    vstmia.32   r0!, {s16 - s31} // Move s16 - s31 to pBuffer.
#endif
    // Return to caller.
    bx      lr

    bx          lr     // Return to caller.
    .pool
    .size   CrashCatcher_CopyUpperFloatingPointRegisters, .-CrashCatcher_CopyUpperFloatingPointRegisters
    .size CrashCatcher_CopyUpperFloatingPointRegisters, .-CrashCatcher_CopyUpperFloatingPointRegisters


	/*
		This function is called by the SVC #1 syscall
		and then collect stack data for the crash dump
		which will be run in the second stage
		It also changes stack to the static internal
		due to possibility of corruption of the oryginal
		stack frame
		extern "C" void _StackTrace_Dump_svc_1(void);
    */
	 * This function is called by the SVC #1 syscall
	 * and then collect stack data for the crash dump
	 * which will be run in the second stage.
	 * It also changes stack to the static internal
	 * due to possibility of corruption of the original
	 * stack frame.
	 */

	/*	extern "C" void _StackTrace_Dump_svc_1(void); */
    .global _StackTrace_Dump_svc_1
    .type _StackTrace_Dump_svc_1 , %function
    .thumb_func
_StackTrace_Dump_svc_1:
    // Preserve exception stack frame
    mrs     r3, xpsr
    mrs     r2, psp
    mrs     r1, msp
    ldr     sp, =(g_crashCatcherStack + 4 * CRASH_CATCHER_STACK_WORD_COUNT)
    push.w  {r1-r11,lr}

    // Preserve current CrashCatcher's stack pointer value for use in second stage below
	ldr     r0, =crash_orig_stack
    str    	sp, [r0]

    mov     sp, r1
    bx      lr
    mov     sp, r1 // Switch back to original stack
    bx      lr     // Return from exception
    .pool
    .size   _StackTrace_Dump_svc_1, .-_StackTrace_Dump_svc_1


	/* This function is the second stage of the crash dump
	   crash orig stack should contain valid stack from
	   the exception and now crash catcher should be able
	   to read stack frame pointer and dump data in the
	   user mode from the second part of the exit function
	   In our model crash newer return to the caller so
	   we can use simply branch without care about unstacking
      extern "C" void _StackTrace_Dump_stage_2(void);
	*/
    .size _StackTrace_Dump_svc_1, .-_StackTrace_Dump_svc_1


	/*
	 * This function is the second stage of the crash dump
	 * 'crash_orig_stack' should contain valid stack from
	 * the exception, so that CrashCatcher is able to read
	 * stack frame pointer and dump data in the user mode
	 * from the second part of the exit function.
	 * In our model CrashCatcher never returns to the
	 * caller, so simple branch is enough, without caring
	 * about proper unstacking.
	 */

    /* extern "C" void _StackTrace_Dump_stage_2(void); */
    .global _StackTrace_Dump_stage_2
    .type _StackTrace_Dump_stage_2 , %function
    .thumb_func
_StackTrace_Dump_stage_2:
	 ldr	 r0, =crash_orig_stack
	 ldr     r0, [r0]
     b      CrashCatcher_Entry
	 ldr r0,    =crash_orig_stack
	 ldr r0,    [r0]                // Pass CrashCatcher's stack as a first argument to CrashCatcher_Entry
     b          CrashCatcher_Entry  // Jump to CrashCatcher_Entry
    .pool
    .size   _StackTrace_Dump_stage_2, .-_StackTrace_Dump_stage_2
    .size _StackTrace_Dump_stage_2, .-_StackTrace_Dump_stage_2

    .data
    crash_orig_stack: .long 0

    crash_orig_stack: .long 0 // Stores CrashCatcher stack pointer position