diff options
| author | Jenna Fox <a@creativepony.com> | 2012-09-23 22:37:45 +1000 | 
|---|---|---|
| committer | Jenna Fox <a@creativepony.com> | 2012-09-23 22:37:45 +1000 | 
| commit | 409e6097d172f4027b8e541128ef3e89cbaed027 (patch) | |
| tree | a5602811db452b7f3da009b5f39ef13d8cefdb93 /firmware/main.c | |
| parent | 28b65b95cc1f47a6353e6ede5a4dbee6a36a76e3 (diff) | |
| download | micronucleus-409e6097d172f4027b8e541128ef3e89cbaed027.tar.gz micronucleus-409e6097d172f4027b8e541128ef3e89cbaed027.tar.bz2 micronucleus-409e6097d172f4027b8e541128ef3e89cbaed027.zip | |
very close to it working - it uploads some, but the words uploaded are spaced out with 0xFF's between each word :S
Diffstat (limited to 'firmware/main.c')
| -rw-r--r-- | firmware/main.c | 150 | 
1 files changed, 74 insertions, 76 deletions
| diff --git a/firmware/main.c b/firmware/main.c index d4fc842..5f15353 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -22,8 +22,28 @@ static void leaveBootloader() __attribute__((__noreturn__));  #include "bootloaderconfig.h"  #include "usbdrv/usbdrv.c" -#include "libs-device/osccal.c" +#define UBOOT_VERSION 1 +// how many milliseconds should host wait till it sends another write? +// this needs to be above 9, but 20 is only sensible for testing +#define UBOOT_WRITE_SLEEP 20 + +// set a pin on DDRB to be an input or an output - i.e. becomeOutput(pin(3)); +#define bit(number) _BV(number) +#define pin(number) _BV(number) +#define inputs(pinmap) DDRB &= ~(pinmap) +#define outputs(pinmap) DDRB |= (pinmap) + +// turn some pins on or off +#define pinsOn(pinmap) PORTB |= (pinmap) +#define pinsOff(pinmap) PORTB &= ~(pinmap) +#define pinsToggle(pinmap) PORTB ^= pinmap + +// turn a single pin on or off +#define pinOn(pin) pinsOn(bit(pin)) +#define pinOff(pin) pinsOff(bit(pin)) +// TODO: Should be called pinToggle +#define toggle(pin) pinsToggle(bit(pin))  /* ------------------------------------------------------------------------ */ @@ -75,39 +95,19 @@ static uchar events = 0; // bitmap of events to run  #define isEvent(event)   (events & (event))  #define clearEvents()    events = 0 -// state for uploading process -static uchar state = 0; -#define STATE_UNDEFINED 0 -#define STATE_NEW_PAGE 1 -#define STATE_CONTINUING_PAGE 2 +static uchar writeLength;  // becomes 1 when some programming happened  // lets leaveBootloader know if needs to finish up the programming  static uchar didWriteSomething = 0; -static uint16_t         vectorTemp[2]; -static addr_t  currentAddress; /* in bytes */ -PROGMEM char usbHidReportDescriptor[33] = { -    0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop) -    0x09, 0x01,                    // USAGE (Vendor Usage 1) -    0xa1, 0x01,                    // COLLECTION (Application) -    0x15, 0x00,                    //   LOGICAL_MINIMUM (0) -    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255) -    0x75, 0x08,                    //   REPORT_SIZE (8) -    0x85, 0x01,                    //   REPORT_ID (1) -    0x95, 0x06,                    //   REPORT_COUNT (6) -    0x09, 0x00,                    //   USAGE (Undefined) -    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf) -    0x85, 0x02,                    //   REPORT_ID (2) -    0x95, 0x83,                    //   REPORT_COUNT (131) -    0x09, 0x00,                    //   USAGE (Undefined) -    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf) -    0xc0                           // END_COLLECTION -}; + +static uint16_t         vectorTemp[2]; +static addr_t  currentAddress; /* in bytes */  /* ------------------------------------------------------------------------ */ @@ -153,6 +153,7 @@ static void writeWordToPageBuffer(uint16_t data) {          data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET;      } +          // clear page buffer as a precaution before filling the buffer on the first page      // TODO: maybe clear on the first byte of every page?      if (currentAddress == 0x0000) __boot_page_fill_clear(); @@ -164,7 +165,7 @@ static void writeWordToPageBuffer(uint16_t data) {  	// 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) { +    if ((pgm_read_word(currentAddress) & data) != data) {          fireEvent(EVENT_PAGE_NEEDS_ERASE);      } @@ -192,7 +193,6 @@ static inline __attribute__((noreturn)) void leaveBootloader(void) {  	// make sure remainder of flash is erased and write checksum and application reset vectors  	if (didWriteSomething) { -    //if(appWriteComplete) {          while (currentAddress < BOOTLOADER_ADDRESS) {              fillFlashWithVectors();          } @@ -209,58 +209,38 @@ static inline __attribute__((noreturn)) void leaveBootloader(void) {  /* ------------------------------------------------------------------------ */  static uchar usbFunctionSetup(uchar data[8]) { -   usbRequest_t *rq = (void *)data; -   static uchar replyBuffer[7] = { // TODO: Adjust this buffer size when trimming off those two useless bytes -      1, // report ID -      SPM_PAGESIZE & 0xff, -      0, // also completely useless on tiny85's - they'll never have more than 64 byte pagesize -      ((uint)PROGMEM_SIZE) & 0xff, -      (((uint)PROGMEM_SIZE) >> 8) & 0xff, -      0, -      0 // TODO: remove these last ones that don't do anything for these small chips ? -   }; - -   if (rq->bRequest == USBRQ_HID_SET_REPORT) { -      if (rq->wValue.bytes[0] == 2) { -         //offset = 0; -         state = STATE_NEW_PAGE; -         return USB_NO_MSG; -      } +    usbRequest_t *rq = (void *)data; +    static uchar replyBuffer[5] = { // TODO: Adjust this buffer size when trimming off those two useless bytes +        UBOOT_VERSION, +        (((uint)PROGMEM_SIZE) >> 8) & 0xff, +        ((uint)PROGMEM_SIZE) & 0xff, +        SPM_PAGESIZE, +        UBOOT_WRITE_SLEEP +    }; +     +    if (rq->bRequest == 0) { // get device info +        usbMsgPtr = replyBuffer; +        return 5; +       +    } else if (rq->bRequest == 1) { // write page +        pinOff(0); +        writeLength = rq->wValue.word; +        currentAddress = rq->wIndex.word; +        return 0xFF; // magical? IDK - USBaspLoader-tiny85 returns this and it works so whatever. +         +    } else { // exit bootloader  #if BOOTLOADER_CAN_EXIT -      else { -         fireEvent(EVENT_EXIT_BOOTLOADER); -      } +        fireEvent(EVENT_EXIT_BOOTLOADER);  #endif -   } else if (rq->bRequest == USBRQ_HID_GET_REPORT) { -      usbMsgPtr = replyBuffer; -      return 7; // TODO: Adjust this to match replyBuffer's size after trimming two useless bytes -   } -   return 0; +    } +     +    return 0;  }  // read in a page over usb, and write it in to the flash write buffer  static uchar usbFunctionWrite(uchar *data, uchar length) { -    union { -        addr_t  l; -        uint    s[sizeof(addr_t)/2]; -        uchar   c[sizeof(addr_t)]; -    } address; -     -    // if we are the first functionWrite for this page, update our write address -    if (state == STATE_NEW_PAGE) { -        address.l = currentAddress; -         -        //DBG1(0x30, data, 3); -        address.c[0] = data[1]; -        address.c[1] = data[2]; -        data += 4; -        length -= 4; -         -        currentAddress = address.l; -         -        state = STATE_CONTINUING_PAGE; -    } +    writeLength -= length;      do {          // remember vectors or the tinyvector table  @@ -284,8 +264,9 @@ static uchar usbFunctionWrite(uchar *data, uchar length) {          length -= 2;      } while(length); +    // TODO: Isn't this always last?      // if we have now reached another page boundary, we're done -    uchar isLast = !(currentAddress % SPM_PAGESIZE == 0); +    uchar isLast = (writeLength == 0);      if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page      return isLast; // let vusb know we're done with this request @@ -314,6 +295,20 @@ static inline void initForUsbConnectivity(void) {      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_word(RESET_VECTOR_OFFSET * 2) != 0xC000 + (BOOTLOADER_ADDRESS/2) - 1 || +            pgm_read_word(USBPLUS_VECTOR_OFFSET * 2) != 0xC000 + (BOOTLOADER_ADDRESS/2) - 1) { + +        fillFlashWithVectors(); +    } + +    // TODO: necessary to reset currentAddress? +    currentAddress = 0; +} +  static inline void tiny85FlashWrites(void) {      _delay_ms(2); // TODO: why is this here?      // write page to flash, interrupts will be disabled for > 4.5ms including erase @@ -330,13 +325,16 @@ int __attribute__((noreturn)) main(void) {      /* initialize  */      wdt_disable();      /* main app may have enabled watchdog */ -    //tiny85FlashInit(); +    tiny85FlashInit();      currentAddress = 0; // TODO: think about if this is necessary      bootLoaderInit();      //odDebugInit();      ////DBG1(0x00, 0, 0); - - +     +    outputs(pin(0) | pin(1)); +    pinOn(0); +    pinOff(1); +          if (bootLoaderCondition()){          initForUsbConnectivity();          do { | 
