/* * xtos low level exception handler (in rom) * populates an xtos_regs structure with (most) registers * present at the time of the exception and passes it to the * high-level handler. * * Note that the a1 (sp) register is clobbered (bug? necessity?), * however the original stack pointer can be inferred from the address * of the saved registers area, since the exception handler uses the same * user stack. This might be different in other execution modes on the * quite variegated xtensa platform family, but that's how it works on ESP8266. */ IRAM NOINSTR void esp_exception_handler(struct xtensa_stack_frame *frame) { uint32_t cause = RSR(EXCCAUSE); uint32_t vaddr = RSR(EXCVADDR); fprintf(stderr, "\nTrap %d: pc=%p va=%p\n", cause, (void *) frame->pc, (void *) vaddr); memcpy(®s.a[2], frame->a, sizeof(frame->a)); regs.a[0] = frame->a0; regs.a[1] = (uint32_t) frame + ESP_EXC_SP_OFFSET; regs.pc = frame->pc; regs.sar = frame->sar; regs.ps = frame->ps; regs.litbase = RSR(LITBASE); handle_exception(®s); fprintf(stderr, "rebooting\n"); fs_flush_stderr(); /* * Documented `system_restart` does a lot of things (cleanup) which (seems) * cannot be done from exc handler and only after cleanup it calls * `system_restart_local`. */ system_restart_local(); }
void IRAM NORETURN exception_handler (void *arg) { (void)arg; uint32_t excsave1; uint32_t excvaddr; uint32_t exccause; RSR(excsave1, excsave1); RSR(excvaddr, excvaddr); RSR(exccause, exccause); (void)exception_names; ets_printf("EXCEPTION!! exccause=%d (%s) @%08lx excvaddr=%08lx\n", exccause, exception_names[exccause], excsave1, excvaddr); #if defined(DEVELHELP) #if defined(MODULE_PS) ps(); #endif struct mallinfo minfo = mallinfo(); ets_printf("heap: %lu (free %lu) byte\n", &_eheap - &_sheap, get_free_heap_size()); ets_printf("sysmem: %d (used %d, free %d)\n", minfo.arena, minfo.uordblks, minfo.fordblks); #endif /* flushing the buffer */ ets_printf(" \n"); ets_printf(" \n"); ets_printf(" \n"); /* hard reset */ __asm__ volatile (" call0 0x40000080 "); UNREACHABLE(); }
/* Dump exception information from special function registers */ static void dump_excinfo(void) { uint32_t exccause, epc1, epc2, epc3, excvaddr, depc, excsave1; uint32_t excinfo[8]; RSR(exccause, exccause); printf("Fatal exception (%d): \n", (int)exccause); RSR(epc1, epc1); RSR(epc2, epc2); RSR(epc3, epc3); RSR(excvaddr, excvaddr); RSR(depc, depc); RSR(excsave1, excsave1); printf("%s=0x%08x\n", "epc1", epc1); printf("%s=0x%08x\n", "epc2", epc2); printf("%s=0x%08x\n", "epc3", epc3); printf("%s=0x%08x\n", "excvaddr", excvaddr); printf("%s=0x%08x\n", "depc", depc); printf("%s=0x%08x\n", "excsave1", excsave1); sdk_system_rtc_mem_read(0, excinfo, 32); // Why? excinfo[0] = 2; excinfo[1] = exccause; excinfo[2] = epc1; excinfo[3] = epc2; excinfo[4] = epc3; excinfo[5] = excvaddr; excinfo[6] = depc; excinfo[7] = excsave1; sdk_system_rtc_mem_write(0, excinfo, 32); }
static void unity_run_single_test_by_index_parse(const char* filter, int index_max) { if (s_invert) { printf("Inverse is not supported for that kind of filter\n"); return; } int test_index = strtol(filter, NULL, 10); if (test_index >= 1 && test_index <= index_max) { uint32_t start; RSR(CCOUNT, start); unity_run_single_test_by_index(test_index - 1); uint32_t end; RSR(CCOUNT, end); uint32_t ms = (end - start) / (XT_CLOCK_FREQ / 1000); printf("Test ran in %dms\n", ms); } }
/* Dump normal registers that were stored above 'sp' by the exception handler preamble */ void dump_registers_in_exception_handler(uint32_t *sp) { uint32_t excsave1; uint32_t *saved = sp - (0x50 / sizeof(uint32_t)); printf("Registers:\n"); RSR(excsave1, excsave1); printf("a0 %08x ", excsave1); printf("a1 %08x ", (intptr_t)sp); for(int a = 2; a < 14; a++) { printf("a%-2d %08x%c", a, saved[a+3], a == 3 || a == 7 || a == 11 ? '\n':' '); } printf("SAR %08x\n", saved[0x13]); }
void pp_soft_wdt_feed_local() { struct rst_info rst_info; rst_info.exccause = RSR(EXCCAUSE); rst_info.epc1 = RSR(EPC1); rst_info.epc2 = RSR(EPC2); rst_info.epc3 = RSR(EPC3); rst_info.excvaddr = RSR(EXCVADDR); rst_info.depc = RSR(DEPC); if(wdt_flg == true) { rst_info.reason = REASON_SOFT_WDT_RST; // =3 system_rtc_mem_write(0, &rst_info, sizeof(rst_info)); ets_intr_lock(); Wait_SPI_Idle(flashchip); Cache_Read_Enable_New(); system_restart_local(); } else { rst_info.reason = REASON_WDT_RST; // =1 system_rtc_mem_write(0, &rst_info, sizeof(rst_info)); #if DEF_SDK_VERSION >= 1119 wDev_MacTim1Arm(soft_wdt_interval); #else ets_timer_disarm(SoftWdtTimer); ets_timer_arm_new(SoftWdtTimer, soft_wdt_interval, 0, 1); #endif wdt_flg = true; pp_post(12); } }
void pp_soft_wdt_feed() { struct rst_info rst_info; rst_info.exccause = RSR(EXCCAUSE); rst_info.epc1 = RSR(EPC1); rst_info.epc2 = RSR(EPC2); rst_info.epc3 = RSR(EPC3); rst_info.excvaddr = RSR(EXCVADDR); rst_info.depc = RSR(DEPC); rst_info.reason = WDT_RST_FLAG; system_rtc_mem_write(0, &rst_info, sizeof(rst_info)); if(wdt_flg == true) { Cache_Read_Disable(); Cache_Read_Enable_New(); system_restart_local(); } else { #if SDK_VERSION >= 1119 wDev_MacTim1Arm(soft_wdt_interval); #else ets_timer_disarm(SoftWdtTimer); ets_timer_arm_new(SoftWdtTimer, soft_wdt_interval, 0, 1); #endif wdt_flg = true; pp_post(12); } }
/* Task: - Waits for 'trigger' variable to be set - Reads the cycle count on this CPU - Pushes it into a queue supplied as a param - Busy-waits until the main task terminates it */ static void task_send_to_queue(void *param) { QueueHandle_t queue = (QueueHandle_t) param; uint32_t ccount; while(!trigger) {} RSR(CCOUNT, ccount); flag = true; xQueueSendToBack(queue, &ccount, 0); /* This is to ensure that higher priority task won't wake anyhow, due to this task terminating. The task runs until terminated by the main task. */ while(1) {} }
void store_exception_error(uint32_t errn) { uint32_t *ptr = (uint32_t *)(RTC_MEM_BASE); *ptr++ = errn; *ptr++ = RSR(EXCCAUSE); *ptr++ = RSR(EPC1); *ptr++ = RSR(EPC2); *ptr++ = RSR(EPC3); *ptr++ = RSR(EXCVADDR); *ptr++ = RSR(DEPC); if(errn > RST_EVENT_WDT) _ResetVector(); }
void unity_exec_time_stop(void) { RSR(CCOUNT, s_test_stop); }
void unity_exec_time_start(void) { RSR(CCOUNT, s_test_start); }