From 9a194c88b2f1a35d63e4677c10c7c424ee6f4db6 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Mon, 4 Nov 2013 00:34:06 +0100 Subject: remove --- firmware/main_old.c | 487 ---------------------------------------------------- 1 file changed, 487 deletions(-) delete mode 100644 firmware/main_old.c diff --git a/firmware/main_old.c b/firmware/main_old.c deleted file mode 100644 index 527923e..0000000 --- a/firmware/main_old.c +++ /dev/null @@ -1,487 +0,0 @@ -/* Name: main.c - * Project: Micronucleus - * Author: Jenna Fox - * Creation Date: 2007-12-08 - * Tabsize: 4 - * Copyright: (c) 2012 Jenna Fox - * 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) - */ - -#define MICRONUCLEUS_VERSION_MAJOR 1 -#define MICRONUCLEUS_VERSION_MINOR 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__ - - -#include -#include -#include -#include -#include -//#include -#include -//#include - -static void leaveBootloader() __attribute__((__noreturn__)); - -#include "bootloaderconfig.h" -#include "usbdrv/usbdrv.c" - -/* ------------------------------------------------------------------------ */ - -#ifndef ulong -# define ulong unsigned long -#endif -#ifndef uint -# define uint unsigned int -#endif - -#ifndef BOOTLOADER_CAN_EXIT -# define BOOTLOADER_CAN_EXIT 0 -#endif - -/* allow compatibility with avrusbboot's bootloaderconfig.h: */ -#ifdef BOOTLOADER_INIT -# define bootLoaderInit() BOOTLOADER_INIT -# define bootLoaderExit() -#endif -#ifdef BOOTLOADER_CONDITION -# define bootLoaderCondition() BOOTLOADER_CONDITION -#endif - -/* device compatibility: */ -#ifndef GICR /* ATMega*8 don't have GICR, use MCUCR instead */ -# define GICR MCUCR -#endif - -/* ------------------------------------------------------------------------ */ - -#define addr_t uint - -// typedef union longConverter{ -// addr_t l; -// uint w[sizeof(addr_t)/2]; -// uchar b[sizeof(addr_t)]; -// } longConverter_t; - -//////// Stuff Bluebie Added -// 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" -#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 uchar events = 0; // bitmap of events to run -#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 - -// length of bytes to write in to flash memory in upcoming usbFunctionWrite calls -//static unsigned char writeLength; - -// becomes 1 when some programming happened -// lets leaveBootloader know if needs to finish up the programming -static uchar didWriteSomething = 0; - -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 addr_t currentAddress; // current progmem address, used for erasing and writing - -#ifdef RESTORE_OSCCAL - 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); -static void writeWordToPageBuffer(uint16_t data); -static void fillFlashWithVectors(void); -static uchar usbFunctionSetup(uchar data[8]); -static uchar usbFunctionWrite(uchar *data, uchar length); -static inline void initForUsbConnectivity(void); -static inline void tiny85FlashInit(void); -static inline void tiny85FlashWrites(void); -//static inline void tiny85FinishWriting(void); -static inline void leaveBootloader(void); - -// erase any existing application and write in jumps for usb interrupt and reset to bootloader -// - Because flash can be erased once and programmed several times, we can write the bootloader -// - 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 - addr_t ptr = BOOTLOADER_ADDRESS; - - cli(); - while (ptr) { - ptr -= SPM_PAGESIZE; - - boot_page_erase(ptr); - boot_spm_busy_wait(); - } - - currentAddress = 0; - fillFlashWithVectors(); - sei(); -} - -// simply write currently stored page in to already erased flash memory -static void writeFlashPage(void) { - uint8_t previous_sreg = SREG; // backup current interrupt setting - didWriteSomething = 1; - cli(); - boot_page_write(currentAddress - 2); - boot_spm_busy_wait(); // Wait until the memory is written. - SREG = previous_sreg; // restore interrupts to previous state -} - -// 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))) \ - ); \ -})) - -// 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; - - // first two interrupt vectors get replaced with a jump to the bootloader's vector table - if (currentAddress == (RESET_VECTOR_OFFSET * 2) || currentAddress == (USBPLUS_VECTOR_OFFSET * 2)) { - 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; -#ifndef RESTORE_OSCCAL - } else if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET) { - data = OSCCAL; -#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 - if (currentAddress == 0x0000) __boot_page_fill_clear(); - - previous_sreg = SREG; // backup previous interrupt settings - cli(); // ensure interrupts are disabled - boot_page_fill(currentAddress, data); - SREG = previous_sreg; // restore previous interrupt setting - - // only need to erase if there is data already in the page that doesn't match what we're programming - // TODO: what about this: if (pgm_read_word(currentAddress) & data != data) { ??? should work right? - //if (pgm_read_word(currentAddress) != data && pgm_read_word(currentAddress) != 0xFFFF) { - //if ((pgm_read_word(currentAddress) & data) != data) { - // fireEvent(EVENT_PAGE_NEEDS_ERASE); - //} - - // increment progmem address by one word - currentAddress += 2; -} - -// fills the rest of this page with vectors - interrupt vector or tinyvector tables where needed -static void fillFlashWithVectors(void) { - //int16_t i; - // - // fill all or remainder of page with 0xFFFF (as if unprogrammed) - //for (i = currentAddress % SPM_PAGESIZE; i < SPM_PAGESIZE; i += 2) { - // writeWordToPageBuffer(0xFFFF); // is where vector tables are sorted out - //} - - // TODO: Or more simply: - - -#if SPM_PAGESIZE<256 - do { - writeWordToPageBuffer(0xFFFF); - } while ((uchar)currentAddress % SPM_PAGESIZE); -#else - do { - writeWordToPageBuffer(0xFFFF); - } while (currentAddress % SPM_PAGESIZE); -#endif - - - writeFlashPage(); -} - -/* ------------------------------------------------------------------------ */ - -static uchar usbFunctionSetup(uchar data[8]) { - usbRequest_t *rq = (void *)data; - idlePolls = 0; // reset idle polls when we get usb traffic - - static uchar replyBuffer[4] = { - (((uint)PROGMEM_SIZE) >> 8) & 0xff, - ((uint)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 - //writeLength = rq->wValue.word; - 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 - } - - return 0; -} - - -// read in a page over usb, and write it in to the flash write buffer -static uchar usbFunctionWrite(uchar *data, uchar length) { - //if (length > writeLength) length = writeLength; // test for missing final page bug - //writeLength -= length; - - do { - // remember vectors or the tinyvector table - if (currentAddress == RESET_VECTOR_OFFSET * 2) { - vectorTemp[0] = *(short *)data; - } - - if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) { - vectorTemp[1] = *(short *)data; - } - - // make sure we don't write over the bootloader! - if (currentAddress >= BOOTLOADER_ADDRESS) { - //__boot_page_fill_clear(); - break; - } - - writeWordToPageBuffer(*(uint16_t *) data); - data += 2; // advance data pointer - length -= 2; - } while(length); - - // if we have now reached another page boundary, we're done - //uchar isLast = (writeLength == 0); - -#if SPM_PAGESIZE<256 - // Hack to reduce code size - uchar isLast = ((((uchar)currentAddress) % SPM_PAGESIZE) == 0); -#else - uchar 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 -} - -/* ------------------------------------------------------------------------ */ - -void PushMagicWord (void) __attribute__ ((naked)) __attribute__ ((section (".init3"))); - -// 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"::); -} - -/* ------------------------------------------------------------------------ */ - -static inline void initForUsbConnectivity(void) { - usbInit(); - /* enforce USB re-enumerate: */ - usbDeviceDisconnect(); /* do this while interrupts are disabled */ - _delay_ms(500); - usbDeviceConnect(); - sei(); -} - -static inline void tiny85FlashInit(void) { - // check for erased first page (no bootloader interrupt vectors), add vectors if missing - // this needs to happen for usb communication to work later - essential to first run after bootloader - // being installed - - if(pgm_read_byte(RESET_VECTOR_OFFSET * 2+1) == 0xff) fillFlashWithVectors(); // write vectors if flash is empty - - // TODO: necessary to reset currentAddress? - currentAddress = 0; -} - -static inline void tiny85FlashWrites(void) { - _delay_us(2000); // TODO: why is this here? - it just adds pointless two level deep loops seems like? - // write page to flash, interrupts will be disabled for > 4.5ms including erase - - // TODO: Do we need this? Wouldn't the programmer always send full sized pages? - -#if SPM_PAGESIZE<256 - // Hack to reduce code size - if ((uchar)currentAddress % SPM_PAGESIZE) -#else - if (currentAddress % SPM_PAGESIZE) -#endif - { - // when we aren't perfectly aligned to a flash page boundary - fillFlashWithVectors(); // fill up the rest of the page with 0xFFFF (unprogrammed) bits - } else { - writeFlashPage(); // otherwise just write it - } -} - -// finishes up writing to the flash, including adding the tinyVector tables at the end of memory -// TODO: can this be simplified? EG: currentAddress = PROGMEM_SIZE; fillFlashWithVectors(); -// static inline void tiny85FinishWriting(void) { -// // make sure remainder of flash is erased and write checksum and application reset vectors -// if (didWriteSomething) { -// while (currentAddress < BOOTLOADER_ADDRESS) { -// fillFlashWithVectors(); -// } -// } -// } - -// reset system to a normal state and launch user program -static inline void leaveBootloader(void) { - _delay_ms(10); // removing delay causes USB errors - - //DBG1(0x01, 0, 0); - bootLoaderExit(); - cli(); - usbDeviceDisconnect(); /* do this while interrupts are disabled */ - - 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 - // *(uint8_t*)(RAMEND-1) = 0x00; - -#ifndef RESTORE_OSCCAL - // adjust clock to previous calibration value, so user program always starts with same calibration - // as when it was uploaded originally - // TODO: Test this and find out, do we need the +1 offset? - 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; // this should really be a gradual change, but maybe it's alright anyway? - // do the gradual change - failed to score extra free bytes anyway in 1.06 - - while (OSCCAL > stored_osc_calibration) OSCCAL--; - while (OSCCAL < stored_osc_calibration) OSCCAL++; - } -#endif - // jump to application reset vector at end of flash - asm volatile ("rjmp __vectors - 4"); -} - -int main(void) { - /* initialize */ - #ifdef RESTORE_OSCCAL - osccal_default = OSCCAL; - #endif - #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE - uint8_t prescaler_default = CLKPR; - #endif - - MCUSR=0; - wdt_disable(); /* main app may have enabled watchdog */ - tiny85FlashInit(); - bootLoaderInit(); - - - if (bootLoaderStartCondition()) { - #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 - - initForUsbConnectivity(); - do { - 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)) tiny85FlashWrites(); - -# if BOOTLOADER_CAN_EXIT - if (isEvent(EVENT_EXECUTE)) { // when host requests device run uploaded program - break; - } -# endif - - clearEvents(); - - } while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */ - } - - // 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 - - // slowly bring down OSCCAL to it's original value before launching in to user program - #ifdef RESTORE_OSCCAL - while (OSCCAL > osccal_default) { OSCCAL -= 1; } - #endif - leaveBootloader(); -} - -/* ------------------------------------------------------------------------ */ -- cgit v1.2.3