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