From: Jakob Gruber Date: Thu, 19 Jul 2012 21:37:02 +0000 (+0200) Subject: simavr: Improved accuracy of sleep durations X-Git-Tag: v1.0~54 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=8e195b43da0db4f2e9bd6f56cf68ba91b57676e2;p=sx%2Fsimavr.git simavr: Improved accuracy of sleep durations This commit solves (or at least improves) an issue that occurs when short sleep times are requested in avr_callback_sleep_*. The operating system cannot accurately handle short sleep requests, and sending many short requests takes significantly longer than requesting the equivalent time in longer bursts. This can be observed by running the board_hd77480 example - the counter is much slower when vcd recording is turned on (= short sleep requests) than when it is turned off (= long sleep requests). We improve this situation by accumulating sleep requests until a certain minimum count of pending usecs is reached which can be handled somewhat accurately (200 microseconds worked well for me). --- diff --git a/simavr/sim/sim_avr.c b/simavr/sim/sim_avr.c index fe1f007..37fae8f 100644 --- a/simavr/sim/sim_avr.c +++ b/simavr/sim/sim_avr.c @@ -173,9 +173,25 @@ void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, avr_flashaddr_t ad memcpy(avr->flash + address, code, size); } +/** + * Accumulates sleep requests (and returns a sleep time of 0) until + * a minimum count of requested sleep microseconds are reached + * (low amounts cannot be handled accurately). + */ +static inline uint32_t avr_pending_sleep_usec(avr_t * avr, avr_cycle_count_t howLong) +{ + avr->sleep_usec += avr_cycles_to_usec(avr, howLong); + uint32_t usec = avr->sleep_usec; + if (usec > 200) { + avr->sleep_usec = 0; + return usec; + } + return 0; +} + void avr_callback_sleep_gdb(avr_t * avr, avr_cycle_count_t howLong) { - uint32_t usec = avr_cycles_to_usec(avr, howLong); + uint32_t usec = avr_pending_sleep_usec(avr, howLong); while (avr_gdb_processor(avr, usec)) ; } @@ -239,8 +255,10 @@ void avr_callback_run_gdb(avr_t * avr) void avr_callback_sleep_raw(avr_t * avr, avr_cycle_count_t howLong) { - uint32_t usec = avr_cycles_to_usec(avr, howLong); - usleep(usec); + uint32_t usec = avr_pending_sleep_usec(avr, howLong); + if (usec > 0) { + usleep(usec); + } } void avr_callback_run_raw(avr_t * avr) diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 199af29..f7ac26d 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -139,6 +139,13 @@ typedef struct avr_t { // not only to "cycles that runs" but also "cycles that might have run" // like, sleeping. avr_cycle_count_t cycle; // current cycle + + /** + * Sleep requests are accumulated in sleep_usec until the minimum sleep value + * is reached, at which point sleep_usec is cleared and the sleep request + * is passed on to the operating system. + */ + uint32_t sleep_usec; // called at init time void (*init)(struct avr_t * avr);