X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=simavr%2Fsim%2Fsim_avr.h;h=737b3ce9bc1862619f49c87e0d66d3efe4570372;hb=33cb87d48ecd68f2000d02659bb3752a329274c8;hp=88026f7637da7eef60479d6d10f1efaffbd7d55b;hpb=1898613e4ff3926250bc98e9917fc57b078f48f0;p=simavr diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 88026f7..737b3ce 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -1,7 +1,7 @@ /* sim_avr.h - Copyright 2008, 2009 Michel Pollet + Copyright 2008-2012 Michel Pollet This file is part of simavr. @@ -22,14 +22,26 @@ #ifndef __SIM_AVR_H__ #define __SIM_AVR_H__ -#include +#ifdef __cplusplus +extern "C" { +#endif + +#include "sim_irq.h" +#include "sim_interrupts.h" +#include "sim_cycle_timers.h" -typedef uint64_t avr_cycle_count_t; +typedef uint32_t avr_flashaddr_t; struct avr_t; -typedef uint8_t (*avr_io_read_t)(struct avr_t * avr, uint8_t addr, void * param); -typedef void (*avr_io_write_t)(struct avr_t * avr, uint8_t addr, uint8_t v, void * param); -typedef avr_cycle_count_t (*avr_cycle_timer_t)(struct avr_t * avr, avr_cycle_count_t when, void * param); +typedef uint8_t (*avr_io_read_t)( + struct avr_t * avr, + avr_io_addr_t addr, + void * param); +typedef void (*avr_io_write_t)( + struct avr_t * avr, + avr_io_addr_t addr, + uint8_t v, + void * param); enum { // SREG bit indexes @@ -42,24 +54,61 @@ enum { // real SREG R_SREG = 32+0x3f, - // maximum number of IO regisrer, on normal AVRs - MAX_IOs = 256 - 32, // minus 32 GP registers + // maximum number of IO registers, on normal AVRs + MAX_IOs = 279, // Bigger AVRs need more than 256-32 (mega1280) }; #define AVR_DATA_TO_IO(v) ((v) - 32) #define AVR_IO_TO_DATA(v) ((v) + 32) /* - * Core states. This will need populating with debug states for gdb + * Core states. */ enum { cpu_Limbo = 0, // before initialization is finished - cpu_Stopped, - cpu_Running, - cpu_Sleeping, + cpu_Stopped, // all is stopped, timers included + + cpu_Running, // we're free running + + cpu_Sleeping, // we're now sleeping until an interrupt - cpu_Step, - cpu_StepDone, + cpu_Step, // run ONE instruction, then... + cpu_StepDone, // tell gdb it's all OK, and give it registers + cpu_Done, // avr software stopped gracefully + cpu_Crashed, // avr software crashed (watchdog fired) +}; + +// this is only ever used if CONFIG_SIMAVR_TRACE is defined +struct avr_trace_data_t { + struct avr_symbol_t ** codeline; + + /* DEBUG ONLY + * this keeps track of "jumps" ie, call,jmp,ret,reti and so on + * allows dumping of a meaningful data even if the stack is + * munched and so on + */ + #define OLD_PC_SIZE 32 + struct { + uint32_t pc; + uint16_t sp; + } old[OLD_PC_SIZE]; // catches reset.. + int old_pci; + +#if AVR_STACK_WATCH + #define STACK_FRAME_SIZE 32 + // this records the call/ret pairs, to try to catch + // code that munches the stack -under- their own frame + struct { + uint32_t pc; + uint16_t sp; + } stack_frame[STACK_FRAME_SIZE]; + int stack_frame_index; +#endif + + // DEBUG ONLY + // keeps track of which registers gets touched by instructions + // reset before each new instructions. Allows meaningful traces + uint32_t touched[256 / 32]; // debug }; /* @@ -75,43 +124,112 @@ typedef struct avr_t { uint8_t vector_size; uint8_t signature[3]; uint8_t fuse[4]; + avr_io_addr_t rampz; // optional, only for ELPM/SPM on >64Kb cores + avr_io_addr_t eind; // optional, only for EIJMP/EICALL on >64Kb cores // filled by the ELF data, this allow tracking of invalid jumps uint32_t codeend; int state; // stopped, running, sleeping uint32_t frequency; // frequency we are running at + // mostly used by the ADC for now + uint32_t vcc,avcc,aref; // (optional) voltages in millivolts + + // cycles gets incremented when sleeping and when running; it corresponds + // 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); + // called at init time (for special purposes like using a memory mapped file as flash see: simduino) + void (*special_init)(struct avr_t * avr); + // called at termination time ( to clean special initializations) + void (*special_deinit)(struct avr_t * avr); // called at reset time void (*reset)(struct avr_t * avr); + /*! + * Default AVR core run function. + * Two modes are available, a "raw" run that goes as fast as + * it can, and a "gdb" mode that also watchouts for gdb events + * and is a little bit slower. + */ + void (*run)(struct avr_t * avr); + + /*! + * Sleep default behaviour. + * In "raw" mode, it calls usleep, in gdb mode, it waits + * for howLong for gdb command on it's sockets. + */ + void (*sleep)(struct avr_t * avr, avr_cycle_count_t howLong); + + /*! + * Every IRQs will be stored in this pool. It is not + * mandatory (yet) but will allow listing IRQs and their connections + */ + avr_irq_pool_t irq_pool; + // Mirror of the SREG register, to facilitate the access to bits // in the opcode decoder. - // This array is re-synthetized back/forth when SREG changes + // This array is re-synthesized back/forth when SREG changes uint8_t sreg[8]; + uint8_t i_shadow; // used to detect edges on I flag /* * ** current PC ** - * Note that the PC is reoresenting /bytes/ while the AVR value is + * Note that the PC is representing /bytes/ while the AVR value is * assumed to be "words". This is in line with what GDB does... - * this is why you will see >>1 ane <<1 in the decoder to handle jumps + * this is why you will see >>1 and <<1 in the decoder to handle jumps. + * It CAN be a little confusing, so concentrate, young grasshopper. */ - uint32_t pc; + avr_flashaddr_t pc; /* - * callback when specific IO registers are read/written + * callback when specific IO registers are read/written. + * There is one drawback here, there is in way of knowing what is the + * "beginning of useful sram" on a core, so there is no way to deduce + * what is the maximum IO register for a core, and thus, we can't + * allocate this table dynamically. + * If you wanted to emulate the BIG AVRs, and XMegas, this would need + * work. */ struct { - void * param; - avr_io_read_t r; - } ior[MAX_IOs]; + struct avr_irq_t * irq; // optional, used only if asked for with avr_iomem_getirq() + struct { + void * param; + avr_io_read_t c; + } r; + struct { + void * param; + avr_io_write_t c; + } w; + } io[MAX_IOs]; + + /* + * This block allows sharing of the IO write/read on addresses between + * multiple callbacks. In 99% of case it's not needed, however on the tiny* + * (tiny85 at last) some registers have bits that are used by different + * IO modules. + * If this case is detected, a special "dispatch" callback is installed that + * will handle this particular case, without impacting the performance of the + * other, normal cases... + */ + int io_shared_io_count; struct { - void * param; - avr_io_write_t w; - } iow[MAX_IOs]; + int used; + struct { + void * param; + void * c; + } io[4]; + } io_shared_io[4]; // flash memory (initialized to 0xff, and code loaded into it) uint8_t * flash; @@ -121,56 +239,28 @@ typedef struct avr_t { // queue of io modules struct avr_io_t *io_port; - // cycle timers are callbacks that will be called when "when" cycle is reached - // the bitmap allows quick knowledge of whether there is anything to call - // these timers are one shots, then get cleared if the timer function returns zero, - // they get reset if the callback function returns a new cycle number - uint32_t cycle_timer_map; - struct { - avr_cycle_count_t when; - avr_cycle_timer_t timer; - void * param; - } cycle_timer[32]; + // cycle timers tracking & delivery + avr_cycle_timer_pool_t cycle_timers; + // interrupt vectors and delivery fifo + avr_int_table_t interrupts; - // interrupt vectors, and their enable/clear registers - struct avr_int_vector_t * vector[64]; - uint8_t pending_wait; // number of cycles to wait for pending - uint32_t pending[2]; // pending interrupts + // DEBUG ONLY -- value ignored if CONFIG_SIMAVR_TRACE = 0 + uint8_t trace : 1, + log : 2; // log level, default to 1 - // DEBUG ONLY - int trace; - struct avr_symbol_t ** codeline; - - /* DEBUG ONLY - * this keeps track of "jumps" ie, call,jmp,ret,reti and so on - * allows dumping of a meaningful data even if the stack is - * munched and so on - */ - #define OLD_PC_SIZE 32 - struct { - uint32_t pc; - uint16_t sp; - } old[OLD_PC_SIZE]; // catches reset.. - int old_pci; - -#if AVR_STACK_WATCH - #define STACK_FRAME_SIZE 32 - // this records the call/ret pairs, to try to catch - // code that munches the stack -under- their own frame - struct { - uint32_t pc; - uint16_t sp; - } stack_frame[STACK_FRAME_SIZE]; - int stack_frame_index; -#endif - - // DEBUG ONLY - // keeps track of wich registers gets touched by instructions - // reset before each new instructions. Allows meaningful traces - uint32_t touched[256 / 32]; // debug + // Only used if CONFIG_SIMAVR_TRACE is defined + struct avr_trace_data_t *trace_data; + // VALUE CHANGE DUMP file (waveforms) + // this is the VCD file that gets allocated if the + // firmware that is loaded explicitly asks for a trace + // to be generated, and allocates it's own symbols + // using AVR_MMCU_TAG_VCD_TRACE (see avr_mcu_section.h) + struct avr_vcd_t * vcd; + // gdb hooking structure. Only present when gdb server is active struct avr_gdb_t * gdb; + // if non-zero, the gdb server will be started when the core // crashed even if not activated at startup // if zero, the simulator will just exit() in case of a crash @@ -191,47 +281,91 @@ typedef struct avr_symbol_t { } avr_symbol_t; // locate the maker for mcu "name" and allocates a new avr instance -avr_t * avr_make_mcu_by_name(const char *name); +avr_t * +avr_make_mcu_by_name( + const char *name); // initializes a new AVR instance. Will call the IO registers init(), and then reset() -int avr_init(avr_t * avr); +int +avr_init( + avr_t * avr); +// Used by the cores, allocated a mutable avr_t from the const global +avr_t * +avr_core_allocate( + const avr_t * core, + uint32_t coreLen); + // resets the AVR, and the IO modules -void avr_reset(avr_t * avr); +void +avr_reset( + avr_t * avr); // run one cycle of the AVR, sleep if necessary -int avr_run(avr_t * avr); +int +avr_run( + avr_t * avr); +// finish any pending operations +void +avr_terminate( + avr_t * avr); + +// set an IO register to receive commands from the AVR firmware +// it's optional, and uses the ELF tags +void +avr_set_command_register( + avr_t * avr, + avr_io_addr_t addr); + +// specify the "console register" -- output sent to this register +// is printed on the simulator console, without using a UART +void +avr_set_console_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 nunber 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); +void +avr_loadcode( + avr_t * avr, + uint8_t * code, + uint32_t size, + avr_flashaddr_t address); /* - * these are accessors for avr->data but allows watchpoints to be set for gdb + * These are accessors for avr->data but allows watchpoints to be set for gdb * IO modules use that to set values to registers, and the AVR core decoder uses * that to register "public" read by instructions. */ -void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v); -uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr); +void +avr_core_watch_write( + avr_t *avr, + uint16_t addr, + uint8_t v); +uint8_t +avr_core_watch_read( + avr_t *avr, + uint16_t addr); // called when the core has detected a crash somehow. // this might activate gdb server -void avr_sadly_crashed(avr_t *avr, uint8_t signal); +void +avr_sadly_crashed( + avr_t *avr, + uint8_t signal); + + +/* + * These are callbacks for the two 'main' behaviour in simavr + */ +void avr_callback_sleep_gdb(avr_t * avr, avr_cycle_count_t howLong); +void avr_callback_run_gdb(avr_t * avr); +void avr_callback_sleep_raw(avr_t * avr, avr_cycle_count_t howLong); +void avr_callback_run_raw(avr_t * avr); + +#ifdef __cplusplus +}; +#endif #include "sim_io.h" #include "sim_regbit.h" -#include "sim_interrupts.h" -#include "sim_irq.h" #endif /*__SIM_AVR_H__*/