From: Michel Pollet Date: Sat, 26 Dec 2009 13:34:15 +0000 (+0000) Subject: core: Shuffled code around X-Git-Tag: v1.0a1~15 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=a01329d1ee30a22840908d26087a72f22355f496;p=sx%2Fsimavr.git core: Shuffled code around Moved cycle timer code into it's own files Signed-off-by: Michel Pollet --- diff --git a/simavr/sim/sim_avr.c b/simavr/sim/sim_avr.c index 1682c2e..0512c2a 100644 --- a/simavr/sim/sim_avr.c +++ b/simavr/sim/sim_avr.c @@ -121,134 +121,6 @@ void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address) memcpy(avr->flash + address, code, size); } -void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v) -{ - if (addr > avr->ramend) { - printf("*** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x out of ram\n", - avr->pc, _avr_sp_get(avr), avr->flash[avr->pc] | (avr->flash[avr->pc]<<8), addr, v); - CRASH(); - } - if (addr < 32) { - printf("*** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x low registers\n", - avr->pc, _avr_sp_get(avr), avr->flash[avr->pc] | (avr->flash[avr->pc]<<8), addr, v); - CRASH(); - } -#if AVR_STACK_WATCH - /* - * this checks that the current "function" is not doctoring the stack frame that is located - * higher on the stack than it should be. It's a sign of code that has overrun it's stack - * frame and is munching on it's own return address. - */ - if (avr->stack_frame_index > 1 && addr > avr->stack_frame[avr->stack_frame_index-2].sp) { - printf("\e[31m%04x : munching stack SP %04x, A=%04x <= %02x\e[0m\n", avr->pc, _avr_sp_get(avr), addr, v); - } -#endif - avr->data[addr] = v; -} - -uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr) -{ - if (addr > avr->ramend) { - printf("*** Invalid read address PC=%04x SP=%04x O=%04x Address %04x out of ram (%04x)\n", - avr->pc, _avr_sp_get(avr), avr->flash[avr->pc] | (avr->flash[avr->pc]<<8), addr, avr->ramend); - CRASH(); - } - return avr->data[addr]; -} - -// converts a number of usec to a number of machine cycles, at current speed -avr_cycle_count_t avr_usec_to_cycles(avr_t * avr, uint32_t usec) -{ - return avr->frequency * (avr_cycle_count_t)usec / 1000000; -} - -uint32_t avr_cycles_to_usec(avr_t * avr, avr_cycle_count_t cycles) -{ - return 1000000 * cycles / avr->frequency; -} - -// converts a number of hz (to megahertz etc) to a number of cycle -avr_cycle_count_t avr_hz_to_cycles(avr_t * avr, uint32_t hz) -{ - return avr->frequency / hz; -} - -void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param) -{ - avr_cycle_timer_cancel(avr, timer, param); - - if (avr->cycle_timer_map == 0xffffffff) { - fprintf(stderr, "avr_cycle_timer_register is full!\n"); - return; - } - when += avr->cycle; - for (int i = 0; i < 32; i++) - if (!(avr->cycle_timer_map & (1 << i))) { - avr->cycle_timer[i].timer = timer; - avr->cycle_timer[i].param = param; - avr->cycle_timer[i].when = when; - avr->cycle_timer_map |= (1 << i); - return; - } -} - -void avr_cycle_timer_register_usec(avr_t * avr, uint32_t when, avr_cycle_timer_t timer, void * param) -{ - avr_cycle_timer_register(avr, avr_usec_to_cycles(avr, when), timer, param); -} - -void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param) -{ - if (!avr->cycle_timer_map) - return; - for (int i = 0; i < 32; i++) - if ((avr->cycle_timer_map & (1 << i)) && - avr->cycle_timer[i].timer == timer && - avr->cycle_timer[i].param == param) { - avr->cycle_timer[i].timer = NULL; - avr->cycle_timer[i].param = NULL; - avr->cycle_timer[i].when = 0; - avr->cycle_timer_map &= ~(1 << i); - return; - } -} - -/* - * run thru all the timers, call the ones that needs it, - * clear the ones that wants it, and calculate the next - * potential cycle we could sleep for... - */ -static avr_cycle_count_t avr_cycle_timer_check(avr_t * avr) -{ - if (!avr->cycle_timer_map) - return (avr_cycle_count_t)-1; - - avr_cycle_count_t min = (avr_cycle_count_t)-1; - - for (int i = 0; i < 32; i++) { - if (!(avr->cycle_timer_map & (1 << i))) - continue; - // do it several times, in case we're late - while (avr->cycle_timer[i].when && avr->cycle_timer[i].when <= avr->cycle) { - // call it - avr->cycle_timer[i].when = - avr->cycle_timer[i].timer(avr, - avr->cycle_timer[i].when, - avr->cycle_timer[i].param); - if (avr->cycle_timer[i].when == 0) { - // clear it - avr->cycle_timer[i].timer = NULL; - avr->cycle_timer[i].param = NULL; - avr->cycle_timer[i].when = 0; - avr->cycle_timer_map &= ~(1 << i); - break; - } - } - if (avr->cycle_timer[i].when && avr->cycle_timer[i].when < min) - min = avr->cycle_timer[i].when; - } - return min - avr->cycle; -} int avr_run(avr_t * avr) { @@ -283,7 +155,7 @@ int avr_run(avr_t * avr) port->run(port); port = port->next; } - avr_cycle_count_t sleep = avr_cycle_timer_check(avr); + avr_cycle_count_t sleep = avr_cycle_timer_process(avr); avr->pc = new_pc; diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 5a96a19..663a57f 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -235,19 +235,6 @@ void avr_set_command_register(avr_t * avr, avr_io_addr_t addr); // load code in the "flash" void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address); -// converts a number of usec to a nunber of machine cycles, at current speed -avr_cycle_count_t avr_usec_to_cycles(avr_t * avr, uint32_t usec); -// converts a number of hz (to megahertz etc) to a number of cycle -avr_cycle_count_t avr_hz_to_cycles(avr_t * avr, uint32_t hz); -// converts back a number of cycles to usecs (for usleep) -uint32_t avr_cycles_to_usec(avr_t * avr, avr_cycle_count_t cycles); - -// register for calling 'timer' in 'when' cycles -void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param); -// register a timer to call in 'when' usec -void avr_cycle_timer_register_usec(avr_t * avr, uint32_t when, avr_cycle_timer_t timer, void * param); -// cancel a previously set timer -void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param); /* * these are accessors for avr->data but allows watchpoints to be set for gdb @@ -265,6 +252,7 @@ void avr_sadly_crashed(avr_t *avr, uint8_t signal); #include "sim_regbit.h" #include "sim_interrupts.h" #include "sim_irq.h" +#include "sim_cycle_timers.h" #endif /*__SIM_AVR_H__*/ diff --git a/simavr/sim/sim_core.c b/simavr/sim/sim_core.c index e7e1f6f..ee95552 100644 --- a/simavr/sim/sim_core.c +++ b/simavr/sim/sim_core.c @@ -84,6 +84,41 @@ int donttrace = 0; #define SREG() #endif +void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v) +{ + if (addr > avr->ramend) { + printf("*** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x out of ram\n", + avr->pc, _avr_sp_get(avr), avr->flash[avr->pc] | (avr->flash[avr->pc]<<8), addr, v); + CRASH(); + } + if (addr < 32) { + printf("*** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x low registers\n", + avr->pc, _avr_sp_get(avr), avr->flash[avr->pc] | (avr->flash[avr->pc]<<8), addr, v); + CRASH(); + } +#if AVR_STACK_WATCH + /* + * this checks that the current "function" is not doctoring the stack frame that is located + * higher on the stack than it should be. It's a sign of code that has overrun it's stack + * frame and is munching on it's own return address. + */ + if (avr->stack_frame_index > 1 && addr > avr->stack_frame[avr->stack_frame_index-2].sp) { + printf("\e[31m%04x : munching stack SP %04x, A=%04x <= %02x\e[0m\n", avr->pc, _avr_sp_get(avr), addr, v); + } +#endif + avr->data[addr] = v; +} + +uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr) +{ + if (addr > avr->ramend) { + printf("*** Invalid read address PC=%04x SP=%04x O=%04x Address %04x out of ram (%04x)\n", + avr->pc, _avr_sp_get(avr), avr->flash[avr->pc] | (avr->flash[avr->pc]<<8), addr, avr->ramend); + CRASH(); + } + return avr->data[addr]; +} + /* * Set a register (r < 256) * if it's an IO regisrer (> 31) also (try to) call any callback that was diff --git a/simavr/sim/sim_cycle_timers.c b/simavr/sim/sim_cycle_timers.c new file mode 100644 index 0000000..f2161d9 --- /dev/null +++ b/simavr/sim/sim_cycle_timers.c @@ -0,0 +1,101 @@ +/* + sim_cycle_timers.c + + Copyright 2008, 2009 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include +#include "sim_cycle_timers.h" + +void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param) +{ + avr_cycle_timer_cancel(avr, timer, param); + + if (avr->cycle_timer_map == 0xffffffff) { + fprintf(stderr, "avr_cycle_timer_register is full!\n"); + return; + } + when += avr->cycle; + for (int i = 0; i < 32; i++) + if (!(avr->cycle_timer_map & (1 << i))) { + avr->cycle_timer[i].timer = timer; + avr->cycle_timer[i].param = param; + avr->cycle_timer[i].when = when; + avr->cycle_timer_map |= (1 << i); + return; + } +} + +void avr_cycle_timer_register_usec(avr_t * avr, uint32_t when, avr_cycle_timer_t timer, void * param) +{ + avr_cycle_timer_register(avr, avr_usec_to_cycles(avr, when), timer, param); +} + +void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param) +{ + if (!avr->cycle_timer_map) + return; + for (int i = 0; i < 32; i++) + if ((avr->cycle_timer_map & (1 << i)) && + avr->cycle_timer[i].timer == timer && + avr->cycle_timer[i].param == param) { + avr->cycle_timer[i].timer = NULL; + avr->cycle_timer[i].param = NULL; + avr->cycle_timer[i].when = 0; + avr->cycle_timer_map &= ~(1 << i); + return; + } +} + +/* + * run thru all the timers, call the ones that needs it, + * clear the ones that wants it, and calculate the next + * potential cycle we could sleep for... + */ +avr_cycle_count_t avr_cycle_timer_process(avr_t * avr) +{ + if (!avr->cycle_timer_map) + return (avr_cycle_count_t)-1; + + avr_cycle_count_t min = (avr_cycle_count_t)-1; + + for (int i = 0; i < 32; i++) { + if (!(avr->cycle_timer_map & (1 << i))) + continue; + // do it several times, in case we're late + while (avr->cycle_timer[i].when && avr->cycle_timer[i].when <= avr->cycle) { + // call it + avr->cycle_timer[i].when = + avr->cycle_timer[i].timer(avr, + avr->cycle_timer[i].when, + avr->cycle_timer[i].param); + if (avr->cycle_timer[i].when == 0) { + // clear it + avr->cycle_timer[i].timer = NULL; + avr->cycle_timer[i].param = NULL; + avr->cycle_timer[i].when = 0; + avr->cycle_timer_map &= ~(1 << i); + break; + } + } + if (avr->cycle_timer[i].when && avr->cycle_timer[i].when < min) + min = avr->cycle_timer[i].when; + } + return min - avr->cycle; +} diff --git a/simavr/sim/sim_cycle_timers.h b/simavr/sim/sim_cycle_timers.h new file mode 100644 index 0000000..8496b6c --- /dev/null +++ b/simavr/sim/sim_cycle_timers.h @@ -0,0 +1,59 @@ +/* + sim_cycle_timers.h + + Copyright 2008, 2009 Michel Pollet + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + + +#ifndef __SIM_CYCLE_TIMERS_H___ +#define __SIM_CYCLE_TIMERS_H___ + +#include "sim_avr.h" + +// converts a number of usec to a number of machine cycles, at current speed +static inline avr_cycle_count_t avr_usec_to_cycles(avr_t * avr, uint32_t usec) +{ + return avr->frequency * (avr_cycle_count_t)usec / 1000000; +} + +// converts back a number of cycles to usecs (for usleep) +static inline uint32_t avr_cycles_to_usec(avr_t * avr, avr_cycle_count_t cycles) +{ + return 1000000 * cycles / avr->frequency; +} + +// converts a number of hz (to megahertz etc) to a number of cycle +static inline avr_cycle_count_t avr_hz_to_cycles(avr_t * avr, uint32_t hz) +{ + return avr->frequency / hz; +} + +// register for calling 'timer' in 'when' cycles +void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param); +// register a timer to call in 'when' usec +void avr_cycle_timer_register_usec(avr_t * avr, uint32_t when, avr_cycle_timer_t timer, void * param); +// cancel a previously set timer +void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param); + + +// +// Private, called from the core +// +avr_cycle_count_t avr_cycle_timer_process(avr_t * avr); + +#endif /* __SIM_CYCLE_TIMERS_H___ */