Move crash handler to src/health.c

This commit is contained in:
cpq committed 2026-10-02 12:47:05 +01:00
1 parent ce35cbf586
commit d7e708b9bc
14 files changed
+179 -267

No files matched your search

@@ -47,10 +47,6 @@ extern "C" {
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
@@ -18,7 +18,6 @@
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32h7xx_hal.h"
#include "string.h"
/* Private includes ----------------------------------------------------------*/
@@ -94,6 +93,9 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/api/tick"), NULL)) {
mg_http_reply(c, 200, "", "{%m:%lu}\n", MG_ESC("tick"), HAL_GetTick());
} else if (mg_match(hm->uri, mg_str("/api/kill"), NULL)) {
SCB->SHCSR &= ~SCB_SHCSR_USGFAULTENA_Msk;
__asm volatile("udf #0");
} else {
mg_http_reply(c, 200, "", "Hi from Mongoose, tick %lu\n", HAL_GetTick());
}
@@ -109,7 +111,7 @@ int main(void)
{
/* USER CODE BEGIN 1 */
MG_HEALTH_INIT();
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
@@ -78,66 +78,6 @@ void NMI_Handler(void)
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
@@ -154,9 +154,9 @@ SECTIONS
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* mongoose Ethernet driver */
.eth_ram : { *(.eth_ram .eth_ram*) } > RAM_D2 AT > FLASH
/* mongoose Ethernet driver */
.eth_ram : { *(.eth_ram .eth_ram*) } > RAM_D2 AT > FLASH
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
@@ -42,23 +42,23 @@ Mcu.Pin6=PB0
Mcu.Pin7=PB13
Mcu.Pin8=PB14
Mcu.Pin9=PD8
Mcu.PinsNb=19
Mcu.PinsNb=17
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32H723ZGTx
MxCube.Version=6.17.0
MxDb.Version=DB.6.0.170
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false
PA1.Mode=RMII
PA1.Signal=ETH_REF_CLK
PA2.Mode=RMII
@@ -114,8 +114,8 @@ ProjectManager.MainLocation=Core/Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=h723.ioc
ProjectManager.ProjectName=h723
ProjectManager.ProjectFileName=nucleo-h723zg.ioc
ProjectManager.ProjectName=nucleo-h723zg
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x2000
@@ -28,5 +28,5 @@ SECTIONS {
_end = .;
/* Retained health record. Startup code must neither copy nor clear it. */
.mg_health (NOLOAD) : { KEEP(*(.mg_health .mg_health*)) } > bkpsram
.mg_health (NOLOAD) : { KEEP(*(.mg_health .mg_health*)) } > ram_d3
}
+3 -51
View File
@@ -17,19 +17,10 @@
#define LED2 PIN('E', 1)
#define LED3 PIN('B', 14)
enum { CRASH_SP, CRASH_LR, CRASH_PC, CRASH_STACK };
static void log_fn(char ch, void *param) {
hal_uart_write_buf(param, &ch, 1);
}
static void hal_storage_init(void) {
RCC->AHB4ENR |= RCC_AHB4ENR_BKPRAMEN;
(void) RCC->AHB4ENR;
PWR->CR2 |= PWR_CR2_BREN;
while ((PWR->CR2 & PWR_CR2_BRRDY) == 0) (void) 0;
}
static void blink_task(void) {
static uint64_t blink_timer = 0;
if (hal_timer_expired(&blink_timer, 500, hal_get_tick())) {
@@ -37,46 +28,6 @@ static void blink_task(void) {
}
}
// Fault handler body. Runs in exception context: no printf, no malloc, no
// blocking calls. Copies the unwind registers and raw stack into the health
// record, then resets.
// "used" keeps the linker from garbage-collecting this section: the only
// reference is the "b fault_c" branch in the naked handler below
__attribute__((used, noinline)) static void fault_c(uint32_t *frame,
uint32_t exc_return) {
extern uint32_t _estack;
uint32_t *stack = frame + 8 + ((exc_return & (1U << 4)) ? 0 : 18);
uint32_t *r = mg_health_record.data;
if (frame[7] & (1U << 9)) stack++; // Eight-byte stack alignment padding
r[CRASH_SP] = (uint32_t) (uintptr_t) stack;
r[CRASH_LR] = frame[5];
r[CRASH_PC] = frame[6];
for (size_t i = 0; i < MG_HEALTH_DATA_SIZE - CRASH_STACK; i++) {
r[CRASH_STACK + i] = stack + i < &_estack ? stack[i] : 0;
}
mg_health_record.cpuid = SCB->CPUID;
mg_health_record.reset_reason = MG_HEALTH_RESET_FAULT;
NVIC_SystemReset();
}
// Common fault entry. EXC_RETURN bit 2 tells which stack was in use:
// 0 = MSP, 1 = PSP. Load the faulting SP into r0 and hand it to fault_c()
__attribute__((naked)) void HardFault_Handler(void) {
__asm volatile(
"mov r1, lr\n\t"
"tst lr, #4\n\t"
"ite eq\n\t"
"mrseq r0, msp\n\t"
"mrsne r0, psp\n\t"
"b fault_c\n\t");
}
// Route the other fault types through the same entry point
void MemManage_Handler(void) __attribute__((alias("HardFault_Handler")));
void BusFault_Handler(void) __attribute__((alias("HardFault_Handler")));
void UsageFault_Handler(void) __attribute__((alias("HardFault_Handler")));
uint64_t mg_millis(void) {
return hal_get_tick();
}
@@ -105,9 +56,9 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
}
int main(void) {
MG_HEALTH_INIT();
hal_clock_init();
hal_storage_init();
MG_HEALTH_INIT(); // Must be called after clock init
hal_uart_init(UART_DEBUG, UART_DEBUG_TX_PIN, UART_DEBUG_RX_PIN, 115200);
mg_log_set_fn(log_fn, UART_DEBUG);
hal_rng_init();
@@ -117,6 +68,7 @@ int main(void) {
hal_gpio_output(LED3);
MG_INFO(("Initialised. CPU clock: %lu MHz", SystemCoreClock / 1000000));
MG_INFO(("Crash record: %M", mg_print_crash_record));
struct mg_mgr mgr;
mg_mgr_init(&mgr);
@@ -27,9 +27,10 @@
} while (0)
// Crash report support. Health record lives in the .mg_health region, see link.ld
#define MG_ENABLE_HEALTH 1
#define MG_HEALTH_RAM __attribute__((section(".mg_health")))
#define MG_HEALTH_DATA_SIZE 1000 // fill the 4KB backup SRAM
#define MG_HEALTH_DATA_SIZE 1000
// mdash.net device management service support
#define MG_ENABLE_MDASH 1
#define MG_MDASH_KEY "u8eyWvBmkc6gw9991z1SQ8Lg" // Set this - mDash device token
#define MG_ENABLE_MDASH 0
#define MG_MDASH_KEY "..." // Set this - mDash device token