mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-01 05:52:32 +07:00
Show backtrace
This commit is contained in:
@@ -1,2 +1,11 @@
|
||||
#pragma once
|
||||
#define MG_ARCH MG_ARCH_CUBE
|
||||
|
||||
// Ethernet driver tunables:
|
||||
// #define MG_DRIVER_MDC_CR 4 // RMII MDC clock divider, from 0 to 5
|
||||
// #define MG_TCPIP_PHY_ADDR 0 // PHY address
|
||||
|
||||
// Uncomment this for static IP configuration:
|
||||
// #define MG_TCPIP_IP MG_IPV4(192, 168, 0, 10) // IP
|
||||
// #define MG_TCPIP_GW MG_IPV4(192, 168, 0, 1) // Gateway
|
||||
// #define MG_TCPIP_MASK MG_IPV4(255, 255, 255, 0) // Netmask
|
||||
|
||||
@@ -45,8 +45,8 @@ __attribute__((used, noinline)) static void fault_c(uint32_t *sp) {
|
||||
mg_health_record.backtrace[n++] = sp[5] & ~1U; // Stacked LR
|
||||
for (uint32_t *p = sp + 8;
|
||||
n < MG_HEALTH_BACKTRACE &&
|
||||
(uintptr_t) p < (uintptr_t) sp + 4096U && // Bound the scan
|
||||
(uintptr_t) p < (uintptr_t) &_estack; // Stay in RAM
|
||||
(uintptr_t) p < (uintptr_t) sp + 4096U && // Bound the scan
|
||||
(uintptr_t) p < (uintptr_t) &_estack; // Stay in RAM
|
||||
p++) {
|
||||
uint32_t v = *p;
|
||||
if ((v & 1U) && v >= 0x08000000U && v < 0x08000000U + 1024U * 1024U) {
|
||||
@@ -60,8 +60,8 @@ __attribute__((used, noinline)) static void fault_c(uint32_t *sp) {
|
||||
// 0 = MSP, 1 = PSP. Load the faulting SP into r0 and hand it to fault_c()
|
||||
__attribute__((naked)) void HardFault_Handler(void) {
|
||||
__asm volatile(
|
||||
"tst lr, #4\n\t" // Test EXC_RETURN bit 2
|
||||
"ite eq\n\t" // If zero, use MSP; else PSP
|
||||
"tst lr, #4\n\t" // Test EXC_RETURN bit 2
|
||||
"ite eq\n\t" // If zero, use MSP; else PSP
|
||||
"mrseq r0, msp\n\t"
|
||||
"mrsne r0, psp\n\t"
|
||||
"b fault_c\n\t");
|
||||
@@ -85,43 +85,24 @@ bool mg_random(void *buf, size_t len) {
|
||||
}
|
||||
|
||||
static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||
if (ev == MG_EV_HTTP_HDRS) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (mg_match(hm->uri, mg_str("/api/ota/update"), NULL)) {
|
||||
mg_http_start_ota(c, hm, NULL);
|
||||
}
|
||||
} else if (ev == MG_EV_HTTP_MSG) {
|
||||
if (ev == MG_EV_HTTP_MSG) {
|
||||
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:%llu}\n", MG_ESC("tick"), hal_get_tick());
|
||||
} else if (mg_match(hm->uri, mg_str("/api/ota/commit"), NULL)) {
|
||||
c->data[0] = 1;
|
||||
mg_http_reply(c, 200, "", "ok\n");
|
||||
} else if (mg_match(hm->uri, mg_str("/api/ota/rollback"), NULL)) {
|
||||
c->data[0] = 2;
|
||||
mg_http_reply(c, 200, "", "ok\n");
|
||||
} 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 %llu\n", hal_get_tick());
|
||||
mg_http_reply(c, 200, "", "Hi from Mongoose, tick %llu\n",
|
||||
hal_get_tick());
|
||||
}
|
||||
} else if (ev == MG_EV_CLOSE && c->data[0] == 1) {
|
||||
MG_OTA_STATE_SET(MG_OTA_CONFIRMED);
|
||||
NVIC_SystemReset();
|
||||
} else if (ev == MG_EV_CLOSE && c->data[0] == 2) {
|
||||
MG_OTA_STATE_SET(MG_OTA_CONFIRMED);
|
||||
MG_OTA_ROLLBACK();
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
hal_clock_init();
|
||||
|
||||
// Enable MemManage, BusFault and UsageFault so faults are precise and
|
||||
// routed to their own handlers instead of escalating to HardFault
|
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk |
|
||||
SCB_SHCSR_USGFAULTENA_Msk;
|
||||
|
||||
MG_OTA_BOOT_CHECK(); // Must be called after clock init
|
||||
MG_HEALTH_INIT(); // Must be called after clock 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);
|
||||
@@ -132,17 +113,20 @@ int main(void) {
|
||||
hal_gpio_output(LED3);
|
||||
|
||||
MG_INFO(("Initialised. CPU clock: %lu MHz", SystemCoreClock / 1000000));
|
||||
|
||||
// Report the previous boot's crash backtrace, if any
|
||||
if (mg_health_reason() == MG_HEALTH_RESET_FAULT) {
|
||||
MG_INFO(("Previous boot faulted. Backtrace:"));
|
||||
char buf[MG_HEALTH_BACKTRACE * 10 + 100];
|
||||
mg_snprintf(buf, sizeof(buf), "%s",
|
||||
"arm-none-eabi-addr2line -pfiaC -e firmware.elf");
|
||||
for (int i = 0; i < MG_HEALTH_BACKTRACE; i++) {
|
||||
if (mg_health_record.backtrace[i] == 0) break;
|
||||
MG_INFO((" #%d 0x%08lx", i,
|
||||
(unsigned long) mg_health_record.backtrace[i]));
|
||||
mg_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " 0x%08lx",
|
||||
mg_health_record.backtrace[i]);
|
||||
}
|
||||
// * (volatile uint32_t *) 0 = 123; // Deliberate fault: write to unmapped memory
|
||||
// mg_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "\n");
|
||||
MG_INFO(("Previous boot crashed! Analyse with: %s", buf));
|
||||
}
|
||||
// for (;;) (void) 0;
|
||||
|
||||
struct mg_mgr mgr;
|
||||
mg_mgr_init(&mgr);
|
||||
|
||||
@@ -10,50 +10,10 @@
|
||||
#define MG_ENABLE_CUSTOM_MILLIS 1
|
||||
#define MG_ENABLE_CUSTOM_RANDOM 1
|
||||
#define MG_ENABLE_DRIVER_STM32H 1
|
||||
#define MG_ENABLE_PACKED_FS 1
|
||||
|
||||
// Place Ethernet driver's buffers into the DMA-accessible RAM, see link.ld
|
||||
#define MG_ETH_RAM __attribute__((section(".eth_ram")))
|
||||
|
||||
// #define MG_DRIVER_MDC_CR 4 // RMII MDC clock divider, from 0 to 5
|
||||
// #define MG_TCPIP_PHY_ADDR 0 // PHY address
|
||||
|
||||
// For static IP configuration, define MG_TCPIP_{IP,MASK,GW}
|
||||
// By default, those are set to zero, meaning that DHCP is used
|
||||
//
|
||||
// #define MG_TCPIP_IP MG_IPV4(192, 168, 0, 10) // IP
|
||||
// #define MG_TCPIP_GW MG_IPV4(192, 168, 0, 1) // Gateway
|
||||
// #define MG_TCPIP_MASK MG_IPV4(255, 255, 255, 0) // Netmask
|
||||
|
||||
// OTA rollback timer via IWDG1. PR=7 → /512 on H723 (RM0468 §54.4.2).
|
||||
// Fixed 10 s hang-detection window: RLR = 10 * 32000 / 512 = 625.
|
||||
// RM0468 §54.4 sequence: 0xCCCC first (starts LSI), then 0x5555 to unlock,
|
||||
// write PR+RLR, wait SR=0 (PVU|RVU), then 0xAAAA to reload the counter.
|
||||
// mg_ota_poll() feeds the watchdog every 500ms while in MG_OTA_TESTING state.
|
||||
#define MG_OTA_ROLLBACK_TIMER_START() \
|
||||
do { \
|
||||
IWDG1->KR = 0xCCCCU; /* start/LSI */ \
|
||||
IWDG1->KR = 0x5555U; /* unlock */ \
|
||||
IWDG1->PR = 7U; /* /512 */ \
|
||||
IWDG1->RLR = 625U; /* 10 s */ \
|
||||
while (IWDG1->SR & (IWDG_SR_PVU | IWDG_SR_RVU)) (void) 0; /* wait SR=0 */ \
|
||||
IWDG1->KR = 0xAAAAU; /* reload */ \
|
||||
} while (0)
|
||||
#define MG_OTA_ROLLBACK_TIMER_FEED() (IWDG1->KR = 0xAAAAU)
|
||||
|
||||
// OTA state in RTC backup register 0 (survives all resets, clears on POR).
|
||||
// Requires hal_backup_domain_init() (called from hal_clock_init) to have run.
|
||||
#define MG_OTA_STATE_GET() (RTC->BKP0R)
|
||||
#define MG_OTA_STATE_SET(v) (RTC->BKP0R = (uint32_t) (v))
|
||||
|
||||
// Health record lives in the .mg_health region, see link.ld
|
||||
#define MG_HEALTH_RAM __attribute__((section(".mg_health")))
|
||||
|
||||
// mdash device token
|
||||
#define MG_ENABLE_MDASH 1
|
||||
|
||||
#ifndef MG_MDASH_KEY
|
||||
#define MG_MDASH_KEY "" // Set this
|
||||
#endif
|
||||
|
||||
// Construct MAC address from the MCU unique ID
|
||||
#define MGUID ((uint32_t *) UID_BASE)
|
||||
#define MG_SET_MAC_ADDRESS(mac) \
|
||||
@@ -65,3 +25,10 @@
|
||||
mac[4] = MGUID[1] & 255; \
|
||||
mac[5] = MGUID[2] & 255; \
|
||||
} while (0)
|
||||
|
||||
// Crash report support. Health record lives in the .mg_health region, see link.ld
|
||||
#define MG_HEALTH_RAM __attribute__((section(".mg_health")))
|
||||
|
||||
// mdash.net device management service support
|
||||
#define MG_ENABLE_MDASH 1
|
||||
#define MG_MDASH_KEY "u8eyWvBmkc6gw9991z1SQ8Lg" // Set this - mDash device token
|
||||
|
||||
Reference in New Issue
Block a user