From 02224cdc7724d27d04312127af0e249357319d12 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 15 Dec 2013 17:00:59 +0100 Subject: restructure, optimizations by shay #1 -> use register for events --- firmware/main.c | 55 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 24 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index a6af148..b4f57e7 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -16,7 +16,6 @@ // how many milliseconds should host wait till it sends another erase or write? // needs to be above 4.5 (and a whole integer) as avr freezes for 4.5ms #define MICRONUCLEUS_WRITE_SLEEP 8 - // Use the old delay routines without NOP padding. This saves memory. #define __DELAY_BACKWARD_COMPATIBLE__ @@ -26,7 +25,6 @@ #include #include -static void leaveBootloader() __attribute__((__noreturn__)); #include "bootloaderconfig.h" #include "usbdrv/usbdrv.c" @@ -50,7 +48,9 @@ static void leaveBootloader() __attribute__((__noreturn__)); #endif // events system schedules functions to run in the main loop -static uchar events = 0; // bitmap of events to run +// static uchar events = 0; // bitmap of events to run +register uint8_t events asm( "r1" ); // register saves many bytes + #define EVENT_ERASE_APPLICATION 1 #define EVENT_WRITE_PAGE 2 #define EVENT_EXECUTE 4 @@ -156,10 +156,7 @@ static void writeWordToPageBuffer(uint16_t data) { previous_sreg=SREG; cli(); // ensure interrupts are disabled - // clear page buffer as a precaution before filling the buffer on the first page - // in case the bootloader somehow ran after user program and there was something - // in the page buffer already - if (currentAddress == 0x0000) __boot_page_fill_clear(); + boot_page_fill(currentAddress, data); // increment progmem address by one word @@ -235,8 +232,33 @@ void PushMagicWord (void) { asm volatile("push r16"::); } +static void initHardware (void) +{ + MCUSR=0; /* need this to properly disable watchdog */ + wdt_disable(); + + #if LOW_POWER_MODE + // turn off clock prescalling - chip must run at full speed for usb + // if you might run chip at lower voltages, detect that in bootLoaderStartCondition + CLKPR = 1 << CLKPCE; + CLKPR = 0; + #endif + + // clear page buffer as a precaution before filling the buffer on the first page + // in case the bootloader somehow ran after user program and there was something + // in the page buffer already + __boot_page_fill_clear(); + + usbDeviceDisconnect(); /* do this while interrupts are disabled */ + _delay_ms(500); + usbDeviceConnect(); + usbInit(); // Initialize INT settings after reconnect + sei(); +} + /* ------------------------------------------------------------------------ */ // reset system to a normal state and launch user program +static void leaveBootloader(void) __attribute__((__noreturn__)); static inline void leaveBootloader(void) { _delay_ms(10); // removing delay causes USB errors @@ -280,26 +302,11 @@ int main(void) { if (bootLoaderStartCondition()) { - MCUSR=0; /* need this to properly disable watchdog */ - wdt_disable(); - - #if LOW_POWER_MODE - // turn off clock prescalling - chip must run at full speed for usb - // if you might run chip at lower voltages, detect that in bootLoaderStartCondition - CLKPR = 1 << CLKPCE; - CLKPR = 0; - #endif + initHardware(); # if LED_PRESENT LED_INIT(); -# endif - - usbDeviceDisconnect(); /* do this while interrupts are disabled */ - _delay_ms(500); - usbDeviceConnect(); - usbInit(); // Initialize INT settings after reconnect - sei(); - +# endif do { usbPoll(); _delay_us(100); -- cgit v1.2.3 From f6daa493d57a22caf58eb45aaebc978d5c2fa4f7 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 15 Dec 2013 17:03:46 +0100 Subject: C99 types --- firmware/main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index b4f57e7..401aaa8 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -48,7 +48,7 @@ #endif // events system schedules functions to run in the main loop -// static uchar events = 0; // bitmap of events to run +// static uint8_t events = 0; // bitmap of events to run register uint8_t events asm( "r1" ); // register saves many bytes #define EVENT_ERASE_APPLICATION 1 @@ -77,8 +77,8 @@ static uint16_t currentAddress; // current progmem address, used for erasing and static inline void eraseApplication(void); static void writeFlashPage(void); static void writeWordToPageBuffer(uint16_t data); -static uchar usbFunctionSetup(uchar data[8]); -static uchar usbFunctionWrite(uchar *data, uchar length); +static uint8_t usbFunctionSetup(uint8_t data[8]); +static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length); static inline void leaveBootloader(void); // erase any existing application and write in jumps for usb interrupt and reset to bootloader @@ -165,11 +165,11 @@ static void writeWordToPageBuffer(uint16_t data) { } /* ------------------------------------------------------------------------ */ -static uchar usbFunctionSetup(uchar data[8]) { +static uint8_t usbFunctionSetup(uint8_t data[8]) { usbRequest_t *rq = (void *)data; ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic - static uchar replyBuffer[4] = { + static uint8_t replyBuffer[4] = { (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff, ((uint16_t)PROGMEM_SIZE) & 0xff, SPM_PAGESIZE, @@ -197,7 +197,7 @@ static uchar usbFunctionSetup(uchar data[8]) { } // read in a page over usb, and write it in to the flash write buffer -static uchar usbFunctionWrite(uchar *data, uchar length) { +static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { do { // make sure we don't write over the bootloader! if (currentAddress >= BOOTLOADER_ADDRESS) break; @@ -210,9 +210,9 @@ static uchar usbFunctionWrite(uchar *data, uchar length) { // if we have now reached another page boundary, we're done #if SPM_PAGESIZE<256 // Hack to reduce code size - uchar isLast = ((((uchar)currentAddress) % SPM_PAGESIZE) == 0); + uint8_t isLast = ((((uint8_t)currentAddress) % SPM_PAGESIZE) == 0); #else - uchar isLast = ((currentAddress % SPM_PAGESIZE) == 0); + uint8_t isLast = ((currentAddress % SPM_PAGESIZE) == 0); #endif // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! -- cgit v1.2.3 From 7f1b5e11a801b4c6609870f79bbb93edab3292fd Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 15 Dec 2013 20:19:35 +0100 Subject: don't exit bootloader with clean memory --- firmware/main.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 401aaa8..3fca133 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -25,7 +25,6 @@ #include #include - #include "bootloaderconfig.h" #include "usbdrv/usbdrv.c" @@ -49,7 +48,7 @@ // events system schedules functions to run in the main loop // static uint8_t events = 0; // bitmap of events to run -register uint8_t events asm( "r1" ); // register saves many bytes +register uint8_t events asm( "r3" ); // register saves many bytes #define EVENT_ERASE_APPLICATION 1 #define EVENT_WRITE_PAGE 2 @@ -156,7 +155,6 @@ static void writeWordToPageBuffer(uint16_t data) { previous_sreg=SREG; cli(); // ensure interrupts are disabled - boot_page_fill(currentAddress, data); // increment progmem address by one word @@ -260,7 +258,7 @@ static void initHardware (void) // reset system to a normal state and launch user program static void leaveBootloader(void) __attribute__((__noreturn__)); static inline void leaveBootloader(void) { - _delay_ms(10); // removing delay causes USB errors + _delay_ms(10); // removing delay causes USB errors bootLoaderExit(); cli(); @@ -308,28 +306,27 @@ int main(void) { LED_INIT(); # endif do { + clearEvents(); usbPoll(); _delay_us(100); - - // these next two freeze the chip for ~ 4.5ms, breaking usb protocol - // and usually both of these will activate in the same loop, so host - // needs to wait > 9ms before next usb request - if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); - if (isEvent(EVENT_WRITE_PAGE)) { - _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- - writeFlashPage(); - } - -# if BOOTLOADER_CAN_EXIT - if (isEvent(EVENT_EXECUTE)) break; // when host requests device run uploaded program -# endif - clearEvents(); + + // these next two freeze the chip for ~ 4.5ms, breaking usb protocol + // and usually both of these will activate in the same loop, so host + // needs to wait > 9ms before next usb request + if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); + if (isEvent(EVENT_WRITE_PAGE)) { + _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- + writeFlashPage(); + } # if LED_PRESENT LED_MACRO( ((uint8_t*)&idlePolls)[1] ) # endif - - } while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */ + + // Only try to execute program if reset vector is set - bootloader will not time out with erased memory + if (!bootLoaderCondition()&&(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET)!=0xff)) fireEvent(EVENT_EXECUTE); + + } while(!isEvent(EVENT_EXECUTE)); /* main event loop runs as long as program is not executed */ } // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses) -- cgit v1.2.3 From f32bf1b6c6c5f157f981c111e2ccce2399e4c509 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Mon, 16 Dec 2013 09:34:40 +0100 Subject: firmware: fix condition for EXECUTE read high byte of user programm reset vector --- firmware/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 3fca133..04b0e33 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -324,7 +324,7 @@ int main(void) { # endif // Only try to execute program if reset vector is set - bootloader will not time out with erased memory - if (!bootLoaderCondition()&&(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET)!=0xff)) fireEvent(EVENT_EXECUTE); + if (!bootLoaderCondition()&&(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)!=0xff)) fireEvent(EVENT_EXECUTE); } while(!isEvent(EVENT_EXECUTE)); /* main event loop runs as long as program is not executed */ } -- cgit v1.2.3 From bda177784ad97bd3934bb2359621c5c5460805ef Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Mon, 16 Dec 2013 09:38:22 +0100 Subject: firmware: Clean buffer at begin of write improve robustness --- firmware/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 04b0e33..a7deccc 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -179,6 +179,10 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { return 4; } else if (rq->bRequest == 1) { // write page + + // clear page buffer as a precaution before filling the buffer in case + // a previous write operation failed and there is still something in the buffer. + __boot_page_fill_clear(); currentAddress = rq->wIndex.word; return USB_NO_MSG; // hands off work to usbFunctionWrite @@ -242,10 +246,6 @@ static void initHardware (void) CLKPR = 0; #endif - // clear page buffer as a precaution before filling the buffer on the first page - // in case the bootloader somehow ran after user program and there was something - // in the page buffer already - __boot_page_fill_clear(); usbDeviceDisconnect(); /* do this while interrupts are disabled */ _delay_ms(500); -- cgit v1.2.3 From bd22f84cfae23f84a2d2fee343b937794942b0f1 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Tue, 17 Dec 2013 19:49:02 +0100 Subject: firmware: bootloader will only exit when program was loaded --- firmware/main.c | 56 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index a7deccc..36a42be 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -284,20 +284,23 @@ static inline void leaveBootloader(void) { } int main(void) { - /* initialize */ - #if OSCCAL_RESTORE - osccal_default = OSCCAL; - #endif - #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE - uint8_t prescaler_default = CLKPR; - #endif + + /* initialize */ + #if OSCCAL_RESTORE + osccal_default = OSCCAL; + #endif + + #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE + uint8_t prescaler_default = CLKPR; + #endif - bootLoaderInit(); + bootLoaderInit(); -# if AUTO_EXIT_NO_USB_MS - ((uint8_t*)&idlePolls)[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; // write only high byte to save 6 bytes -# endif + #if AUTO_EXIT_NO_USB_MS + ((uint8_t*)&idlePolls)[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; // write only high byte to save 6 bytes + #endif + if (bootLoaderStartCondition()) { initHardware(); @@ -319,14 +322,15 @@ int main(void) { writeFlashPage(); } -# if LED_PRESENT - LED_MACRO( ((uint8_t*)&idlePolls)[1] ) -# endif + #if LED_PRESENT + LED_MACRO( ((uint8_t*)&idlePolls)[1] ) + #endif - // Only try to execute program if reset vector is set - bootloader will not time out with erased memory - if (!bootLoaderCondition()&&(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)!=0xff)) fireEvent(EVENT_EXECUTE); - - } while(!isEvent(EVENT_EXECUTE)); /* main event loop runs as long as program is not executed */ + // Try to execute program if bootloader exit condition is met + if (!bootLoaderCondition()) fireEvent(EVENT_EXECUTE); + + /* main event loop runs as long as no problem is uploaded or existing program is not executed */ + } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); } // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses) @@ -340,15 +344,15 @@ int main(void) { #endif #endif -# if LED_PRESENT - LED_EXIT(); -# endif + #if LED_PRESENT + LED_EXIT(); + #endif -# if OSCCAL_RESTORE - OSCCAL=osccal_default; - asm volatile("nop"); // NOP to avoid CPU hickup during oscillator stabilization -# endif + #if OSCCAL_RESTORE + OSCCAL=osccal_default; + asm volatile("nop"); // NOP to avoid CPU hickup during oscillator stabilization + #endif - leaveBootloader(); + leaveBootloader(); } /* ------------------------------------------------------------------------ */ -- cgit v1.2.3 From 181445ff3a2e28c980d3c6f8dd38578659db5664 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Fri, 27 Dec 2013 18:36:28 +0100 Subject: firmware: clean up nop --- firmware/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 36a42be..83c5538 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -60,8 +60,9 @@ register uint8_t events asm( "r3" ); // register saves many bytes #define clearEvents() events = 0 // Definition of sei and cli without memory barrier keyword to prevent reloading of memory variables -#define sei() __asm__ __volatile__ ("sei") -#define cli() __asm__ __volatile__ ("cli") +#define sei() asm volatile("sei") +#define cli() asm volatile("cli") +#define nop() asm volatile("nop") uint16_t idlePolls = 0; // how long have we been idle? @@ -276,7 +277,7 @@ static inline void leaveBootloader(void) { unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET); if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) { OSCCAL=stored_osc_calibration; - asm volatile("nop"); + nop(); } #endif // jump to application reset vector at end of flash @@ -350,7 +351,7 @@ int main(void) { #if OSCCAL_RESTORE OSCCAL=osccal_default; - asm volatile("nop"); // NOP to avoid CPU hickup during oscillator stabilization + nop(); // NOP to avoid CPU hickup during oscillator stabilization #endif leaveBootloader(); -- cgit v1.2.3 From 713142dceff2f12ebbb62f2196d8aed348504299 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 12:26:53 +0100 Subject: firmware: move increment idlePolls to main again --- firmware/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 83c5538..0723c3e 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -326,7 +326,8 @@ int main(void) { #if LED_PRESENT LED_MACRO( ((uint8_t*)&idlePolls)[1] ) #endif - + + idlePolls++; // Try to execute program if bootloader exit condition is met if (!bootLoaderCondition()) fireEvent(EVENT_EXECUTE); -- cgit v1.2.3 From 1a38f02b1117442b137a4a210ed250ab8fd3de21 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 12:46:06 +0100 Subject: firmware: clean up LED code --- firmware/main.c | 63 ++++++++++++++++++++++++++------------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 0723c3e..88753a8 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -300,40 +300,37 @@ int main(void) { #if AUTO_EXIT_NO_USB_MS ((uint8_t*)&idlePolls)[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; // write only high byte to save 6 bytes #endif - - if (bootLoaderStartCondition()) { +// if (bootLoaderStartCondition()||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)) { + if (bootLoaderStartCondition()) { + + initHardware(); + LED_INIT(); - initHardware(); - -# if LED_PRESENT - LED_INIT(); -# endif - do { - clearEvents(); - usbPoll(); - _delay_us(100); - - // these next two freeze the chip for ~ 4.5ms, breaking usb protocol - // and usually both of these will activate in the same loop, so host - // needs to wait > 9ms before next usb request - if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); - if (isEvent(EVENT_WRITE_PAGE)) { - _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- - writeFlashPage(); - } - - #if LED_PRESENT - LED_MACRO( ((uint8_t*)&idlePolls)[1] ) - #endif + do { + clearEvents(); + usbPoll(); - idlePolls++; - // Try to execute program if bootloader exit condition is met - if (!bootLoaderCondition()) fireEvent(EVENT_EXECUTE); - - /* main event loop runs as long as no problem is uploaded or existing program is not executed */ - } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); - } + _delay_us(100); + + // these next two freeze the chip for ~ 4.5ms, breaking usb protocol + // and usually both of these will activate in the same loop, so host + // needs to wait > 9ms before next usb request + if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); + if (isEvent(EVENT_WRITE_PAGE)) { + _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- + writeFlashPage(); + } + + LED_MACRO( ((uint8_t*)&idlePolls)[1] ) + + idlePolls++; + // Try to execute program if bootloader exit condition is met + if (AUTO_EXIT_MS&&(idlePolls>AUTO_EXIT_MS*10)) fireEvent(EVENT_EXECUTE); + + /* main event loop runs as long as no problem is uploaded or existing program is not executed */ + } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); + } // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses) #if LOW_POWER_MODE @@ -346,9 +343,7 @@ int main(void) { #endif #endif - #if LED_PRESENT - LED_EXIT(); - #endif + LED_EXIT(); #if OSCCAL_RESTORE OSCCAL=osccal_default; -- cgit v1.2.3 From c3de9534f78ff338031516e17f94c44480f25fed Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 13:54:18 +0100 Subject: firmware: clean up entrymode --- firmware/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 88753a8..0ab0682 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -301,8 +301,7 @@ int main(void) { ((uint8_t*)&idlePolls)[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; // write only high byte to save 6 bytes #endif -// if (bootLoaderStartCondition()||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)) { - if (bootLoaderStartCondition()) { + if (bootLoaderStartCondition()||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)) { initHardware(); LED_INIT(); @@ -322,9 +321,9 @@ int main(void) { writeFlashPage(); } - LED_MACRO( ((uint8_t*)&idlePolls)[1] ) - + LED_MACRO( ((uint8_t*)&idlePolls)[1] ); idlePolls++; + // Try to execute program if bootloader exit condition is met if (AUTO_EXIT_MS&&(idlePolls>AUTO_EXIT_MS*10)) fireEvent(EVENT_EXECUTE); -- cgit v1.2.3 From 2e10478426a6f0d04099bdb24fc17102a6abde1b Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 13:56:39 +0100 Subject: firmware: default is entry_always, kill warning --- firmware/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 0ab0682..bafb121 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -325,7 +325,7 @@ int main(void) { idlePolls++; // Try to execute program if bootloader exit condition is met - if (AUTO_EXIT_MS&&(idlePolls>AUTO_EXIT_MS*10)) fireEvent(EVENT_EXECUTE); + if (AUTO_EXIT_MS&&(idlePolls>AUTO_EXIT_MS*10L)) fireEvent(EVENT_EXECUTE); /* main event loop runs as long as no problem is uploaded or existing program is not executed */ } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); -- cgit v1.2.3 From 26b1c45b1145f9b96c4ec90e93a61a3da63e2473 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 14:09:54 +0100 Subject: firmware: removed low power code - was dysfunctional --- firmware/main.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index bafb121..48ac399 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -237,22 +237,15 @@ void PushMagicWord (void) { static void initHardware (void) { - MCUSR=0; /* need this to properly disable watchdog */ - wdt_disable(); - - #if LOW_POWER_MODE - // turn off clock prescalling - chip must run at full speed for usb - // if you might run chip at lower voltages, detect that in bootLoaderStartCondition - CLKPR = 1 << CLKPCE; - CLKPR = 0; - #endif + MCUSR=0; /* need this to properly disable watchdog */ + wdt_disable(); - - usbDeviceDisconnect(); /* do this while interrupts are disabled */ - _delay_ms(500); - usbDeviceConnect(); - usbInit(); // Initialize INT settings after reconnect - sei(); + usbDeviceDisconnect(); /* do this while interrupts are disabled */ + _delay_ms(500); + usbDeviceConnect(); + usbInit(); // Initialize INT settings after reconnect + + sei(); } /* ------------------------------------------------------------------------ */ @@ -290,11 +283,7 @@ int main(void) { #if OSCCAL_RESTORE osccal_default = OSCCAL; #endif - - #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE - uint8_t prescaler_default = CLKPR; - #endif - + bootLoaderInit(); #if AUTO_EXIT_NO_USB_MS @@ -331,17 +320,6 @@ int main(void) { } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); } - // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses) - #if LOW_POWER_MODE - #ifdef SET_CLOCK_PRESCALER - CLKPR = 1 << CLKPCE; - CLKPR = SET_CLOCK_PRESCALER; - #else - CLKPR = 1 << CLKPCE; - CLKPR = prescaler_default; - #endif - #endif - LED_EXIT(); #if OSCCAL_RESTORE -- cgit v1.2.3 From fefbff026f6ab8e3b5bc7d7a317a86c901057124 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 14:44:31 +0100 Subject: firmware: fix tabs --- firmware/main.c | 246 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 122 insertions(+), 124 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 48ac399..bec0305 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -70,7 +70,7 @@ static uint16_t vectorTemp[2]; // remember data to create tinyVector table befor static uint16_t currentAddress; // current progmem address, used for erasing and writing #if OSCCAL_RESTORE - static uint8_t osccal_default; // due to compiler insanity, having this as global actually saves memory + static uint8_t osccal_default; // due to compiler insanity, having this as global actually saves memory #endif /* ------------------------------------------------------------------------ */ @@ -86,142 +86,140 @@ static inline void leaveBootloader(void); // - vectors in now, and write in the application stuff around them later. // - if vectors weren't written back in immediately, usb would fail. static inline void eraseApplication(void) { - // erase all pages until bootloader, in reverse order (so our vectors stay in place for as long as possible) - // while the vectors don't matter for usb comms as interrupts are disabled during erase, it's important - // to minimise the chance of leaving the device in a state where the bootloader wont run, if there's power failure - // during upload - - uint8_t i; - uint16_t ptr = BOOTLOADER_ADDRESS; - cli(); - while (ptr) { - ptr -= SPM_PAGESIZE; - boot_page_erase(ptr); - } + // erase all pages until bootloader, in reverse order (so our vectors stay in place for as long as possible) + // while the vectors don't matter for usb comms as interrupts are disabled during erase, it's important + // to minimise the chance of leaving the device in a state where the bootloader wont run, if there's power failure + // during upload + + uint8_t i; + uint16_t ptr = BOOTLOADER_ADDRESS; + cli(); + + while (ptr) { + ptr -= SPM_PAGESIZE; + boot_page_erase(ptr); + } currentAddress = 0; - for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF); // Write first 8 words to fill in vectors. - writeFlashPage(); // enables interrupts + for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF); // Write first 8 words to fill in vectors. + writeFlashPage(); // enables interrupts } // simply write currently stored page in to already erased flash memory static void writeFlashPage(void) { - cli(); - boot_page_write(currentAddress - 2); // will halt CPU, no waiting required - sei(); + cli(); + boot_page_write(currentAddress - 2); // will halt CPU, no waiting required + sei(); } // clear memory which stores data to be written by next writeFlashPage call #define __boot_page_fill_clear() \ (__extension__({ \ - __asm__ __volatile__ \ - ( \ - "sts %0, %1\n\t" \ - "spm\n\t" \ - : \ - : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ - "r" ((uint8_t)(__BOOT_PAGE_FILL | (1 << CTPB))) \ - ); \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)(__BOOT_PAGE_FILL | (1 << CTPB))) \ + ); \ })) // write a word in to the page buffer, doing interrupt table modifications where they're required static void writeWordToPageBuffer(uint16_t data) { - uint8_t previous_sreg; + uint8_t previous_sreg; + + // first two interrupt vectors get replaced with a jump to the bootloader's vector table + // remember vectors or the tinyvector table + if (currentAddress == RESET_VECTOR_OFFSET * 2) { + vectorTemp[0] = data; + data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; + } + + if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) { + vectorTemp[1] = data; + data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; + } - // first two interrupt vectors get replaced with a jump to the bootloader's vector table - // remember vectors or the tinyvector table - if (currentAddress == RESET_VECTOR_OFFSET * 2) { - vectorTemp[0] = data; - data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; - } - - if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) { - vectorTemp[1] = data; - data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; - } - - // at end of page just before bootloader, write in tinyVector table - // see http://embedded-creations.com/projects/attiny85-usb-bootloader-overview/avr-jtag-programmer/ - // for info on how the tiny vector table works - if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) { - data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET; - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) { - data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET; + // at end of page just before bootloader, write in tinyVector table + // see http://embedded-creations.com/projects/attiny85-usb-bootloader-overview/avr-jtag-programmer/ + // for info on how the tiny vector table works + if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) { + data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET; + } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) { + data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET; #if (!OSCCAL_RESTORE) && OSCCAL_16_5MHz - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { - data = OSCCAL; + } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { + data = OSCCAL; #endif - } + } - previous_sreg=SREG; - cli(); // ensure interrupts are disabled - - boot_page_fill(currentAddress, data); - - // increment progmem address by one word - currentAddress += 2; - SREG=previous_sreg; + previous_sreg=SREG; + cli(); // ensure interrupts are disabled + + boot_page_fill(currentAddress, data); + + // increment progmem address by one word + currentAddress += 2; + SREG=previous_sreg; } /* ------------------------------------------------------------------------ */ static uint8_t usbFunctionSetup(uint8_t data[8]) { - usbRequest_t *rq = (void *)data; - ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic - - static uint8_t replyBuffer[4] = { - (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff, - ((uint16_t)PROGMEM_SIZE) & 0xff, - SPM_PAGESIZE, - MICRONUCLEUS_WRITE_SLEEP - }; + usbRequest_t *rq = (void *)data; + ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic + + static uint8_t replyBuffer[4] = { + (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff, + ((uint16_t)PROGMEM_SIZE) & 0xff, + SPM_PAGESIZE, + MICRONUCLEUS_WRITE_SLEEP + }; - if (rq->bRequest == 0) { // get device info - usbMsgPtr = replyBuffer; - return 4; - - } else if (rq->bRequest == 1) { // write page - - // clear page buffer as a precaution before filling the buffer in case - // a previous write operation failed and there is still something in the buffer. - __boot_page_fill_clear(); - currentAddress = rq->wIndex.word; - return USB_NO_MSG; // hands off work to usbFunctionWrite - - } else if (rq->bRequest == 2) { // erase application - fireEvent(EVENT_ERASE_APPLICATION); - - } else { // exit bootloader -# if BOOTLOADER_CAN_EXIT - fireEvent(EVENT_EXECUTE); -# endif - } + if (rq->bRequest == 0) { // get device info + usbMsgPtr = replyBuffer; + return 4; + } else if (rq->bRequest == 1) { // write page + + // clear page buffer as a precaution before filling the buffer in case + // a previous write operation failed and there is still something in the buffer. + __boot_page_fill_clear(); + currentAddress = rq->wIndex.word; + return USB_NO_MSG; // hands off work to usbFunctionWrite - return 0; + } else if (rq->bRequest == 2) { // erase application + fireEvent(EVENT_ERASE_APPLICATION); + + } else { // exit bootloader + fireEvent(EVENT_EXECUTE); + } + + return 0; } // read in a page over usb, and write it in to the flash write buffer static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { - do { - // make sure we don't write over the bootloader! - if (currentAddress >= BOOTLOADER_ADDRESS) break; - - writeWordToPageBuffer(*(uint16_t *) data); - data += 2; // advance data pointer - length -= 2; - } while(length); + do { + // make sure we don't write over the bootloader! + if (currentAddress >= BOOTLOADER_ADDRESS) break; - // if we have now reached another page boundary, we're done + writeWordToPageBuffer(*(uint16_t *) data); + data += 2; // advance data pointer + length -= 2; + } while(length); + + // if we have now reached another page boundary, we're done #if SPM_PAGESIZE<256 // Hack to reduce code size - uint8_t isLast = ((((uint8_t)currentAddress) % SPM_PAGESIZE) == 0); + uint8_t isLast = ((((uint8_t)currentAddress) % SPM_PAGESIZE) == 0); #else - uint8_t isLast = ((currentAddress % SPM_PAGESIZE) == 0); + uint8_t isLast = ((currentAddress % SPM_PAGESIZE) == 0); #endif - // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! - if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page - - return isLast; // let vusb know we're done with this request + // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! + if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page + + return isLast; // let vusb know we're done with this request } /* ------------------------------------------------------------------------ */ @@ -229,10 +227,10 @@ void PushMagicWord (void) __attribute__ ((naked)) __attribute__ ((section (".ini // put the word "B007" at the bottom of the stack (RAMEND - RAMEND-1) void PushMagicWord (void) { - asm volatile("ldi r16, 0xB0"::); - asm volatile("push r16"::); - asm volatile("ldi r16, 0x07"::); - asm volatile("push r16"::); + asm volatile("ldi r16, 0xB0"::); + asm volatile("push r16"::); + asm volatile("ldi r16, 0x07"::); + asm volatile("push r16"::); } static void initHardware (void) @@ -252,29 +250,29 @@ static void initHardware (void) // reset system to a normal state and launch user program static void leaveBootloader(void) __attribute__((__noreturn__)); static inline void leaveBootloader(void) { - _delay_ms(10); // removing delay causes USB errors - - bootLoaderExit(); - cli(); + _delay_ms(10); // removing delay causes USB errors + + bootLoaderExit(); + cli(); usbDeviceDisconnect(); /* Disconnect micronucleus */ - - USB_INTR_ENABLE = 0; - USB_INTR_CFG = 0; /* also reset config bits */ - // clear magic word from bottom of stack before jumping to the app - *(uint8_t*)(RAMEND) = 0x00; // A single write is sufficient to invalidate magic word + USB_INTR_ENABLE = 0; + USB_INTR_CFG = 0; /* also reset config bits */ + + // clear magic word from bottom of stack before jumping to the app + *(uint8_t*)(RAMEND) = 0x00; // A single write is sufficient to invalidate magic word #if (!OSCCAL_RESTORE) && OSCCAL_16_5MHz - // adjust clock to previous calibration value, so user program always starts with same calibration - // as when it was uploaded originally - unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET); - if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) { - OSCCAL=stored_osc_calibration; - nop(); - } + // adjust clock to previous calibration value, so user program always starts with same calibration + // as when it was uploaded originally + unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET); + if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) { + OSCCAL=stored_osc_calibration; + nop(); + } #endif - // jump to application reset vector at end of flash - asm volatile ("rjmp __vectors - 4"); + // jump to application reset vector at end of flash + asm volatile ("rjmp __vectors - 4"); } int main(void) { -- cgit v1.2.3 From 0712bc8b3fe71e923e37067242fe43978f6d7db9 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sat, 28 Dec 2013 15:05:19 +0100 Subject: firmware: More robut WDT handling backported optimization by @gblargg --- firmware/main.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index bec0305..4ceb19e 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -113,10 +113,10 @@ static void writeFlashPage(void) { } // clear memory which stores data to be written by next writeFlashPage call -#define __boot_page_fill_clear() \ -(__extension__({ \ - __asm__ __volatile__ \ - ( \ +#define __boot_page_fill_clear() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ "sts %0, %1\n\t" \ "spm\n\t" \ : \ @@ -235,9 +235,11 @@ void PushMagicWord (void) { static void initHardware (void) { - MCUSR=0; /* need this to properly disable watchdog */ - wdt_disable(); - + // Disable watchdog and set timeout to maximum in case the WDT is fused on + MCUSR=0; + WDTCR = 1< Date: Sat, 28 Dec 2013 23:24:23 +0100 Subject: firmware: code clean up, consolidated wait loops to save 4 bytes --- firmware/main.c | 65 ++++++++++++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 35 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 4ceb19e..8394e7e 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -239,7 +239,12 @@ static void initHardware (void) MCUSR=0; WDTCR = 1< 9ms before next usb request - if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); - if (isEvent(EVENT_WRITE_PAGE)) { - _delay_us(2000); // Wait for USB traffic to finish before halting CPU with write- - writeFlashPage(); - } - - LED_MACRO( ((uint8_t*)&idlePolls)[1] ); + idlePolls++; // Try to execute program if bootloader exit condition is met if (AUTO_EXIT_MS&&(idlePolls>AUTO_EXIT_MS*10L)) fireEvent(EVENT_EXECUTE); + LED_MACRO( ((uint8_t*)&idlePolls)[1] ); + + // Wait for USB traffic to finish before a blocking event is executed + // All events will render the MCU unresponsive to USB traffic for a while. + if (events) _delay_ms(2); + if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); + if (isEvent(EVENT_WRITE_PAGE)) writeFlashPage(); + /* main event loop runs as long as no problem is uploaded or existing program is not executed */ } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); + + LED_EXIT(); } - LED_EXIT(); - - #if OSCCAL_RESTORE - OSCCAL=osccal_default; - nop(); // NOP to avoid CPU hickup during oscillator stabilization - #endif - leaveBootloader(); } /* ------------------------------------------------------------------------ */ -- cgit v1.2.3 From 67039d6a1334e65db2e7dd4d5e97a81474d0ee71 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 29 Dec 2013 18:48:45 +0100 Subject: fireware: Bugfix: no slowndown after timer overflow --- firmware/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 8394e7e..4673384 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -304,17 +304,18 @@ int main(void) { clearEvents(); usbPoll(); - + idlePolls++; // Try to execute program if bootloader exit condition is met - if (AUTO_EXIT_MS&&(idlePolls>AUTO_EXIT_MS*10L)) fireEvent(EVENT_EXECUTE); + if (AUTO_EXIT_MS&&(idlePolls==AUTO_EXIT_MS*10L)) fireEvent(EVENT_EXECUTE); + LED_MACRO( ((uint8_t*)&idlePolls)[1] ); // Wait for USB traffic to finish before a blocking event is executed // All events will render the MCU unresponsive to USB traffic for a while. if (events) _delay_ms(2); - + if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); if (isEvent(EVENT_WRITE_PAGE)) writeFlashPage(); -- cgit v1.2.3 From af4391ccca909aa788424d50c1cb3469c3f146ed Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 29 Dec 2013 19:47:55 +0100 Subject: firmware: Replace flag system with single command system to save 12 bytes --- firmware/main.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 4673384..89e038d 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,5 +1,5 @@ /* Name: main.c - * Project: Micronucleus + * Project: Micronucleus * Author: Jenna Fox * Creation Date: 2007-12-08 * Tabsize: 4 @@ -12,7 +12,7 @@ */ #define MICRONUCLEUS_VERSION_MAJOR 1 -#define MICRONUCLEUS_VERSION_MINOR 10 +#define MICRONUCLEUS_VERSION_MINOR 11 // how many milliseconds should host wait till it sends another erase or write? // needs to be above 4.5 (and a whole integer) as avr freezes for 4.5ms #define MICRONUCLEUS_WRITE_SLEEP 8 @@ -48,8 +48,16 @@ // events system schedules functions to run in the main loop // static uint8_t events = 0; // bitmap of events to run -register uint8_t events asm( "r3" ); // register saves many bytes +register uint8_t command asm( "r3" ); // register saves many bytes +enum { + cmd_nop=0, + cmd_erase_application, + cmd_write_page, + cmd_exit +}; + +/* #define EVENT_ERASE_APPLICATION 1 #define EVENT_WRITE_PAGE 2 #define EVENT_EXECUTE 4 @@ -58,7 +66,7 @@ register uint8_t events asm( "r3" ); // register saves many bytes #define fireEvent(event) events |= (event) #define isEvent(event) (events & (event)) #define clearEvents() events = 0 - +*/ // Definition of sei and cli without memory barrier keyword to prevent reloading of memory variables #define sei() asm volatile("sei") #define cli() asm volatile("cli") @@ -188,10 +196,10 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { return USB_NO_MSG; // hands off work to usbFunctionWrite } else if (rq->bRequest == 2) { // erase application - fireEvent(EVENT_ERASE_APPLICATION); + command=cmd_erase_application; } else { // exit bootloader - fireEvent(EVENT_EXECUTE); + command=cmd_exit; } return 0; @@ -217,7 +225,7 @@ static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { #endif // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! - if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page + if (isLast) command=cmd_write_page; // ask runloop to write our page return isLast; // let vusb know we're done with this request } @@ -302,25 +310,25 @@ int main(void) { _delay_us(100); wdt_reset(); // Only necessary if WDT is fused on - clearEvents(); + command=cmd_nop; usbPoll(); idlePolls++; // Try to execute program if bootloader exit condition is met - if (AUTO_EXIT_MS&&(idlePolls==AUTO_EXIT_MS*10L)) fireEvent(EVENT_EXECUTE); + if (AUTO_EXIT_MS&&(idlePolls==AUTO_EXIT_MS*10L)) command=cmd_exit; LED_MACRO( ((uint8_t*)&idlePolls)[1] ); // Wait for USB traffic to finish before a blocking event is executed // All events will render the MCU unresponsive to USB traffic for a while. - if (events) _delay_ms(2); + if (command!=cmd_nop) _delay_ms(2); - if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); - if (isEvent(EVENT_WRITE_PAGE)) writeFlashPage(); + if (command==cmd_erase_application) eraseApplication(); + if (command==cmd_write_page) writeFlashPage(); /* main event loop runs as long as no problem is uploaded or existing program is not executed */ - } while((!isEvent(EVENT_EXECUTE))||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); + } while((command!=cmd_exit)||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); LED_EXIT(); } -- cgit v1.2.3 From b97b7ecb1633750dafc7cc60d834b510961d6cb1 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 29 Dec 2013 19:48:32 +0100 Subject: firmware: Check is irrelevant - idlecount is not changed during erase --- firmware/main.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 89e038d..78f839a 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -39,15 +39,7 @@ # error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize" #endif -#ifdef AUTO_EXIT_MS -# if AUTO_EXIT_MS < (MICRONUCLEUS_WRITE_SLEEP * (BOOTLOADER_ADDRESS / SPM_PAGESIZE)) -# warning "AUTO_EXIT_MS is shorter than the time it takes to perform erase function - might affect reliability?" -# warning "Try increasing AUTO_EXIT_MS if you have stability problems" -# endif -#endif - -// events system schedules functions to run in the main loop -// static uint8_t events = 0; // bitmap of events to run +// command system schedules functions to run in the main loop register uint8_t command asm( "r3" ); // register saves many bytes enum { @@ -57,16 +49,6 @@ enum { cmd_exit }; -/* -#define EVENT_ERASE_APPLICATION 1 -#define EVENT_WRITE_PAGE 2 -#define EVENT_EXECUTE 4 - -// controls state of events -#define fireEvent(event) events |= (event) -#define isEvent(event) (events & (event)) -#define clearEvents() events = 0 -*/ // Definition of sei and cli without memory barrier keyword to prevent reloading of memory variables #define sei() asm volatile("sei") #define cli() asm volatile("cli") -- cgit v1.2.3 From b024f8aa4d9247dfaebe41f9f7b8716a2b31df68 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 29 Dec 2013 20:37:22 +0100 Subject: firmware: clean up, updated file header --- firmware/main.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 78f839a..828ea8f 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,14 +1,13 @@ -/* Name: main.c - * Project: Micronucleus - * Author: Jenna Fox - * Creation Date: 2007-12-08 - * Tabsize: 4 - * Copyright: (c) 2012 Jenna Fox - * All changes past revision 1.06 authored by http://github.com/cpldcpu - * Portions Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH (USBaspLoader) - * Portions Copyright: (c) 2012 Louis Beaudoin (USBaspLoader-tiny85) - * License: GNU GPL v2 (see License.txt) +/* + * Project: Micronucleus - v1.11 + * + * Author (c) 2012 Jenna Fox + * Optimizations after v1.06 (c) 2013 Tim Bo"scke - cpldcpu@gmail.com + * Further input (c) 2013 Shay Green + * Based on USBaspLoader-tiny85 (c) 2012 Louis Beaudoin + * Based on USBaspLoader (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * + * License: GNU GPL v2 (see License.txt) */ #define MICRONUCLEUS_VERSION_MAJOR 1 @@ -28,12 +27,6 @@ #include "bootloaderconfig.h" #include "usbdrv/usbdrv.c" -/* ------------------------------------------------------------------------ */ -// postscript are the few bytes at the end of programmable memory which store tinyVectors -// and used to in USBaspLoader-tiny85 store the checksum iirc -#define POSTSCRIPT_SIZE 6 -#define PROGMEM_SIZE (BOOTLOADER_ADDRESS - POSTSCRIPT_SIZE) /* max size of user program */ - // verify the bootloader address aligns with page size #if BOOTLOADER_ADDRESS % SPM_PAGESIZE != 0 # error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize" -- cgit v1.2.3 From 7f1acb2ebd7cb8c309680af437ea8bb1ca48e4d8 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Sun, 29 Dec 2013 20:53:45 +0100 Subject: firmware: switch saves 2 bytes --- firmware/main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 828ea8f..447ff20 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -299,9 +299,11 @@ int main(void) { // All events will render the MCU unresponsive to USB traffic for a while. if (command!=cmd_nop) _delay_ms(2); - if (command==cmd_erase_application) eraseApplication(); - if (command==cmd_write_page) writeFlashPage(); - + if (command==cmd_erase_application) + eraseApplication(); + else if (command==cmd_write_page) + writeFlashPage(); + /* main event loop runs as long as no problem is uploaded or existing program is not executed */ } while((command!=cmd_exit)||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)); -- cgit v1.2.3 From 58514cfadd15985ff3ac279679930d372f705687 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Tue, 31 Dec 2013 00:54:19 +0100 Subject: firmware: Directly mapped command register saves 12 btes --- firmware/main.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 447ff20..d0a3edd 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -36,10 +36,11 @@ register uint8_t command asm( "r3" ); // register saves many bytes enum { - cmd_nop=0, - cmd_erase_application, - cmd_write_page, - cmd_exit + cmd_nop=0, // also: get device info + cmd_transfer_page=1, + cmd_erase_application=2, + cmd_exit=4, + cmd_write_page=5, }; // Definition of sei and cli without memory barrier keyword to prevent reloading of memory variables @@ -162,22 +163,18 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { if (rq->bRequest == 0) { // get device info usbMsgPtr = replyBuffer; return 4; - } else if (rq->bRequest == 1) { // write page + } else if (rq->bRequest == cmd_transfer_page) { // transfer page // clear page buffer as a precaution before filling the buffer in case // a previous write operation failed and there is still something in the buffer. __boot_page_fill_clear(); currentAddress = rq->wIndex.word; return USB_NO_MSG; // hands off work to usbFunctionWrite - - } else if (rq->bRequest == 2) { // erase application - command=cmd_erase_application; - - } else { // exit bootloader - command=cmd_exit; - } - + } else { + // Handle cmd_erase_application and cmd_exit + command=rq->bRequest; return 0; + } } // read in a page over usb, and write it in to the flash write buffer -- cgit v1.2.3 From 5b94559c7226774bda746f640b351bec07fe842f Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Tue, 31 Dec 2013 12:55:24 +0100 Subject: firemware: Clean up command handling --- firmware/main.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index d0a3edd..ad0b7a2 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -36,7 +36,8 @@ register uint8_t command asm( "r3" ); // register saves many bytes enum { - cmd_nop=0, // also: get device info + cmd_local_nop=0, // also: get device info + cmd_device_info=0, cmd_transfer_page=1, cmd_erase_application=2, cmd_exit=4, @@ -151,7 +152,6 @@ static void writeWordToPageBuffer(uint16_t data) { /* ------------------------------------------------------------------------ */ static uint8_t usbFunctionSetup(uint8_t data[8]) { usbRequest_t *rq = (void *)data; - ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic static uint8_t replyBuffer[4] = { (((uint16_t)PROGMEM_SIZE) >> 8) & 0xff, @@ -159,21 +159,22 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { SPM_PAGESIZE, MICRONUCLEUS_WRITE_SLEEP }; - - if (rq->bRequest == 0) { // get device info + + ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic + + if (rq->bRequest == cmd_device_info) { // get device info usbMsgPtr = replyBuffer; return 4; - } else if (rq->bRequest == cmd_transfer_page) { // transfer page - + } else if (rq->bRequest == cmd_transfer_page) { // transfer page // clear page buffer as a precaution before filling the buffer in case // a previous write operation failed and there is still something in the buffer. __boot_page_fill_clear(); currentAddress = rq->wIndex.word; return USB_NO_MSG; // hands off work to usbFunctionWrite } else { - // Handle cmd_erase_application and cmd_exit - command=rq->bRequest; - return 0; + // Handle cmd_erase_application and cmd_exit + command=rq->bRequest; + return 0; } } @@ -263,7 +264,7 @@ static inline void leaveBootloader(void) { // jump to application reset vector at end of flash asm volatile ("rjmp __vectors - 4"); -} + } int main(void) { @@ -282,7 +283,7 @@ int main(void) { _delay_us(100); wdt_reset(); // Only necessary if WDT is fused on - command=cmd_nop; + command=cmd_local_nop; usbPoll(); idlePolls++; @@ -294,7 +295,7 @@ int main(void) { // Wait for USB traffic to finish before a blocking event is executed // All events will render the MCU unresponsive to USB traffic for a while. - if (command!=cmd_nop) _delay_ms(2); + if (command!=cmd_local_nop) _delay_ms(2); if (command==cmd_erase_application) eraseApplication(); -- cgit v1.2.3 From 8f6ccdaccf624a3e2c727ff4e6ad2c7dc479b51b Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Tue, 31 Dec 2013 13:34:12 +0100 Subject: firmware: leavebootloader does never return The compiler does only understand this when inserting an infinite loop. Saves two bytes and prevents a warning. --- firmware/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index ad0b7a2..efef481 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -261,10 +261,11 @@ static inline void leaveBootloader(void) { nop(); } #endif - - // jump to application reset vector at end of flash - asm volatile ("rjmp __vectors - 4"); - } + + asm volatile ("rjmp __vectors - 4"); // jump to application reset vector at end of flash + + for (;;); // Make sure function does not return to help compiler optimize +} int main(void) { -- cgit v1.2.3 From 6d2ac9e09f61d6ff267961ba9ff79b0a07e78e28 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Tue, 31 Dec 2013 15:42:09 +0100 Subject: firmware: more global registers and unions types Saves 70(!) bytes or so.. --- firmware/main.c | 78 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 40 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index efef481..3ad1a14 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -29,11 +29,23 @@ // verify the bootloader address aligns with page size #if BOOTLOADER_ADDRESS % SPM_PAGESIZE != 0 -# error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize" + #error "BOOTLOADER_ADDRESS in makefile must be a multiple of chip's pagesize" +#endif + +#if SPM_PAGESIZE>256 + #error "Micronucleus only supports pagesizes up to 256 bytes" #endif // command system schedules functions to run in the main loop -register uint8_t command asm( "r3" ); // register saves many bytes +register uint8_t command asm("r3"); // bind command to r3 +register uint16_union_t currentAddress asm("r4"); // r4/r5 current progmem address, used for erasing and writing +register uint16_union_t idlePolls asm("r6"); // r6/r7 idlecounter + +#if OSCCAL_RESTORE + register uint8_t osccal_default asm("r2"); +#endif + +static uint16_t vectorTemp[2]; // remember data to create tinyVector table before BOOTLOADER_ADDRESS enum { cmd_local_nop=0, // also: get device info @@ -49,15 +61,6 @@ enum { #define cli() asm volatile("cli") #define nop() asm volatile("nop") -uint16_t idlePolls = 0; // how long have we been idle? - -static uint16_t vectorTemp[2]; // remember data to create tinyVector table before BOOTLOADER_ADDRESS -static uint16_t currentAddress; // current progmem address, used for erasing and writing - -#if OSCCAL_RESTORE - static uint8_t osccal_default; // due to compiler insanity, having this as global actually saves memory -#endif - /* ------------------------------------------------------------------------ */ static inline void eraseApplication(void); static void writeFlashPage(void); @@ -85,7 +88,7 @@ static inline void eraseApplication(void) { boot_page_erase(ptr); } - currentAddress = 0; + currentAddress.w = 0; for (i=0; i<8; i++) writeWordToPageBuffer(0xFFFF); // Write first 8 words to fill in vectors. writeFlashPage(); // enables interrupts } @@ -93,7 +96,7 @@ static inline void eraseApplication(void) { // simply write currently stored page in to already erased flash memory static void writeFlashPage(void) { cli(); - boot_page_write(currentAddress - 2); // will halt CPU, no waiting required + boot_page_write(currentAddress.w - 2); // will halt CPU, no waiting required sei(); } @@ -116,12 +119,12 @@ static void writeWordToPageBuffer(uint16_t data) { // first two interrupt vectors get replaced with a jump to the bootloader's vector table // remember vectors or the tinyvector table - if (currentAddress == RESET_VECTOR_OFFSET * 2) { + if (currentAddress.w == RESET_VECTOR_OFFSET * 2) { vectorTemp[0] = data; data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; } - if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) { + if (currentAddress.w == USBPLUS_VECTOR_OFFSET * 2) { vectorTemp[1] = data; data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1; } @@ -129,12 +132,12 @@ static void writeWordToPageBuffer(uint16_t data) { // at end of page just before bootloader, write in tinyVector table // see http://embedded-creations.com/projects/attiny85-usb-bootloader-overview/avr-jtag-programmer/ // for info on how the tiny vector table works - if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) { + if (currentAddress.w == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) { data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET; - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) { + } else if (currentAddress.w == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) { data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET; #if (!OSCCAL_RESTORE) && OSCCAL_16_5MHz - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { + } else if (currentAddress.w == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { data = OSCCAL; #endif } @@ -142,10 +145,10 @@ static void writeWordToPageBuffer(uint16_t data) { previous_sreg=SREG; cli(); // ensure interrupts are disabled - boot_page_fill(currentAddress, data); + boot_page_fill(currentAddress.w, data); // increment progmem address by one word - currentAddress += 2; + currentAddress.w += 2; SREG=previous_sreg; } @@ -160,8 +163,8 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { MICRONUCLEUS_WRITE_SLEEP }; - ((uint8_t*)&idlePolls)[1] = 0; // reset idle polls when we get usb traffic - + idlePolls.b[1]=0; // reset idle polls when we get usb traffic + if (rq->bRequest == cmd_device_info) { // get device info usbMsgPtr = replyBuffer; return 4; @@ -169,7 +172,7 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { // clear page buffer as a precaution before filling the buffer in case // a previous write operation failed and there is still something in the buffer. __boot_page_fill_clear(); - currentAddress = rq->wIndex.word; + currentAddress.w = rq->wIndex.word; return USB_NO_MSG; // hands off work to usbFunctionWrite } else { // Handle cmd_erase_application and cmd_exit @@ -182,7 +185,7 @@ static uint8_t usbFunctionSetup(uint8_t data[8]) { static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { do { // make sure we don't write over the bootloader! - if (currentAddress >= BOOTLOADER_ADDRESS) break; + if (currentAddress.w >= BOOTLOADER_ADDRESS) break; writeWordToPageBuffer(*(uint16_t *) data); data += 2; // advance data pointer @@ -190,17 +193,10 @@ static uint8_t usbFunctionWrite(uint8_t *data, uint8_t length) { } while(length); // if we have now reached another page boundary, we're done -#if SPM_PAGESIZE<256 - // Hack to reduce code size - uint8_t isLast = ((((uint8_t)currentAddress) % SPM_PAGESIZE) == 0); -#else - uint8_t isLast = ((currentAddress % SPM_PAGESIZE) == 0); -#endif - - // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop! + uint8_t isLast = ((currentAddress.b[0] % SPM_PAGESIZE) == 0); if (isLast) command=cmd_write_page; // ask runloop to write our page - return isLast; // let vusb know we're done with this request + return isLast; // let V-USB know we're done with this request } /* ------------------------------------------------------------------------ */ @@ -271,14 +267,16 @@ int main(void) { bootLoaderInit(); - #if AUTO_EXIT_NO_USB_MS - ((uint8_t*)&idlePolls)[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; // write only high byte to save 6 bytes - #endif - if (bootLoaderStartCondition()||(pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET + 1)==0xff)) { initHardware(); LED_INIT(); + + if (AUTO_EXIT_NO_USB_MS>0) { + idlePolls.b[1]=((AUTO_EXIT_MS-AUTO_EXIT_NO_USB_MS) * 10UL)>>8; + } else { + idlePolls.b[1]=0; + } do { _delay_us(100); @@ -287,12 +285,12 @@ int main(void) { command=cmd_local_nop; usbPoll(); - idlePolls++; + idlePolls.w++; // Try to execute program if bootloader exit condition is met - if (AUTO_EXIT_MS&&(idlePolls==AUTO_EXIT_MS*10L)) command=cmd_exit; + if (AUTO_EXIT_MS&&(idlePolls.w==AUTO_EXIT_MS*10L)) command=cmd_exit; - LED_MACRO( ((uint8_t*)&idlePolls)[1] ); + LED_MACRO( idlePolls.b[1] ); // Wait for USB traffic to finish before a blocking event is executed // All events will render the MCU unresponsive to USB traffic for a while. -- cgit v1.2.3 From be508b4aa482d1677a894318fd4ad9da3a8fe5d4 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Fri, 3 Jan 2014 20:50:08 +0100 Subject: firmware: typo, fix warning --- firmware/main.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'firmware/main.c') diff --git a/firmware/main.c b/firmware/main.c index 3ad1a14..16cca65 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,9 +1,11 @@ /* * Project: Micronucleus - v1.11 * - * Author (c) 2012 Jenna Fox - * Optimizations after v1.06 (c) 2013 Tim Bo"scke - cpldcpu@gmail.com - * Further input (c) 2013 Shay Green + * Original author (c) 2012 Jenna Fox + * + * Optimizations v1.10/v1.11 (c) 2013 Tim Bo"scke - cpldcpu@gmail.com + * v1.11 (c) 2013 Shay Green + * * Based on USBaspLoader-tiny85 (c) 2012 Louis Beaudoin * Based on USBaspLoader (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * @@ -25,6 +27,9 @@ #include #include "bootloaderconfig.h" + + + #include "usbdrv/usbdrv.c" // verify the bootloader address aligns with page size @@ -152,6 +157,9 @@ static void writeWordToPageBuffer(uint16_t data) { SREG=previous_sreg; } +// This function is never called, it is just here to suppress a compiler warning. +USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { return 0; } + /* ------------------------------------------------------------------------ */ static uint8_t usbFunctionSetup(uint8_t data[8]) { usbRequest_t *rq = (void *)data; -- cgit v1.2.3