From aadaf418bc7d8bb09a85257b77fb8c40addf4b63 Mon Sep 17 00:00:00 2001 From: Edgar Bonet Date: Sat, 6 Jun 2020 23:35:28 +0200 Subject: [PATCH] run_avr: gracefully quit on exit() from firmware When the firmware calls exit() or returns from main(), it ends up running _exit(), which disables interrupts and hangs the CPU in an infinite, empty loop. run_avr now terminates the simulation if the CPU-hanging instruction (rjmp .-2) is executed with interrupts disabled. --- simavr/sim/sim_avr.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/simavr/sim/sim_avr.c b/simavr/sim/sim_avr.c index 6e43bf91f..d08b2ec77 100644 --- a/simavr/sim/sim_avr.c +++ b/simavr/sim/sim_avr.c @@ -282,6 +282,16 @@ avr_callback_sleep_gdb( ; } +static void +gracefully_quit( + avr_t * avr, + const char * reason) +{ + if (avr->log) + AVR_LOG(avr, LOG_TRACE, "simavr: %s, quitting gracefully\n", reason); + avr->state = cpu_Done; +} + void avr_callback_run_gdb( avr_t * avr) @@ -309,13 +319,16 @@ avr_callback_run_gdb( // until the next timer is due avr_cycle_count_t sleep = avr_cycle_timer_process(avr); + if (avr->state == cpu_Running && new_pc == avr->pc && avr->flash[new_pc] == 0xff && avr->flash[new_pc+1] == 0xcf && !avr->sreg[S_I]) { + gracefully_quit(avr, "rjmp .-2 with interrupts off"); + return; + } + avr->pc = new_pc; if (avr->state == cpu_Sleeping) { if (!avr->sreg[S_I]) { - if (avr->log) - AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n"); - avr->state = cpu_Done; + gracefully_quit(avr, "sleeping with interrupts off"); return; } /* @@ -372,13 +385,16 @@ avr_callback_run_raw( // until the next timer is due avr_cycle_count_t sleep = avr_cycle_timer_process(avr); + if (avr->state == cpu_Running && new_pc == avr->pc && avr->flash[new_pc] == 0xff && avr->flash[new_pc+1] == 0xcf && !avr->sreg[S_I]) { + gracefully_quit(avr, "rjmp .-2 with interrupts off"); + return; + } + avr->pc = new_pc; if (avr->state == cpu_Sleeping) { if (!avr->sreg[S_I]) { - if (avr->log) - AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n"); - avr->state = cpu_Done; + gracefully_quit(avr, "sleeping with interrupts off"); return; } /*