From fc61d39288c2aedc84307d903f377def283cebd6 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Sun, 3 Nov 2019 18:31:30 +0100 Subject: [PATCH] Do not use IRQs and remove vector table Do not use ISRs and poll for interrupt flags in the main loop. No need for moving vector table into bootloader and back. Remove vector table by adding LDFLAGS = -nostartfiles. Manually add some code which is now removed, but still needed by C runtime: - make sure that r1 is 0x00 (zero register). - on some MCUs the stack pointer is not initialized correctly after reset. - main() need to be placed in special section .init9 to be called at all. Not sure why the BSS and DATA segment are still initialized. This change is heavily based on the optiboot bootloader. --- Makefile | 1 + README.md | 13 +++++----- main.c | 77 +++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 667a8a8..3613287 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,7 @@ endif CFLAGS = -pipe -g -Os -mmcu=$(MCU) -Wall -fdata-sections -ffunction-sections CFLAGS += -Wa,-adhlns=$(*F).lst -DBOOTLOADER_START=$(BOOTLOADER_START) LDFLAGS = -Wl,-Map,$(@:.elf=.map),--cref,--relax,--gc-sections,--section-start=.text=$(BOOTLOADER_START) +LDFLAGS += -nostartfiles # --------------------------------------------------------------------------- diff --git a/README.md b/README.md index 16a870a..ba09435 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ Currently the following AVR MCUs are supported: AVR MCU | Flash bytes used (.text + .data) | Bootloader region size --- | --- | --- -atmega8 | 872 (0x368) | 512 words -atmega88 | 918 (0x396) | 512 words -atmega168 | 970 (0x3CA) | 512 words -atmega328p | 970 (0x3CA) | 512 words +atmega8 | 724 (0x2D4) | 512 words +atmega88 | 744 (0x2E8) | 512 words +atmega168 | 744 (0x2E8) | 512 words +atmega328p | 744 (0x2E8) | 512 words (Compiled on Ubuntu 18.04 LTS (gcc 5.4.0 / avr-libc 2.0.0) with EEPROM and LED support) @@ -91,6 +91,5 @@ Issue reports, feature requests, patches or simply success stories are much appr ## Roadmap ## Some ideas that I want to investigate / implement in twiboot: -- [ ] do not use interrupts and remove vector table to save flash space -- [ ] find a way to not rely on TWI clock stretching during write access -- [ ] support AVR TINYs (USI peripheral, no bootloader fuse, no Read-While-Write flash) +- find a way to not rely on TWI clock stretching during write access +- support AVR TINYs (USI peripheral, no bootloader fuse, no Read-While-Write flash) diff --git a/main.c b/main.c index 8ee42ed..aff73ef 100644 --- a/main.c +++ b/main.c @@ -132,7 +132,7 @@ const static uint8_t chipinfo[8] = { /* wait 40 * 25ms = 1s */ static uint8_t boot_timeout = TIMEOUT; -volatile static uint8_t cmd = CMD_WAIT; +static uint8_t cmd = CMD_WAIT; /* flash buffer */ static uint8_t buf[SPM_PAGESIZE]; @@ -355,7 +355,7 @@ static uint8_t TWI_data_read(uint8_t bcnt) /* ************************************************************************* * TWI_vect * ************************************************************************* */ -ISR(TWI_vect) +static void TWI_vect(void) { static uint8_t bcnt; uint8_t control = TWCR; @@ -410,7 +410,7 @@ ISR(TWI_vect) /* ************************************************************************* * TIMER0_OVF_vect * ************************************************************************* */ -ISR(TIMER0_OVF_vect) +static void TIMER0_OVF_vect(void) { /* restart timer */ TCNT0 = TIMER_RELOAD; @@ -433,6 +433,26 @@ ISR(TIMER0_OVF_vect) static void (*jump_to_app)(void) __attribute__ ((noreturn)) = 0x0000; + +/* ************************************************************************* + * init1 + * ************************************************************************* */ +void init1(void) __attribute__((naked, section(".init1"))); +void init1(void) +{ + /* make sure r1 is 0x00 */ + asm volatile ("clr __zero_reg__"); + + /* on some MCUs the stack pointer defaults NOT to RAMEND */ +#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8515__) || \ + defined(__AVR_ATmega8535__) || defined (__AVR_ATmega16__) || \ + defined (__AVR_ATmega32__) || defined (__AVR_ATmega64__) || \ + defined (__AVR_ATmega128__) || defined (__AVR_ATmega162__) + SP = RAMEND; +#endif +} /* init1 */ + + /* * For newer devices the watchdog timer remains active even after a * system reset. So disable it as soon as possible. @@ -456,55 +476,56 @@ void disable_wdt_timer(void) /* ************************************************************************* * main * ************************************************************************* */ -int main(void) __attribute__ ((noreturn)); +int main(void) __attribute__ ((OS_main, section (".init9"))); int main(void) { LED_INIT(); LED_GN_ON(); - /* move interrupt-vectors to bootloader */ - /* timer0: running with F_CPU/1024, OVF interrupt */ + /* timer0: running with F_CPU/1024 */ #if defined (__AVR_ATmega8__) - GICR = (1<