#include <unistd.h>
#include "sim_avr.h"
#include "sim_core.h"
+#include "sim_time.h"
#include "sim_gdb.h"
#include "avr_uart.h"
#include "sim_vcd_file.h"
#include "avr_mcu_section.h"
+#define AVR_KIND_DECL
+#include "sim_core_decl.h"
int avr_init(avr_t * avr)
{
// cpu is in limbo before init is finished.
avr->state = cpu_Limbo;
- avr->frequency = 1000000; // can be overriden via avr_mcu_section
+ avr->frequency = 1000000; // can be overridden via avr_mcu_section
if (avr->special_init)
avr->special_init(avr);
if (avr->init)
avr->run = avr_callback_run_raw;
avr->sleep = avr_callback_sleep_raw;
avr->state = cpu_Running;
+ avr->log = 1;
avr_reset(avr);
return 0;
}
avr->sreg[i] = 0;
if (avr->reset)
avr->reset(avr);
-
+ avr_interrupt_reset(avr);
+ avr_cycle_timer_reset(avr);
avr_io_t * port = avr->io_port;
while (port) {
if (port->reset)
avr_gdb_init(avr);
}
if (!avr->gdb)
- exit(1); // no gdb ?
+ avr->state = cpu_Crashed;
}
static void _avr_io_command_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
static char * buf = NULL;
static int size = 0, len = 0;
- if (v == '\r') {
+ if (v == '\r' && buf) {
+ buf[len] = 0;
printf("O:" "%s" "" "\n", buf);
fflush(stdout);
+ len = 0;
+ return;
}
if (len + 1 >= size) {
size += 128;
buf = (char*)realloc(buf, size);
}
- buf[len++] = v;
+ if (v >= ' ')
+ buf[len++] = v;
}
void avr_set_console_register(avr_t * avr, avr_io_addr_t addr)
avr_register_io_write(avr, addr, _avr_io_console_write, NULL);
}
-void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address)
+void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, avr_flashaddr_t address)
{
if (size > avr->flashend+1) {
fprintf(stderr, "avr_loadcode(): Attempted to load code of size %d but flash size is only %d.\n",
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))
;
}
if (step)
avr->state = cpu_Running;
- uint16_t new_pc = avr->pc;
+ avr_flashaddr_t new_pc = avr->pc;
if (avr->state == cpu_Running) {
new_pc = avr_run_one(avr);
// if we just re-enabled the interrupts...
// double buffer the I flag, to detect that edge
if (avr->sreg[S_I] && !avr->i_shadow)
- avr->pending_wait++;
+ avr->interrupts.pending_wait++;
avr->i_shadow = avr->sreg[S_I];
- // run the cycle timers, get the suggested sleeo time
+ // run the cycle timers, get the suggested sleep time
// until the next timer is due
avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
if (avr->state == cpu_Sleeping) {
if (!avr->sreg[S_I]) {
- printf("simavr: sleeping with interrupts off, quitting gracefully\n");
- avr_terminate(avr);
- exit(0);
+ if (avr->log)
+ printf("simavr: sleeping with interrupts off, quitting gracefully\n");
+ avr->state = cpu_Done;
+ return;
}
/*
* try to sleep for as long as we can (?)
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)
{
-
- uint16_t new_pc = avr->pc;
+ avr_flashaddr_t new_pc = avr->pc;
if (avr->state == cpu_Running) {
new_pc = avr_run_one(avr);
// if we just re-enabled the interrupts...
// double buffer the I flag, to detect that edge
if (avr->sreg[S_I] && !avr->i_shadow)
- avr->pending_wait++;
+ avr->interrupts.pending_wait++;
avr->i_shadow = avr->sreg[S_I];
- // run the cycle timers, get the suggested sleeo time
+ // run the cycle timers, get the suggested sleep time
// until the next timer is due
avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
if (avr->state == cpu_Sleeping) {
if (!avr->sreg[S_I]) {
- printf("simavr: sleeping with interrupts off, quitting gracefully\n");
- avr_terminate(avr);
- exit(0);
+ if (avr->log)
+ printf("simavr: sleeping with interrupts off, quitting gracefully\n");
+ avr->state = cpu_Done;
+ return;
}
/*
* try to sleep for as long as we can (?)
return avr->state;
}
+avr_t *
+avr_core_allocate(
+ const avr_t * core,
+ uint32_t coreLen)
+{
+ uint8_t * b = malloc(coreLen);
+ memcpy(b, core, coreLen);
+ return (avr_t *)b;
+}
-extern avr_kind_t tiny13;
-extern avr_kind_t tiny2313;
-extern avr_kind_t tiny25,tiny45,tiny85;
-extern avr_kind_t tiny24,tiny44,tiny84;
-extern avr_kind_t mega48,mega88,mega168,mega328;
-extern avr_kind_t mega164,mega324,mega644;
-extern avr_kind_t mega128;
-
-avr_kind_t * avr_kind[] = {
- &tiny13,
- &tiny2313,
- &tiny25, &tiny45, &tiny85,
- &tiny24, &tiny44, &tiny84,
- &mega48, &mega88, &mega168, &mega328,
- &mega164, &mega324, &mega644,
- &mega128,
- NULL
-};
-
-avr_t * avr_make_mcu_by_name(const char *name)
+avr_t *
+avr_make_mcu_by_name(
+ const char *name)
{
avr_kind_t * maker = NULL;
for (int i = 0; avr_kind[i] && !maker; i++) {
}
}
if (!maker) {
- fprintf(stderr, "%s: AVR '%s' now known\n", __FUNCTION__, name);
+ fprintf(stderr, "%s: AVR '%s' not known\n", __FUNCTION__, name);
return NULL;
}