From acb73a9c606777a5be81ecbea043905c7e211b09 Mon Sep 17 00:00:00 2001 From: Erasmus Cedernaes Date: Tue, 12 Nov 2024 21:25:38 +0100 Subject: [PATCH 1/3] Move the interrupt table to the bootloader sector when IVSEL is set --- simavr/sim/sim_interrupts.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/simavr/sim/sim_interrupts.c b/simavr/sim/sim_interrupts.c index 9e3ed9c06..25b8d9b61 100644 --- a/simavr/sim/sim_interrupts.c +++ b/simavr/sim/sim_interrupts.c @@ -27,6 +27,7 @@ #include "sim_interrupts.h" #include "sim_avr.h" #include "sim_core.h" +#include "sim_core_declare.h" DEFINE_FIFO(avr_int_vector_p, avr_int_pending); @@ -281,7 +282,13 @@ avr_service_interrupts( printf("IRQ%d calling\n", vector->vector); _avr_push_addr(avr, avr->pc); avr_sreg_set(avr, S_I, 0); - avr->pc = vector->vector * avr->vector_size; + const int mcucr = _SFR_IO8(0x35); + const int ivsel = 1; + const char interrupt_sector_moved_to_bootloader = avr->data[mcucr] & (1 << ivsel); + if (interrupt_sector_moved_to_bootloader) + avr->pc = vector->vector * avr->vector_size + 0x7000; + else + avr->pc = vector->vector * avr->vector_size; avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 1); avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING, vector->vector); From f22aef3aa468e30af93635613842a9d5a7cf6e88 Mon Sep 17 00:00:00 2001 From: Erasmus Cedernaes Date: Fri, 15 Nov 2024 22:24:09 +0100 Subject: [PATCH 2/3] Break out into function --- simavr/sim/sim_interrupts.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/simavr/sim/sim_interrupts.c b/simavr/sim/sim_interrupts.c index 25b8d9b61..e8f707b72 100644 --- a/simavr/sim/sim_interrupts.c +++ b/simavr/sim/sim_interrupts.c @@ -227,6 +227,20 @@ avr_interrupt_reti( table->running[table->running_ptr-1]->vector : 0); } +static int interrupt_table_offset(avr_t *avr) +{ + const int mcucr = _SFR_IO8(0x35); + const int ivsel = 1; + const char interrupt_sector_moved_to_bootloader = avr->data[mcucr] & (1 << ivsel); + + const int bootloader_size = 0x800; + + if (interrupt_sector_moved_to_bootloader) + return avr->flashend - bootloader_size + 1; + + return 0; +} + /* * check whether interrupts are pending. If so, check if the interrupt "latency" is reached, * and if so triggers the handlers and jump to the vector. @@ -282,13 +296,7 @@ avr_service_interrupts( printf("IRQ%d calling\n", vector->vector); _avr_push_addr(avr, avr->pc); avr_sreg_set(avr, S_I, 0); - const int mcucr = _SFR_IO8(0x35); - const int ivsel = 1; - const char interrupt_sector_moved_to_bootloader = avr->data[mcucr] & (1 << ivsel); - if (interrupt_sector_moved_to_bootloader) - avr->pc = vector->vector * avr->vector_size + 0x7000; - else - avr->pc = vector->vector * avr->vector_size; + avr->pc = vector->vector * avr->vector_size + interrupt_table_offset(avr); avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 1); avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING, vector->vector); From b80b39fa59b80cb8a321ab247a34741a5115ee80 Mon Sep 17 00:00:00 2001 From: Erasmus Cedernaes Date: Fri, 15 Nov 2024 22:39:57 +0100 Subject: [PATCH 3/3] Calculate boot size for ATmega328 based on fuses --- simavr/sim/sim_interrupts.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/simavr/sim/sim_interrupts.c b/simavr/sim/sim_interrupts.c index e8f707b72..fe4188b36 100644 --- a/simavr/sim/sim_interrupts.c +++ b/simavr/sim/sim_interrupts.c @@ -227,16 +227,33 @@ avr_interrupt_reti( table->running[table->running_ptr-1]->vector : 0); } +static int bootloader_size_avr328(avr_t *avr) +{ + const char efuse = avr->fuse[2]; + const char bootsz = (efuse >> 1) & 0x3; + + switch (bootsz) + { + case 0: + return 256 * 2; + case 1: + return 512 * 2; + case 2: + return 1024 * 2; + default: + return 2048 * 2; + } +} + static int interrupt_table_offset(avr_t *avr) { const int mcucr = _SFR_IO8(0x35); const int ivsel = 1; const char interrupt_sector_moved_to_bootloader = avr->data[mcucr] & (1 << ivsel); - const int bootloader_size = 0x800; - + const int flash_size = avr->flashend + 1; if (interrupt_sector_moved_to_bootloader) - return avr->flashend - bootloader_size + 1; + return flash_size - bootloader_size_avr328(avr); return 0; }