Commit 4ebde35337d05315c5170390377ef3a0f9dde53c
authorMichel Pollet <buserror@gmail.com>
Thu, 3 Dec 2009 23:31:42 +0000 (23:31 +0000)
committerMichel Pollet <buserror@gmail.com>
Thu, 3 Dec 2009 23:31:42 +0000 (23:31 +0000)
GDB handler re-done, removed the thread, removed the pauses,
Now as fast as possible for stepping trhu code.
Note you /need/ the dwarf-2 debug symbols for gdb to work
properly, a simple '-g' will not work.

Also added a mode that starts the gdb server and waits if the
AVR core detects a "crash". Added a piece if test unit to
test just that.

Signed-off-by: Michel Pollet <buserror@gmail.com>
26 files changed:
.gitignore
Makefile.common [new file with mode: 0644]
simavr/Makefile
simavr/cores/sim_mega644.c
simavr/cores/sim_tiny85.c
simavr/sim/avr_eeprom.c
simavr/sim/avr_ioport.c
simavr/sim/avr_spi.c
simavr/sim/avr_spi.h
simavr/sim/avr_timer8.c
simavr/sim/avr_uart.c
simavr/sim/run_avr.c
simavr/sim/sim_avr.c
simavr/sim/sim_avr.h
simavr/sim/sim_core.h
simavr/sim/sim_elf.c
simavr/sim/sim_elf.h
simavr/sim/sim_gdb.c
simavr/sim/sim_gdb.h
simavr/sim/sim_interrupts.c
simavr/sim/sim_io.c
simavr/sim/sim_io.h
simavr/sim/sim_irq.c
simavr/sim/sim_irq.h
tests/Makefile
tests/attiny85_crash_gdb.c [new file with mode: 0644]

index 543ae13f810bd32d56bd50463df97bc5bcfe0bbf..f7e610b23b9b668cfab32dcbfe906ade11881da2 100644 (file)
@@ -4,3 +4,4 @@ obj
 *.s
 simavr/simavr
 simavr/run_avr
+*.a
diff --git a/Makefile.common b/Makefile.common
new file mode 100644 (file)
index 0000000..1f89b04
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# This makefile take each "at*" file, extracts it's part name
+# And compile it into an ELF binary.
+# It also disassemble it for debugging purposes.
+# 
+# The code is compiled "optimized" to the max.
+# 
+# The wierd "-Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000"
+# is used to tell the linker not to discard the .mmcu section,
+# otherwise the --gc-sections will delete it.
+# 
+#      Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
+#
+#      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 <http://www.gnu.org/licenses/>.
+
+%.hex: %.axf
+               @${AVR}objcopy -j .text -j .data -O ihex ${<} ${@}
+
+%.s: %.axf
+               @${AVR}objdump -j .text -j .data -j .bss -d  ${<} > ${@}
+
+# --mcall-prologues 
+%.axf: %.c 
+               @echo CC ${<}
+               @part=${<} ; part=$${part/_*}; \
+               ${AVR}gcc -Wall -gdwarf-2 -Os -std=gnu99 \
+                               -mmcu=$$part \
+                               -DF_CPU=8000000 \
+                               -fno-inline-small-functions \
+                               -ffunction-sections -fdata-sections \
+                               -Wl,--relax,--gc-sections \
+                               -Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000 \
+                               -I../include \
+                               ${<} -o ${@}
+               @${AVR}size ${@}|sed '1d'
index 3625912a3557d0788900b318bb18613e2c7826e0..eba24e088c333eff26acbf6fa1572fb58bf26b06 100644 (file)
@@ -29,7 +29,7 @@ CFLAGS        += -O3  -mfpmath=sse -msse2
 
 cores  = ${wildcard cores/*.c}
 cores_o = ${patsubst cores/%.c, obj/%.o, ${cores}}
-sim            = ${wildcard sim/*.c}
+sim            = ${wildcard sim/sim_*.c} ${wildcard sim/avr_*.c}
 sim_o  = ${patsubst sim/%.c, obj/%.o, ${sim}}
 
 VPATH  = .
@@ -44,9 +44,9 @@ IPATH += /opt/local/include
 
 CFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}}
 LFLAGS = -L/opt/local/lib/
-LDFLAGS        += -lelf -lpthread
+LDFLAGS        += -lelf 
 
-all:   obj ${target}
+all:   obj ${target} libsimavr.a
 
 obj:
        @mkdir -p obj
@@ -63,14 +63,20 @@ obj/%.o: %.c
        @gcc $(CFLAGS) \
                $<  -c -o $@
        @echo CC $<
-       
+
+libsimavr.a    :       ${cores_o}
+libsimavr.a    :       ${sim_o}
+       ar cru $@ $^
+       ranlib $@
+
 ${target}      :       ${cores_o}
 ${target}      :       ${sim_o}
+${target}      :       obj/${target}.o
        @gcc $(CFLAGS) $(LFLAGS) \
                ${^} -o $@ \
                 $(LDFLAGS)
        @echo LD $@
 
 clean:
-       rm -rf ${target} obj
+       rm -rf ${target} obj *.a
 
index f240a2f1d878666cae5a367eabcd5aa97762ae04..cc1b396c2754a17306760bfecbe5c19dc6adee33 100644 (file)
@@ -26,6 +26,7 @@
 #include "avr_ioport.h"
 #include "avr_uart.h"
 #include "avr_timer8.h"
+#include "avr_spi.h"
 
 #define _AVR_IO_H_
 #define __ASSEMBLER__
@@ -41,6 +42,7 @@ static struct mcu_t {
        avr_ioport_t    porta, portb, portc, portd;
        avr_uart_t              uart0,uart1;
        avr_timer8_t    timer0,timer2;
+       avr_spi_t               spi;
 } mcu = {
        .core = {
                .mmcu = "atmega644",
@@ -201,6 +203,23 @@ static struct mcu_t {
                        .vector = TIMER2_COMPB_vect,
                },
        },
+       .spi = {
+               .disabled = AVR_IO_REGBIT(PRR,PRSPI),
+
+               .r_spdr = SPDR,
+               .r_spcr = SPCR,
+               .r_spsr = SPSR,
+
+               .spe = AVR_IO_REGBIT(SPCR, SPE),
+               .mstr = AVR_IO_REGBIT(SPCR, MSTR),
+
+               .spr = { AVR_IO_REGBIT(SPCR, SPR0), AVR_IO_REGBIT(SPCR, SPR1), AVR_IO_REGBIT(SPSR, SPI2X) },
+               .spi = {
+                       .enable = AVR_IO_REGBIT(SPCR, SPIE),
+                       .raised = AVR_IO_REGBIT(SPSR, SPIF),
+                       .vector = SPI_STC_vect,
+               },
+       },
 };
 
 static avr_t * make()
@@ -228,6 +247,7 @@ static void init(struct avr_t * avr)
        avr_uart_init(avr, &mcu->uart1);
        avr_timer8_init(avr, &mcu->timer0);
        avr_timer8_init(avr, &mcu->timer2);
+       avr_spi_init(avr, &mcu->spi);
 }
 
 static void reset(struct avr_t * avr)
index eec13a639b191e9118fc36e2b3461c46222c115a..aac82996d50b715540e23319106264f10c256e82 100644 (file)
@@ -120,6 +120,7 @@ static avr_t * make()
 }
 
 avr_kind_t tiny85 = {
+       .names = { "attiny85" },
        .make = make
 };
 
index 53c82f0bd1ddd894e08bb1e62870a769ebdd4d93..eebdf3154db3271a8b3ebaf8a50f4355135238ed 100644 (file)
 #include <string.h>
 #include "avr_eeprom.h"
 
-static void avr_eeprom_run(avr_t * avr, avr_io_t * port)
+static void avr_eeprom_run(avr_io_t * port)
 {
        avr_eeprom_t * p = (avr_eeprom_t *)port;
+       avr_t * avr = p->io.avr;
        //printf("%s\n", __FUNCTION__);
        if (p->eempe_clear_timer) {
                p->eempe_clear_timer--;
@@ -44,7 +45,7 @@ static void avr_eeprom_run(avr_t * avr, avr_io_t * port)
        }
 }
 
-static void avr_eeprom_write(struct avr_t * avr, uint8_t addr, uint8_t v, void * param)
+static void avr_eeprom_write(avr_t * avr, uint8_t addr, uint8_t v, void * param)
 {
        avr_eeprom_t * p = (avr_eeprom_t *)param;
        uint8_t eempe = avr_regbit_get(avr, p->eempe);
@@ -76,7 +77,7 @@ static void avr_eeprom_write(struct avr_t * avr, uint8_t addr, uint8_t v, void *
        avr_regbit_clear(avr, p->eere);
 }
 
-static int avr_eeprom_ioctl(avr_t * avr, avr_io_t * port, uint32_t ctl, void * io_param)
+static int avr_eeprom_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
 {
        avr_eeprom_t * p = (avr_eeprom_t *)port;
        int res = -1;
index 7394c0c792a8a280d5dcbc79071b10a54ba3c873..2b3eaaed63dba9aadacbbd44c1747c18208904fb 100644 (file)
 #include <stdio.h>
 #include "avr_ioport.h"
 
-static void avr_ioport_run(avr_t * avr, avr_io_t * port)
-{
-       //printf("%s\n", __FUNCTION__);
-}
-
 static uint8_t avr_ioport_read(struct avr_t * avr, uint8_t addr, void * param)
 {
        avr_ioport_t * p = (avr_ioport_t *)param;
@@ -58,8 +53,8 @@ static void avr_ioport_write(struct avr_t * avr, uint8_t addr, uint8_t v, void *
                        // raise the internal IRQ callbacks
                        for (int i = 0; i < 8; i++)
                                if (mask & (1 << i))
-                                       avr_raise_irq(avr, p->io.irq + i, (v >> i) & 1);
-                       avr_raise_irq(avr, p->io.irq + IOPORT_IRQ_PIN_ALL, v);
+                                       avr_raise_irq(p->io.irq + i, (v >> i) & 1);
+                       avr_raise_irq(p->io.irq + IOPORT_IRQ_PIN_ALL, v);
                }
        }
 }
@@ -69,9 +64,10 @@ static void avr_ioport_write(struct avr_t * avr, uint8_t addr, uint8_t v, void *
  * AVR code, or any external piece of code that see fit to do it.
  * Either way, this will raise pin change interrupts, if needed
  */
-void avr_ioport_irq_notify(avr_t * avr, struct avr_irq_t * irq, uint32_t value, void * param)
+void avr_ioport_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
 {
        avr_ioport_t * p = (avr_ioport_t *)param;
+       avr_t * avr = p->io.avr;
        if (p->r_pcint) {
                uint8_t mask = 1 << irq->irq;
                // set the real PIN bit. ddr doesn't matter here as it's masked when read.
@@ -85,16 +81,15 @@ void avr_ioport_irq_notify(avr_t * avr, struct avr_irq_t * irq, uint32_t value,
        }
 }
 
-static void avr_ioport_reset(avr_t * avr, avr_io_t * port)
+static void avr_ioport_reset(avr_io_t * port)
 {
        avr_ioport_t * p = (avr_ioport_t *)port;
        for (int i = 0; i < IOPORT_IRQ_PIN_ALL; i++) 
-               avr_irq_register_notify(avr, p->io.irq + i, avr_ioport_irq_notify, p);
+               avr_irq_register_notify(p->io.irq + i, avr_ioport_irq_notify, p);
 }
 
 static avr_io_t        _io = {
        .kind = "io",
-       .run = avr_ioport_run,
        .reset = avr_ioport_reset,
 };
 
@@ -108,7 +103,7 @@ void avr_ioport_init(avr_t * avr, avr_ioport_t * p)
 
        // allocate this module's IRQ
        p->io.irq_count = IOPORT_IRQ_COUNT;
-       p->io.irq = avr_alloc_irq(avr, 0, p->io.irq_count);
+       p->io.irq = avr_alloc_irq(0, p->io.irq_count);
        p->io.irq_ioctl_get = AVR_IOCTL_IOPORT_GETIRQ(p->name);
        
        avr_register_io(avr, &p->io);
index 01b0d7f99896e3d971f44509393bbc85989baaa2..1ef1ee982a1fd74a973a3415bb16cf2f15c3b4c4 100644 (file)
 #include <stdio.h>
 #include "avr_spi.h"
 
-static void avr_spi_run(avr_t * avr, avr_io_t * port)
-{
-//     printf("%s\n", __FUNCTION__);
-}
-
 static uint8_t avr_spi_read(struct avr_t * avr, uint8_t addr, void * param)
 {
        avr_spi_t * p = (avr_spi_t *)param;
-       uint8_t v = avr->data[addr];
+       uint8_t v = p->input_data_register;
+       p->input_data_register = 0;
 //     printf("** PIN%c = %02x\n", p->name, v);
        return v;
 }
@@ -42,29 +38,44 @@ static void avr_spi_write(struct avr_t * avr, uint8_t addr, uint8_t v, void * pa
        if (addr == p->r_spdr) {
        //      printf("UDR%c(%02x) = %02x\n", p->name, addr, v);
                avr_core_watch_write(avr, addr, v);
+
+               if (avr_regbit_get(avr, p->spe)) {
+                       // in master mode, any byte is sent as it comes..
+                       if (avr_regbit_get(avr, p->mstr)) {
+                               avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, v);
+                       }
+               }
        }
 }
 
-static void avr_spi_irq_input(avr_t * avr, struct avr_irq_t * irq, uint32_t value, void * param)
+static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
 {
        avr_spi_t * p = (avr_spi_t *)param;
+       avr_t * avr = p->io.avr;
 
        // check to see fi receiver is enabled
        if (!avr_regbit_get(avr, p->spe))
                return;
 
        // double buffer the input.. ?
+       p->input_data_register = value;
+       avr_raise_interrupt(avr, &p->spi);
+
+       // if in slave mode, 
+       // 'output' the byte only when we received one...
+       if (!avr_regbit_get(avr, p->mstr)) {
+               avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
+       }
 }
 
-void avr_spi_reset(avr_t * avr, struct avr_io_t *io)
+void avr_spi_reset(struct avr_io_t *io)
 {
        avr_spi_t * p = (avr_spi_t *)io;
-       avr_irq_register_notify(avr, p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p);
+       avr_irq_register_notify(p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p);
 }
 
 static avr_io_t        _io = {
        .kind = "spi",
-       .run = avr_spi_run,
        .reset = avr_spi_reset,
 };
 
@@ -77,7 +88,7 @@ void avr_spi_init(avr_t * avr, avr_spi_t * p)
 
        // allocate this module's IRQ
        p->io.irq_count = SPI_IRQ_COUNT;
-       p->io.irq = avr_alloc_irq(avr, 0, p->io.irq_count);
+       p->io.irq = avr_alloc_irq(0, p->io.irq_count);
        p->io.irq_ioctl_get = AVR_IOCTL_SPI_GETIRQ(p->name);
 
        avr_register_io_write(avr, p->r_spdr, avr_spi_write, p);
index 2c24e5285e3a42296f6470b3bee7277682e49c48..9926e66f5808aa8afba68250feb72e114568a6ce 100644 (file)
@@ -47,6 +47,8 @@ typedef struct avr_spi_t {
        avr_regbit_t spr[4];    // clock divider
        
        avr_int_vector_t spi;   // spi interrupt
+
+       uint8_t         input_data_register;
 } avr_spi_t;
 
 void avr_spi_init(avr_t * avr, avr_spi_t * port);
index 6cf20c081f88c55cf608aeddb92d04da51d84134..1e209f93e35f1d6bc11220dd6cf6e269368aabdc 100644 (file)
 #include <stdio.h>
 #include "avr_timer8.h"
 
-static void avr_timer8_run(avr_t * avr, avr_io_t * port)
+static void avr_timer8_run(avr_io_t * port)
 {
        avr_timer8_t * p = (avr_timer8_t *)port;
-       //printf("%s\n", __FUNCTION__);
+       avr_t * avr = p->io.avr;
 
        if (p->compa_cycles) {
                if (p->compa_next == 0) {
@@ -79,7 +79,7 @@ static void avr_timer8_write(struct avr_t * avr, uint8_t addr, uint8_t v, void *
        
 }
 
-static void avr_timer8_reset(avr_t * avr, avr_io_t * port)
+static void avr_timer8_reset(avr_io_t * port)
 {
 }
 
index 35b8b0db950c638a687cfde3b0a9efbd63e0d586..e268cf73edff94bf1943a3ce755adcdd93a9c8ee 100644 (file)
 
 DEFINE_FIFO(uint8_t, uart_fifo, 128);
 
-static void avr_uart_run(avr_t * avr, avr_io_t * port)
+static void avr_uart_run(avr_io_t * port)
 {
        avr_uart_t * p = (avr_uart_t *)port;
+       avr_t * avr = p->io.avr;
        if (p->input_cycle_timer) {
                p->input_cycle_timer--;
                if (p->input_cycle_timer == 0) {
@@ -81,7 +82,7 @@ static void avr_uart_write(struct avr_t * avr, uint8_t addr, uint8_t v, void * p
                }
                // tell other modules we are "outputing" a byte
                if (avr_regbit_get(avr, p->txen))
-                       avr_raise_irq(avr, p->io.irq + UART_IRQ_OUTPUT, v);
+                       avr_raise_irq(p->io.irq + UART_IRQ_OUTPUT, v);
        } else {
                // get the bits before the write
                uint8_t udre = avr_regbit_get(avr, p->udrc.raised);
@@ -97,9 +98,10 @@ static void avr_uart_write(struct avr_t * avr, uint8_t addr, uint8_t v, void * p
        }
 }
 
-static void avr_uart_irq_input(avr_t * avr, struct avr_irq_t * irq, uint32_t value, void * param)
+static void avr_uart_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
 {
        avr_uart_t * p = (avr_uart_t *)param;
+       avr_t * avr = p->io.avr;
 
        // check to see fi receiver is enabled
        if (!avr_regbit_get(avr, p->rxen))
@@ -112,11 +114,12 @@ static void avr_uart_irq_input(avr_t * avr, struct avr_irq_t * irq, uint32_t val
 }
 
 
-void avr_uart_reset(avr_t * avr, struct avr_io_t *io)
+void avr_uart_reset(struct avr_io_t *io)
 {
        avr_uart_t * p = (avr_uart_t *)io;
+       avr_t * avr = p->io.avr;
        avr_regbit_set(avr, p->udrc.raised);
-       avr_irq_register_notify(avr, p->io.irq + UART_IRQ_INPUT, avr_uart_irq_input, p);
+       avr_irq_register_notify(p->io.irq + UART_IRQ_INPUT, avr_uart_irq_input, p);
        p->input_cycle_timer = 0;
        uart_fifo_reset(&p->input);
 }
@@ -136,7 +139,7 @@ void avr_uart_init(avr_t * avr, avr_uart_t * p)
 
        // allocate this module's IRQ
        p->io.irq_count = UART_IRQ_COUNT;
-       p->io.irq = avr_alloc_irq(avr, 0, p->io.irq_count);
+       p->io.irq = avr_alloc_irq(0, p->io.irq_count);
        p->io.irq_ioctl_get = AVR_IOCTL_UART_GETIRQ(p->name);
 
        avr_register_io_write(avr, p->r_udr, avr_uart_write, p);
index 45600331669d0f76d8767f75c5cd7091f9e5748d..49c374c8464695c7375f1bfbac780080e5b22477 100644 (file)
@@ -27,7 +27,6 @@
 #include "sim_elf.h"
 #include "sim_core.h"
 #include "sim_gdb.h"
-#include "avr_eeprom.h"
 #include "avr_uart.h"
 
 void hdump(const char *w, uint8_t *b, size_t l)
@@ -116,33 +115,25 @@ int main(int argc, char *argv[])
                exit(1);
        }
        avr_init(avr);
-       avr->frequency = f.mmcu.f_cpu;
-       avr->codeline = f.codeline;
-       avr_loadcode(avr, f.flash, f.flashsize, 0);
-       avr->codeend = f.flashsize - f.datasize;
-       if (f.eeprom && f.eesize) {
-               avr_eeprom_desc_t d = { .ee = f.eeprom, .offset = 0, .size = f.eesize };
-               avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
-       }
+       avr_load_firmware(avr, &f);
        avr->trace = trace;
 
        // try to enable "local echo" on the first uart, for testing purposes
        {
                avr_irq_t * src = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUTPUT);
                avr_irq_t * dst = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_INPUT);
-               printf("%s:%s activating uart local echo IRQ src %p dst %p\n", __FILE__, __FUNCTION__, src, dst);
-               if (src && dst)
-                       avr_connect_irq(avr, src, dst);
+               if (src && dst) {
+                       printf("%s:%s activating uart local echo IRQ src %p dst %p\n", __FILE__, __FUNCTION__, src, dst);
+                       avr_connect_irq(src, dst);
+               }
        }
-
+       // even if not setup at startup, activate gdb if crashing
+       avr->gdb_port = 1234;
        if (gdb) {
                avr->state = cpu_Stopped;
                avr_gdb_init(avr);
        }
 
-//     for (long long i = 0; i < 8000000*10; i++)
-//     for (long long i = 0; i < 80000; i++)
        for (;;)
-               avr_run(avr);
-       
+               avr_run(avr);   
 }
index 16a908add73d209034e79ca578e655d2373aae8f..46ed8de8f525b0421ed096d9ab2b38af45126fe2 100644 (file)
@@ -58,11 +58,22 @@ void avr_reset(avr_t * avr)
        avr_io_t * port = avr->io_port;
        while (port) {
                if (port->reset)
-                       port->reset(avr, port);
+                       port->reset(port);
                port = port->next;
        }
 }
 
+void avr_sadly_crashed(avr_t *avr, uint8_t signal)
+{
+       avr->state = cpu_Stopped;
+       if (avr->gdb_port) {
+               // enable gdb server, and wait
+               if (!avr->gdb)
+                       avr_gdb_init(avr);
+       } 
+       if (!avr->gdb)
+               exit(1); // no gdb ?
+}
 
 void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address)
 {
@@ -107,13 +118,12 @@ uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr)
 
 int avr_run(avr_t * avr)
 {
-       avr_gdb_processor(avr);
+       avr_gdb_processor(avr, avr->state == cpu_Stopped);
 
-       if (avr->state == cpu_Stopped) {
-               usleep(500);
+       if (avr->state == cpu_Stopped)
                return avr->state;
-       }
 
+       // if we are stepping one insruction, we "run" for one..
        int step = avr->state == cpu_Step;
        if (step) {
                avr->state = cpu_Running;
@@ -137,7 +147,7 @@ int avr_run(avr_t * avr)
        avr_io_t * port = avr->io_port;
        while (port) {
                if (port->run)
-                       port->run(avr, port);
+                       port->run(port);
                port = port->next;
        }
 
@@ -148,7 +158,11 @@ int avr_run(avr_t * avr)
                        printf("simavr: sleeping with interrupts off, quitting gracefuly\n");
                        exit(0);
                }
-               usleep(500);
+               if (avr->gdb) {
+                       while (avr_gdb_processor(avr, 1))
+                               ;
+               } else
+                       usleep(500);
                long sleep = (float)avr->frequency * (1.0f / 500.0f);
                avr->cycle += sleep;
        //      avr->state = cpu_Running;
index fe7f36dcd4e433efc5cbab62c3bec12d2d6145c7..0af48364de0a035ce6c488ac4adafed110d4cf60 100644 (file)
@@ -155,8 +155,12 @@ typedef struct avr_t {
        // reset before each new instructions. Allows meaningful traces
        uint32_t        touched[256 / 32];      // debug
 
-       // placeholder
+       // 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
+       int             gdb_port;
 } avr_t;
 
 
@@ -193,6 +197,9 @@ void avr_loadcode(avr_t * avr, uint8_t * code, uint32_t size, uint32_t address);
 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);
 
 #include "sim_io.h"
 #include "sim_regbit.h"
index bdc16261efedc51f05f1cd82df5f5737573ef682..e5e2a96e4486812b50c274aa29ebe3fd76149f61 100644 (file)
@@ -76,7 +76,7 @@ void avr_dump_state(avr_t * avr);
                }\
                printf("Stack Ptr %04x/%04x = %d \n", _avr_sp_get(avr), avr->ramend, avr->ramend - _avr_sp_get(avr));\
                DUMP_STACK();\
-               exit(1);\
+               avr_sadly_crashed(avr, 0);\
        }
 
 #endif /* SIM_CORE_H_ */
index 02aaa93ff8f244d468d351fd36d6253f1ec5b133..8cdb12aca4bccb41f48a6219d645ed9da55809e4 100644 (file)
 #include <gelf.h>
 
 #include "sim_elf.h"
+#include "avr_eeprom.h"
+
+void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
+{
+       avr->frequency = firmware->mmcu.f_cpu;
+       avr->codeline = firmware->codeline;
+       avr_loadcode(avr, firmware->flash, firmware->flashsize, 0);
+       avr->codeend = firmware->flashsize - firmware->datasize;
+       if (firmware->eeprom && firmware->eesize) {
+               avr_eeprom_desc_t d = { .ee = firmware->eeprom, .offset = 0, .size = firmware->eesize };
+               avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
+       }
+}
 
 int elf_read_firmware(const char * file, elf_firmware_t * firmware)
 {
@@ -89,7 +102,7 @@ int elf_read_firmware(const char * file, elf_firmware_t * firmware)
                } else if (!strcmp(name, ".mmcu")) {
                        Elf_Data *s = elf_getdata(scn, NULL);
                        firmware->mmcu = *((struct avr_mcu_t*)s->d_buf);
-                       printf("%s: avr_mcu_t size %ld / read %ld\n", __FUNCTION__, sizeof(struct avr_mcu_t), s->d_size);
+                       //printf("%s: avr_mcu_t size %ld / read %ld\n", __FUNCTION__, sizeof(struct avr_mcu_t), s->d_size);
                //      avr->frequency = f_cpu;
                }
 #if ELF_SYMBOLS
index aa6bc77ab9e11334638ac111ab98fd646a38b432..bc616138ad66aa6f3a2fbf662e69840f2a795c2b 100644 (file)
@@ -28,9 +28,7 @@
 #define ELF_SYMBOLS 1
 #endif
 
-#if ELF_SYMBOLS
 #include "sim_avr.h"
-#endif
 
 typedef struct elf_firmware_t {
        struct avr_mcu_t mmcu;
@@ -50,4 +48,6 @@ typedef struct elf_firmware_t {
 
 int elf_read_firmware(const char * file, elf_firmware_t * firmware);
 
+void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware);
+
 #endif /* ELF_H_ */
index eac0d20d588e90814492930c37a669f753f67537..751f511d302e36154baa6c085a0e018ee19f6589 100644 (file)
 #include "sim_avr.h"
 #include "avr_eeprom.h"
 
+#define DBG(w)
+
 typedef struct avr_gdb_t {
        avr_t * avr;
        int             listen; // listen socket
        int             s;              // current gdb connection
-       
-       pthread_t thread;
-
-       uint32_t        query_len;
-       char            query[1024];
 
        uint32_t        watchmap;
        struct {
@@ -91,7 +88,7 @@ static void gdb_send_reply(avr_gdb_t * g, char * cmd)
                *dst++ = *cmd++;
        }
        sprintf((char*)dst, "#%02x", check);
-       printf("%s '%s'\n", __FUNCTION__, reply);
+       DBG(printf("%s '%s'\n", __FUNCTION__, reply);)
        send(g->s, reply, dst - reply + 3, 0);
 }
 
@@ -100,7 +97,7 @@ static void gdb_send_quick_status(avr_gdb_t * g, uint8_t signal)
        char cmd[64];
 
        sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;",
-               signal, g->avr->data[R_SREG], 
+               signal ? signal : 5, g->avr->data[R_SREG], 
                g->avr->data[R_SPL], g->avr->data[R_SPH],
                g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
        gdb_send_reply(g, cmd);
@@ -108,7 +105,7 @@ static void gdb_send_quick_status(avr_gdb_t * g, uint8_t signal)
 
 static int gdb_change_breakpoint(avr_gdb_t * g, int set, int kind, uint32_t addr, uint32_t len)
 {
-       printf("set %d kind %d addr %08x len %d (map %08x)\n", set, kind, addr, len, g->watchmap);
+       DBG(printf("set %d kind %d addr %08x len %d (map %08x)\n", set, kind, addr, len, g->watchmap);)
        if (set) {
                if (g->watchmap == 0xffffffff)
                        return -1;      // map full
@@ -140,46 +137,95 @@ static int gdb_change_breakpoint(avr_gdb_t * g, int set, int kind, uint32_t addr
        return -1;
 }
 
-static void gdb_handle_command(avr_gdb_t * g)
+static int gdb_write_register(avr_gdb_t * g, int regi, uint8_t * src)
+{
+       switch (regi) {
+               case 0 ... 31:
+                       g->avr->data[regi] = *src;
+                       return 1;
+               case 32:
+                       g->avr->data[R_SREG] = * src;
+                       return 1;
+               case 33:
+                       g->avr->data[R_SPL] = *src++;
+                       g->avr->data[R_SPH] = *src++;
+                       return 2;
+               case 34:
+                       g->avr->pc = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+                       return 4;
+       }
+       return 1;
+}
+
+static int gdb_read_register(avr_gdb_t * g, int regi, char * rep)
+{
+       switch (regi) {
+               case 0 ... 31:
+                       sprintf(rep, "%02x", g->avr->data[regi]);
+                       break;
+               case 32:
+                       sprintf(rep, "%02x", g->avr->data[R_SREG]);
+                       break;
+               case 33:
+                       sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]);
+                       break;
+               case 34:
+                       sprintf(rep, "%02x%02x%02x00", 
+                               g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
+                       break;
+       }
+       return strlen(rep);
+}
+
+static void gdb_handle_command(avr_gdb_t * g, char * cmd)
 {
        avr_t * avr = g->avr;
-       char * cmd = g->query;
        char rep[1024];
        uint8_t command = *cmd++;
        switch (command) {
                case '?':
-                       gdb_send_reply(g, "S00");
+                       gdb_send_quick_status(g, 0);
                        break;
-               case 'p': {
+               case 'G': {     // set all general purpose registers
+                       // get their binary form
+                       read_hex_string(cmd, (uint8_t*)rep, strlen(cmd));
+                       uint8_t *src = (uint8_t*)rep;
+                       for (int i = 0; i < 35; i++)
+                               src += gdb_write_register(g, i, src);
+                       gdb_send_reply(g, "OK");                                                                                
+               }       break;
+               case 'g': {     // read all general purpose registers
+                       char * dst = rep;
+                       for (int i = 0; i < 35; i++)
+                               dst += gdb_read_register(g, i, dst);
+                       gdb_send_reply(g, rep);                                         
+               }       break;
+               case 'p': {     // read register
                        unsigned int regi = 0;
                        sscanf(cmd, "%x", &regi);
-                       switch (regi) {
-                               case 0 ... 31:
-                                       sprintf(rep, "%02x", g->avr->data[regi]);
-                                       break;
-                               case 32:
-                                       sprintf(rep, "%02x", g->avr->data[R_SREG]);
-                                       break;
-                               case 33:
-                                       sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]);
-                                       break;
-                               case 34:
-                                       sprintf(rep, "%02x%02x%02x00", 
-                                               g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
-                                       break;
-                       }
+                       gdb_read_register(g, regi, rep);
                        gdb_send_reply(g, rep);                 
                }       break;
-               case 'm': {
+               case 'P': {     // write register
+                       unsigned int regi = 0;
+                       char * val = strchr(cmd, '=');
+                       if (!val)
+                               break;
+                       *val++ = 0;
+                       sscanf(cmd, "%x", &regi);
+                       read_hex_string(val, (uint8_t*)rep, strlen(val));
+                       gdb_write_register(g, regi, (uint8_t*)rep);
+                       gdb_send_reply(g, "OK");                                                                                
+               }       break;
+               case 'm': {     // read memory
                        uint32_t addr, len;
                        sscanf(cmd, "%x,%x", &addr, &len);
-                       printf("read memory %08x, %08x\n", addr, len);
                        uint8_t * src = NULL;
                        if (addr < 0xffff) {
                                src = avr->flash + addr;
                        } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
                                src = avr->data + addr - 0x800000;
-                       } else if (addr >= 0x810000 && (addr - 0x810000) <= (16*1024)) {
+                       } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) {
                                avr_eeprom_desc_t ee = {.offset = (addr - 0x810000)};
                                avr_ioctl(avr, AVR_IOCTL_EEPROM_GET, &ee);
                                if (ee.ee)
@@ -187,6 +233,7 @@ static void gdb_handle_command(avr_gdb_t * g)
                                else
                                        gdb_send_reply(g, "E01");
                        } else {
+                               printf("read memory error %08x, %08x (ramend %04x)\n", addr, len, avr->ramend+1);
                                gdb_send_reply(g, "E01");
                                break;
                        }
@@ -198,10 +245,9 @@ static void gdb_handle_command(avr_gdb_t * g)
                        *dst = 0;
                        gdb_send_reply(g, rep);
                }       break;
-               case 'M': {
+               case 'M': {     // write memory
                        uint32_t addr, len;
                        sscanf(cmd, "%x,%x", &addr, &len);
-                       printf("write memory %08x, %08x\n", addr, len);
                        char * start = strchr(cmd, ':');
                        if (!start) {
                                gdb_send_reply(g, "E01");
@@ -213,20 +259,27 @@ static void gdb_handle_command(avr_gdb_t * g)
                        } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
                                read_hex_string(start + 1, avr->data + addr - 0x800000, strlen(start+1));
                                gdb_send_reply(g, "OK");                                                        
-                       } else
-                               gdb_send_reply(g, "E01");                       
+                       } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) {
+                               read_hex_string(start + 1, (uint8_t*)rep, strlen(start+1));
+                               avr_eeprom_desc_t ee = {.offset = (addr - 0x810000), .size = len, .ee = (uint8_t*)rep };
+                               avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &ee);
+                               gdb_send_reply(g, "OK");                                                        
+                       } else {
+                               printf("write memory error %08x, %08x\n", addr, len);
+                               gdb_send_reply(g, "E01");
+                       }               
                }       break;
-               case 'c': {
+               case 'c': {     // continue
                        avr->state = cpu_Running;
                }       break;
-               case 's': {
+               case 's': {     // step
                        avr->state = cpu_Step;
                }       break;
-               case 'Z': 
+               case 'Z':       // set clear break/watchpoint
                case 'z': {
                        uint32_t kind, addr, len;
                        sscanf(cmd, "%d,%x,%x", &kind, &addr, &len);
-                       printf("breakbpoint %d, %08x, %08x\n", kind, addr, len);
+//                     printf("breakbpoint %d, %08x, %08x\n", kind, addr, len);
                        switch (kind) {
                                case 0: // software breakpoint
                                case 1: // hardware breakpoint
@@ -238,6 +291,7 @@ static void gdb_handle_command(avr_gdb_t * g)
                                        } else
                                                gdb_send_reply(g, "E01");               // out of flash address
                                        break;
+                               // TODO
                                case 2: // write watchpoint
                                case 3: // read watchpoint
                                case 4: // access watchpoint
@@ -250,16 +304,97 @@ static void gdb_handle_command(avr_gdb_t * g)
        }
 }
 
-void avr_gdb_processor(avr_t * avr)
+static int gdb_network_handler(avr_gdb_t * g, int dosleep)
+{
+       fd_set read_set;
+       int max;
+       FD_ZERO(&read_set);
+
+       if (g->s != -1) {
+               FD_SET(g->s, &read_set);
+               max = g->s + 1;
+       } else {
+               FD_SET(g->listen, &read_set);
+               max = g->listen + 1;
+       }
+       struct timeval timo = { 0, dosleep ? 500 : 0 }; // short, but not too short interval
+       int ret = select(max, &read_set, NULL, NULL, &timo);
+
+       if (ret == 0)
+               return 0;
+       
+       if (FD_ISSET(g->listen, &read_set)) {
+               g->s = accept(g->listen, NULL, NULL);
+
+               if (g->s == -1) {
+                       perror("gdb_network_handler accept");
+                       sleep(5);
+                       return 1;
+               }
+        int i = 1;
+        setsockopt (g->s, IPPROTO_TCP, TCP_NODELAY, &i, sizeof (i));
+               g->avr->state = cpu_Stopped;
+               printf("%s connection opened\n", __FUNCTION__);         
+       }
+               
+       if (FD_ISSET(g->s, &read_set)) {
+               uint8_t buffer[1024];
+               
+               ssize_t r = recv(g->s, buffer, sizeof(buffer)-1, 0);
+
+               if (r == 0) {
+                       printf("%s connection closed\n", __FUNCTION__);
+                       close(g->s);
+                       g->watchmap = 0;                                // clear breakpoints
+                       g->avr->state = cpu_Running;    // resume
+                       g->s = -1;
+                       return 1;
+               }
+               if (r == -1) {
+                       perror("gdb_network_handler recv");
+                       sleep(1);
+                       return 1;
+               }
+               buffer[r] = 0;
+       //      printf("%s: received %d bytes\n'%s'\n", __FUNCTION__, r, buffer);
+       //      hdump("gdb", buffer, r);
+
+               uint8_t * src = buffer;
+               while (*src == '+' || *src == '-')
+                       src++;
+               // control C -- lets send the guy a nice status packet
+               if (*src == 3) {
+                       src++;
+                       g->avr->state = cpu_StepDone;
+                       printf("GDB hit control-c\n");
+               }
+               if (*src  == '$') {
+                       // strip checksum
+                       uint8_t * end = buffer + r - 1;
+                       while (end > src && *end != '#')
+                               *end-- = 0;
+                       *end = 0;
+                       src++;
+                       DBG(printf("GDB command = '%s'\n", src);)
+
+                       send(g->s, "+", 1, 0);
+
+                       gdb_handle_command(g, (char*)src);
+               }
+       }
+       return 1;
+}
+
+int avr_gdb_processor(avr_t * avr, int sleep)
 {
        if (!avr || !avr->gdb)
-               return; 
+               return 0;       
        avr_gdb_t * g = avr->gdb;
 
        if (g->watchmap && avr->state == cpu_Running) {
                for (int i = 0; i < 32; i++)
                        if ((g->watchmap & (1 << i)) && g->watch[i].pc == avr->pc) {
-                               printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);
+                               DBG(printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);)
                                gdb_send_quick_status(g, 0);
                                avr->state = cpu_Stopped;
                        }               
@@ -268,94 +403,8 @@ void avr_gdb_processor(avr_t * avr)
                gdb_send_quick_status(g, 0);
                avr->state = cpu_Stopped;
        }
-       if (avr->gdb->query_len) {
-               g->query_len = 0;
-       
-       //      printf("avr_gdb_handle_query got a query '%s'\n", g->query);
-               gdb_handle_command(g);
-       }
-}
-
-
-static void * gdb_network_handler(void * param)
-{
-       avr_gdb_t * g = (avr_gdb_t*)param;
-
-       do {
-               if (listen(g->listen, 1)) {
-                       perror("gdb_network_handler listen");
-                       sleep(5);
-                       continue;
-               }
-               
-               struct sockaddr_in address = { 0 };
-               socklen_t ad_len = sizeof(address);
-
-               g->s = accept(g->listen, (struct sockaddr*)&address, &ad_len);
-
-               if (g->s == -1) {
-                       perror("gdb_network_handler accept");
-                       sleep(5);
-                       continue;
-               }
-               // should make that thread safe... 
-               g->avr->state = cpu_Stopped;
-               
-               do {
-                       fd_set read_set;
-                       FD_ZERO(&read_set);
-                       FD_SET(g->s, &read_set);
-
-                       struct timeval timo = { 1, 0000 };      // short, but not too short interval
-                       /*int ret =*/ select(g->s + 1, &read_set, NULL, NULL, &timo);
-
-                       if (FD_ISSET(g->s, &read_set)) {
-                               uint8_t buffer[1024];
-                               
-                               ssize_t r = recv(g->s, buffer, sizeof(buffer)-1, 0);
-
-                               if (r == 0) {
-                                       printf("%s connection closed\n", __FUNCTION__);
-                                       break;
-                               }
-                               if (r == -1) {
-                                       perror("gdb_network_handler recv");
-                                       break;
-                               }
-                               buffer[r] = 0;
-                       //      printf("%s: received %d bytes\n'%s'\n", __FUNCTION__, r, buffer);
-                       //      hdump("gdb", buffer, r);
-
-                               uint8_t * src = buffer;
-                               while (*src == '+' || *src == '-')
-                                       src++;
-                               if (*src == 3) {
-                                       src++;
-                                       g->query[0] = 3;
-                                       g->query_len = 1; // pass it on ?
-                               }
-                               if (*src  == '$') {
-                                       // strip checksum
-                                       uint8_t * end = buffer + r - 1;
-                                       while (end > src && *end != '#')
-                                               *end-- = 0;
-                                       *end = 0;
-                                       src++;
-                                       printf("GDB command = '%s'\n", src);
-
-                                       send(g->s, "+", 1, 0);
-
-                                       strcpy(g->query, (char*)src);
-                                       g->query_len = strlen((char*)src);
-                               }
-                       }
-               } while(1);
-               
-               close(g->s);
-                       
-       } while(1);
-       
-       return NULL;
+       // this also sleeps for a bit
+       return gdb_network_handler(g, sleep);
 }
 
 
@@ -376,17 +425,20 @@ int avr_gdb_init(avr_t * avr)
 
        struct sockaddr_in address = { 0 };
        address.sin_family = AF_INET;
-       address.sin_port = htons (1234);
+       address.sin_port = htons (avr->gdb_port);
 
        if (bind(g->listen, (struct sockaddr *) &address, sizeof(address))) {
                fprintf(stderr, "Can not bind socket: %s", strerror(errno));
                return -1;
        }
-       printf("avr_gdb_init listening on port %d\n", 1234);
+       if (listen(g->listen, 1)) {
+               perror("listen");
+               return -1;
+       }
+       printf("avr_gdb_init listening on port %d\n", avr->gdb_port);
        g->avr = avr;
+       g->s = -1;
        avr->gdb = g;
-
-       pthread_create(&g->thread, NULL, gdb_network_handler, g);
-
+       
        return 0;
 }
index cbd4ed1e15afbb5dff9d25a23b25d4ed5a83c5ab..548c59c9eaafcaad16a8066b8d500bc4d4a97da7 100644 (file)
@@ -25,6 +25,6 @@
 int avr_gdb_init(avr_t * avr);
 
 // call from the main AVR decoder thread
-void avr_gdb_processor(avr_t * avr);
+int avr_gdb_processor(avr_t * avr, int sleep);
 
 #endif
index 545123e20ea1c736e3ff7fd7d29d3ab90d53876d..bf620bbd01a0fb66116eaa1866551f0eaf7f2111 100644 (file)
@@ -76,7 +76,7 @@ void avr_clear_interrupt(avr_t * avr, int v)
        avr->pending[v >> 5] &= ~(1 << (v & 0x1f));
        if (!vector)
                return;
-       printf("%s cleared %d\n", __FUNCTION__, vector->vector);
+//     printf("%s cleared %d\n", __FUNCTION__, vector->vector);
        if (vector->raised.reg)
                avr_regbit_clear(avr, vector->raised);
 }
index d2bf62ee9007a79625dee84f8f5625909b5b464a..4f5dcb6c79fead031e3ccd34dde82dda45b2334f 100644 (file)
@@ -31,7 +31,7 @@ int avr_ioctl(avr_t *avr, uint32_t ctl, void * io_param)
        int res = -1;
        while (port && res == -1) {
                if (port->ioctl)
-                       res = port->ioctl(avr, port, ctl, io_param);
+                       res = port->ioctl(port, ctl, io_param);
                port = port->next;
        }
        return res;
@@ -40,6 +40,7 @@ int avr_ioctl(avr_t *avr, uint32_t ctl, void * io_param)
 void avr_register_io(avr_t *avr, avr_io_t * io)
 {
        io->next = avr->io_port;
+       io->avr = avr;
        avr->io_port = io;
 }
 
index 87eb5b9ddeda961be6e97fa27f828ffb94be7567..330a9dea56917bfeac1f71fd4d8f8bcdd90cd7e3 100644 (file)
  * Modules uses that as their first member in their own struct
  */
 typedef struct avr_io_t {
-       struct avr_io_t * next;
+       struct avr_io_t *       next;
+       avr_t *                         avr;            // avr we are attached to
        const char *            kind;           // pretty name, for debug
 
        uint32_t                        irq_ioctl_get;  // used to get irqs from this module
        int                                     irq_count;      // number of (optional) irqs
        struct avr_irq_t *      irq;            // optional external IRQs
        // called at every instruction
-       void (*run)(avr_t * avr, struct avr_io_t *io);
+       void (*run)(struct avr_io_t *io);
        // called at reset time
-       void (*reset)(avr_t * avr, struct avr_io_t *io);
+       void (*reset)(struct avr_io_t *io);
        // called externally. allow access to io modules and so on
-       int (*ioctl)(avr_t * avr, struct avr_io_t *io, uint32_t ctl, void *io_param);
+       int (*ioctl)(struct avr_io_t *io, uint32_t ctl, void *io_param);
 } avr_io_t;
 
 /*
index b5db20e98ae0a7384c75b8bd4d3a976f1cffcbe1..5daa8241fbb38f13b50229b4fcfd3203d7796088 100644 (file)
@@ -25,7 +25,7 @@
 #include "sim_irq.h"
 
 
-void avr_init_irq(avr_t * avr, avr_irq_t * irq, uint32_t base, uint32_t count)
+void avr_init_irq(avr_irq_t * irq, uint32_t base, uint32_t count)
 {
        memset(irq, 0, sizeof(avr_irq_t) * count);
 
@@ -33,14 +33,14 @@ void avr_init_irq(avr_t * avr, avr_irq_t * irq, uint32_t base, uint32_t count)
                irq[i].irq = base + i;
 }
 
-avr_irq_t * avr_alloc_irq(avr_t * avr, uint32_t base, uint32_t count)
+avr_irq_t * avr_alloc_irq(uint32_t base, uint32_t count)
 {
        avr_irq_t * irq = (avr_irq_t*)malloc(sizeof(avr_irq_t) * count);
-       avr_init_irq(avr, irq, base, count);
+       avr_init_irq(irq, base, count);
        return irq;
 }
 
-void avr_irq_register_notify(avr_t * avr, avr_irq_t * irq, avr_irq_notify_t notify, void * param)
+void avr_irq_register_notify(avr_irq_t * irq, avr_irq_notify_t notify, void * param)
 {
        if (!irq || !notify)
                return;
@@ -59,16 +59,17 @@ void avr_irq_register_notify(avr_t * avr, avr_irq_t * irq, avr_irq_notify_t noti
        irq->hook = hook;
 }
 
-void avr_raise_irq(avr_t * avr, avr_irq_t * irq, uint32_t value)
+void avr_raise_irq(avr_irq_t * irq, uint32_t value)
 {
        if (!irq || irq->value == value)
                return ;
        avr_irq_hook_t *hook = irq->hook;
        while (hook) {
-               if (hook->notify) {
+               if (hook->notify) {     
+                       // prevents reentrance / endless calling loops
                        if (hook->busy == 0) {
                                hook->busy++;
-                               hook->notify(avr, irq, value, hook->param);
+                               hook->notify(irq, value, hook->param);
                                hook->busy--;
                        }
                }
@@ -77,13 +78,13 @@ void avr_raise_irq(avr_t * avr, avr_irq_t * irq, uint32_t value)
        irq->value = value;
 }
 
-static void _avr_irq_connect(avr_t * avr, avr_irq_t * irq, uint32_t value, void * param)
+static void _avr_irq_connect(avr_irq_t * irq, uint32_t value, void * param)
 {
        avr_irq_t * dst = (avr_irq_t*)param;
-       avr_raise_irq(avr, dst, value);
+       avr_raise_irq(dst, value);
 }
 
-void avr_connect_irq(avr_t * avr, avr_irq_t * src, avr_irq_t * dst)
+void avr_connect_irq(avr_irq_t * src, avr_irq_t * dst)
 {
-       avr_irq_register_notify(avr, src, _avr_irq_connect, dst);
+       avr_irq_register_notify(src, _avr_irq_connect, dst);
 }
index 161c3110357d38111c9a448da6281d820acef7d1..c6782149766fefca21ecf462a3995d0c771507de 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef __SIM_IRQ_H__
 #define __SIM_IRQ_H__
 
-#include "sim_avr.h"
+#include <stdint.h>
 
 /*
  * Internal IRQ system
@@ -42,7 +42,7 @@
 // internal structure for a hook, never seen by the notify procs
 struct avr_irq_t;
 
-typedef void (*avr_irq_notify_t)(avr_t * avr, struct avr_irq_t * irq, uint32_t value, void * param);
+typedef void (*avr_irq_notify_t)(struct avr_irq_t * irq, uint32_t value, void * param);
 
 typedef struct avr_irq_hook_t {
        struct avr_irq_hook_t * next;
@@ -57,11 +57,11 @@ typedef struct avr_irq_t {
        avr_irq_hook_t *        hook;
 } avr_irq_t;
 
-avr_irq_t * avr_alloc_irq(avr_t * avr, uint32_t base, uint32_t count);
-void avr_init_irq(avr_t * avr, avr_irq_t * irq, uint32_t base, uint32_t count);
-void avr_raise_irq(avr_t * avr, avr_irq_t * irq, uint32_t value);
+avr_irq_t * avr_alloc_irq(uint32_t base, uint32_t count);
+void avr_init_irq(avr_irq_t * irq, uint32_t base, uint32_t count);
+void avr_raise_irq(avr_irq_t * irq, uint32_t value);
 // this connects a "source" IRQ to a "destination" IRQ
-void avr_connect_irq(avr_t * avr, avr_irq_t * src, avr_irq_t * dst);
-void avr_irq_register_notify(avr_t * avr, avr_irq_t * irq, avr_irq_notify_t notify, void * param);
+void avr_connect_irq(avr_irq_t * src, avr_irq_t * dst);
+void avr_irq_register_notify(avr_irq_t * irq, avr_irq_notify_t notify, void * param);
 
 #endif /* __SIM_IRQ_H__ */
index 1de514e3a029c60e598ac8134133ef37d52bb825..e75a12f17601e53585b58ce4ea82341edaf67ac7 100644 (file)
@@ -39,25 +39,7 @@ sources              := $(wildcard at*.c)
 
 all :  ${sources:.c=.axf} ${sources:.c=.hex}  ${sources:.c=.s}  
 
-%.hex: %.axf
-               @${AVR}objcopy -j .text -j .data -O ihex ${<} ${@}
-
-%.s: %.axf
-               @${AVR}objdump -j .text -j .data -j .bss -d  ${<} > ${@}
-
-%.axf: %.c 
-               @echo CC ${<}
-               @part=${<} ; part=$${part/_*}; \
-               ${AVR}gcc -Wall -g -Os -std=gnu99 \
-                               -mmcu=$$part \
-                               -DF_CPU=8000000 \
-                               -mcall-prologues -fno-inline-small-functions \
-                               -ffunction-sections -fdata-sections \
-                               -Wl,--relax,--gc-sections \
-                               -Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000 \
-                               -I../include \
-                               ${<} -o ${@}
-               @${AVR}size ${@}|sed '1d'
+include ../Makefile.common
 
 clean:
        rm -f *.hex *.o *.axf *.s
diff --git a/tests/attiny85_crash_gdb.c b/tests/attiny85_crash_gdb.c
new file mode 100644 (file)
index 0000000..cfa5bb8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * attiny85_crash_gdb.c
+ *
+ *  Created on: 1 Dec 2009
+ *      Author: jone
+ */
+
+#include <avr/sleep.h>
+#include "avr_mcu_section.h"
+
+AVR_MCU(F_CPU, "attiny85");
+
+int value = 0;
+
+int main()
+{
+
+       /*
+        * this is not much, but that crashed the core, and should activate
+        * the gdb server properly, so you can see it stopped, here
+        */
+       value++;
+
+       *((uint8_t*)0xdead) = 0x55;
+
+       // should never reach here !
+       value++;
+       sleep_mode();
+}