~aleteoryx/muditaos

3193f6fa59af972e2d9a06a80da5d6601185b75b — Lefucjusz 2 years ago 20edafc
[MOS-230] Print last instruction address before RTWDOG reset

Added mechanism that stores address of last
executed instruction before RTWDOG timeout
to enable some basic debugging in such cases,
as such resets do not create crashdumps and
leave no information in logs.
M module-bsp/board/rt1051/bellpx/irq_gpio.cpp => module-bsp/board/rt1051/bellpx/irq_gpio.cpp +34 -2
@@ 188,11 188,43 @@ namespace bsp
         * be power reset.
         *
         * The simplest way to do it is to configure the pin as WDOG_B and use WDOG1 built-in
         * assertion. */
        void RTWDOG_IRQHandler(void)
         * assertion.
         *
         * Before proceeding to exception handler, CPU pushes the following registers
         * to the active stack:
         * r0,       offset 0 (in words),
         * r1        offset 1,
         * r2,       offset 2,
         * r3,       offset 3,
         * r12,      offset 4,
         * r14 (LR), offset 5,
         * r15 (PC), offset 6,
         * xPSR,     offset 7.
         * Get the value of last PC state and store in non-volatile SNVS register
         * to have any data that can be used to debug if program died in IRQ or
         * critical section and neither log nor crashdump was created. */
        __attribute__((used, noreturn)) void RTWDOG_Handler(const uint32_t *sp)
        {
            RTWDOG_ClearStatusFlags(RTWDOG, kRTWDOG_InterruptFlag);

            const uint32_t pc = sp[6];
            SNVS->LPGPR[1]    = pc;

            WDOG1->WCR &= ~WDOG_WCR_WDA_MASK;
            while (true) {}; // Execution should never reach this point, but just in case
        }

        /* This has to be done as naked function to be able to easily extract last
         * PC value before RTWDOG handler was called without having to deal with
         * function prologue. */
        __attribute__((naked)) void RTWDOG_IRQHandler(void)
        {
            __asm__ __volatile__("tst lr, #4\n" // Determine which stack was used
                                 "ite eq\n"
                                 "mrseq r0, msp\n"
                                 "mrsne r0, psp\n"
                                 "b RTWDOG_Handler\n" // Jump to real handler
            );
        }

        // Enable PMU brownout interrupt

M module-bsp/board/rt1051/common/board.cpp => module-bsp/board/rt1051/common/board.cpp +7 -1
@@ 20,7 20,7 @@ extern "C"
#include "board/brownout.hpp"
#include <board/debug_console.hpp>

#include <cstdint>
#include <log/log.hpp>

extern std::uint32_t __sdram_cached_start[];



@@ 187,6 187,12 @@ namespace bsp

        PrintSystemClocks();
        clearAndPrintBootReason();

        if (SNVS->LPGPR[1] != 0) {
            LOG_INFO("Device seems to have been reset by RTWDOG! Last instruction address: 0x%08lX",
                     SNVS->LPGPR[1]);
            SNVS->LPGPR[1] = 0;
        }
    }

    //! Board PowerOff function by cutdown power

M module-bsp/board/rt1051/puretx/irq_gpio.cpp => module-bsp/board/rt1051/puretx/irq_gpio.cpp +43 -8
@@ 1,12 1,12 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "board/irq_gpio.hpp"

#include "board.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "fsl_common.h"
#include <fsl_common.h>
#include <fsl_rtwdog.h>

#include "board/rt1051/bsp/eink/bsp_eink.h"
#include <hal/key_input/KeyInput.hpp>


@@ 14,13 14,9 @@
#include <log/log.hpp>
#include "bsp/cellular/bsp_cellular.hpp"
#include "bsp/headset/headset.hpp"
#include "board/BoardDefinitions.hpp"
#include "bsp/magnetometer/magnetometer.hpp"
#include "bsp/light_sensor/light_sensor.hpp"

namespace bsp
{

    void irq_gpio_Init(void)
    {
        DisableIRQ(GPIO1_Combined_0_15_IRQn);


@@ 28,6 24,7 @@ namespace bsp
        DisableIRQ(GPIO2_Combined_0_15_IRQn);
        DisableIRQ(GPIO2_Combined_16_31_IRQn);
        DisableIRQ(GPIO3_Combined_16_31_IRQn);
        DisableIRQ(RTWDOG_IRQn);

        GPIO_PortDisableInterrupts(GPIO1, UINT32_MAX);
        GPIO_PortDisableInterrupts(GPIO2, UINT32_MAX);


@@ 52,11 49,13 @@ namespace bsp

        EnableIRQ(GPIO3_Combined_16_31_IRQn);
        NVIC_SetPriority(GPIO3_Combined_16_31_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);

        NVIC_ClearPendingIRQ(RTWDOG_IRQn);
        NVIC_EnableIRQ(RTWDOG_IRQn);
    }

    extern "C"
    {

        void GPIO1_Combined_0_15_IRQHandler(void)
        {
            BaseType_t xHigherPriorityTaskWoken = 0;


@@ 163,5 162,41 @@ namespace bsp
            // Switch context if necessary
            portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
        }

        /* Before proceeding to exception handler, CPU pushes the following registers
         * to the active stack:
         * r0,       offset 0 (in words),
         * r1        offset 1,
         * r2,       offset 2,
         * r3,       offset 3,
         * r12,      offset 4,
         * r14 (LR), offset 5,
         * r15 (PC), offset 6,
         * xPSR,     offset 7.
         * Get the value of last PC state and store in non-volatile SNVS register
         * to have any data that can be used to debug if program died in IRQ or
         * critical section and neither log nor crashdump was created. */
        __attribute__((used, noreturn)) void RTWDOG_Handler(const uint32_t *sp)
        {
            RTWDOG_ClearStatusFlags(RTWDOG, kRTWDOG_InterruptFlag);

            const uint32_t pc = sp[6];
            SNVS->LPGPR[1]    = pc;

            while (true) {}; // Wait for RTWDOG to reset the board
        }

        /* This has to be done as naked function to be able to easily extract last
         * PC value before RTWDOG handler was called without having to deal with
         * function prologue. */
        __attribute__((naked)) void RTWDOG_IRQHandler(void)
        {
            __asm__ __volatile__("tst lr, #4\n" // Determine which stack was used
                                 "ite eq\n"
                                 "mrseq r0, msp\n"
                                 "mrsne r0, psp\n"
                                 "b RTWDOG_Handler\n" // Jump to real handler
            );
        }
    }
} // namespace bsp