void StartSketch(void) { cli(); /* Undo TIMER1 setup and clear the count before running the sketch */ TIMSK1 = 0; TCCR1B = 0; // MAH 8/15/12 this clear is removed to save memory. Okay, it // introduces some inaccuracy in the timer in the sketch, but // not enough that it really matters. //TCNT1H = 0; // 16-bit write to TCNT1 requires high byte be written first //TCNT1L = 0; /* Relocate the interrupt vector table to the application section */ MCUCR = (1 << IVCE); MCUCR = 0; L_LED_OFF(); TX_LED_OFF(); RX_LED_OFF(); /* jump to beginning of application space */ __asm__ volatile("jmp 0x0000"); }
/** Configures all hardware required for the bootloader. */ void SetupHardware(void) { /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable(); /* Disable clock division */ clock_prescale_set(clock_div_1); /* Relocate the interrupt vector table to the bootloader section */ MCUCR = (1 << IVCE); MCUCR = (1 << IVSEL); LED_SETUP(); CPU_PRESCALE(0); L_LED_OFF(); TX_LED_OFF(); RX_LED_OFF(); /* Initialize TIMER1 to handle bootloader timeout and LED tasks. * With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz * Our chosen compare match generates an interrupt every 1 ms. * This interrupt is disabled selectively when doing memory reading, erasing, * or writing since SPM has tight timing requirements. */ OCR1AH = 0; OCR1AL = 250; TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match interrupt TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input /* Initialize USB Subsystem */ USB_Init(); }
//uint16_t ctr = 0; ISR(TIMER1_COMPA_vect, ISR_BLOCK) { /* Reset counter */ TCNT1H = 0; TCNT1L = 0; /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */ if (TxLEDPulse && !(--TxLEDPulse)) TX_LED_OFF(); if (RxLEDPulse && !(--RxLEDPulse)) RX_LED_OFF(); if (pgm_read_word(0) != 0xFFFF) Timeout++; }
ISR(TIMER1_COMPA_vect, ISR_BLOCK) { /* Reset counter */ TCNT1H = 0; TCNT1L = 0; /* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */ if (TxLEDPulse && !(--TxLEDPulse)) TX_LED_OFF(); if (RxLEDPulse && !(--RxLEDPulse)) RX_LED_OFF(); resetTimeout++; // Needed for the "short reset delay" mode- governs the time the board waits // for a second reset before loading the sketch. if (pgm_read_word(0) != 0xFFFF) Timeout++; }
// StartSketch() is called to clean up our mess before passing execution to the sketch. void StartSketch(void) { cli(); /* Undo TIMER1 setup and clear the count before running the sketch */ TIMSK1 = 0; TCCR1B = 0; /* Relocate the interrupt vector table to the application section */ MCUCR = (1 << IVCE); MCUCR = 0; L_LED_OFF(); TX_LED_OFF(); RX_LED_OFF(); /* jump to beginning of application space */ __asm__ volatile("jmp 0x0000"); }
void StartSketch(void) { CPU_PRESCALE(1); cli(); /* Undo TIMER1 setup and clear the count before running the sketch */ TIMSK1 = 0; TCCR1B = 0; TCNT1H = 0; // 16-bit write to TCNT1 requires high byte be written first TCNT1L = 0; /* Relocate the interrupt vector table to the application section */ MCUCR = (1 << IVCE); MCUCR = 0; L_LED_OFF(); TX_LED_OFF(); RX_LED_OFF(); /* jump to beginning of application space */ __asm__ volatile("jmp 0x0000"); }
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously * runs the bootloader processing routine until it times out or is instructed to exit. */ int main(void) { /* Save the value of the boot key memory before it is overwritten */ uint8_t bootKeyPtrVal = *bootKeyPtr; *bootKeyPtr = 0; /* Check the reason for the reset so we can act accordingly */ uint8_t mcusr_state = MCUSR; // store the initial state of the Status register MCUSR = 0; // clear all reset flags /* Watchdog may be configured with a 15 ms period so must disable it before going any further */ // MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why // do it twice right in a row? //wdt_disable(); /* Setup hardware required for the bootloader */ // MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the // timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in // the bootloader, there's no point spending the time initializing the USB. // SetupHardware(); wdt_disable(); // Disable clock division clock_prescale_set(clock_div_1); // Relocate the interrupt vector table to the bootloader section MCUCR = (1 << IVCE); MCUCR = (1 << IVSEL); LED_SETUP(); CPU_PRESCALE(0); L_LED_OFF(); TX_LED_OFF(); RX_LED_OFF(); // Initialize TIMER1 to handle bootloader timeout and LED tasks. // With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz // Our chosen compare match generates an interrupt every 1 ms. // This interrupt is disabled selectively when doing memory reading, erasing, // or writing since SPM has tight timing requirements. OCR1AH = 0; OCR1AL = 250; TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match interrupt TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input // MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory. if (pgm_read_word(0) != 0xFFFF) sketchPresent = true; // MAH 8/15/12- quite a bit changed in this section- let's just pretend nothing has been reserved // and all comments throughout are from me. // First case: external reset, bootKey NOT in memory. We'll put the bootKey in memory, then spin // our wheels for about 750ms, then proceed to the sketch, if there is one. If, during that 750ms, // another external reset occurs, on the next pass through this decision tree, execution will fall // through to the bootloader. if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) { *bootKeyPtr = bootKey; sei(); while (RunBootloader) { if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) RunBootloader = false; } cli(); *bootKeyPtr = 0; RunBootloader = true; if (sketchPresent) StartSketch(); } // On a power-on reset, we ALWAYS want to go to the sketch. If there is one. else if ( (mcusr_state & (1<<PORF)) && sketchPresent) { StartSketch(); } // On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just // go straight to the sketch. else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) { // If it looks like an "accidental" watchdog reset then start the sketch. StartSketch(); } // END ALL COMMENTS ON THIS SECTION FROM MAH. /* Initialize USB Subsystem */ USB_Init(); /* Enable global interrupts so that the USB stack can function */ sei(); Timeout = 0; while (RunBootloader) { CDC_Task(); USB_USBTask(); /* Time out and start the sketch if one is present */ if (Timeout > TIMEOUT_PERIOD) RunBootloader = false; // MAH 8/15/12- This used to be a function call- inlining it saves a few bytes. LLEDPulse++; uint8_t p = LLEDPulse >> 8; if (p > 127) p = 254-p; p += p; if (((uint8_t)LLEDPulse) > p) L_LED_OFF(); else L_LED_ON(); } /* Disconnect from the host - USB interface will be reset later along with the AVR */ USB_Detach(); /* Jump to beginning of application space to run the sketch - do not reset */ StartSketch(); }
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously * runs the bootloader processing routine until it times out or is instructed to exit. */ int main(void) { /* Save the value of the boot key memory before it is overwritten */ uint8_t bootKeyPtrVal = *bootKeyPtr; *bootKeyPtr = 0; /* Check the reason for the reset so we can act accordingly */ uint8_t mcusr_state = MCUSR; // store the initial state of the Status register MCUSR = 0; // clear all reset flags /* Watchdog may be configured with a 15 ms period so must disable it before going any further */ // MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why // do it twice right in a row? //wdt_disable(); /* Setup hardware required for the bootloader */ // MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the // timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in // the bootloader, there's no point spending the time initializing the USB. // SetupHardware(); wdt_disable(); // Disable clock division clock_prescale_set(clock_div_1); // Relocate the interrupt vector table to the bootloader section MCUCR = (1 << IVCE); MCUCR = (1 << IVSEL); LED_SETUP(); CPU_PRESCALE(0); L_LED_OFF(); TX_LED_OFF(); RX_LED_OFF(); // Initialize TIMER1 to handle bootloader timeout and LED tasks. // With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz // Our chosen compare match generates an interrupt every 1 ms. // This interrupt is disabled selectively when doing memory reading, erasing, // or writing since SPM has tight timing requirements. OCR1AH = 0; OCR1AL = 250; TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match interrupt TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input // MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory. if (pgm_read_word(0) != 0xFFFF) sketchPresent = true; // MAH 26 Oct 2012- The "bootload or not?" section has been modified since the code released // with Arduino 1.0.1. The simplest modification is the replacement of equivalence checks on // the reset bits with masked checks, so if more than one reset occurs before the register is // checked, the check doesn't fail and fall through to the bootloader unnecessarily. // The second, more in depth modification addresses behavior after an external reset (i.e., // user pushes the reset button). The Leonardo treats all external resets as requests to // re-enter the bootloader and wait for code to be loaded. It remains in bootloader mode for // 8 seconds before continuing on to the sketch (if one is present). By defining RESET_DELAY // equal to 1, this behavior will persist. // However, if RESET_DELAY is defined to 0, the reset timeout before loading the sketch drops // to 750ms. If, during that 750ms, another external reset occurs, THEN an 8-second delay // in the bootloader will occur. // This is the "no-8-second-delay" code. If this is the first time through the loop, we // don't expect to see the bootKey in memory. if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) { *bootKeyPtr = bootKey; // Put the bootKey in memory so if we get back to this // point again, we know to jump into the bootloader sei(); // Enable interrupts, so we can use timer1 to track our time in the bootloader while (RunBootloader) { if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) // resetTimeout is getting incremeted RunBootloader = false; // in the timer1 ISR. } // If we make it past that while loop, it's sketch loading time! *bootKeyPtr = 0; // clear out the bootKey; from now on, we want to treat a reset like // a normal reset. cli(); // Disable interrupts, in case no sketch is present. RunBootloader = true; // We want to hang out in the bootloader if no sketch is present. if (sketchPresent) StartSketch(); // If a sketch is present, go! Otherwise, wait around // in the bootloader until one is uploaded. } // On a power-on reset, we ALWAYS want to go to the sketch. If there is one. // This is a place where the old code had an equivalence and now there is a mask. else if ( (mcusr_state & (1<<PORF)) && sketchPresent) { StartSketch(); } // On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just // go straight to the sketch. // This is a place where the old code had an equivalence and now there is a mask. else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) { // If it looks like an "accidental" watchdog reset then start the sketch. StartSketch(); } /* Initialize USB Subsystem */ USB_Init(); /* Enable global interrupts so that the USB stack can function */ sei(); Timeout = 0; while (RunBootloader) { CDC_Task(); USB_USBTask(); /* Time out and start the sketch if one is present */ if (Timeout > TIMEOUT_PERIOD) RunBootloader = false; // MAH 8/15/12- This used to be a function call- inlining it saves a few bytes. LLEDPulse++; uint8_t p = LLEDPulse >> 8; if (p > 127) p = 254-p; p += p; if (((uint8_t)LLEDPulse) > p) L_LED_OFF(); else L_LED_ON(); } /* Disconnect from the host - USB interface will be reset later along with the AVR */ USB_Detach(); /* Jump to beginning of application space to run the sketch - do not reset */ StartSketch(); }
static int USB_ISR(int irq, void* data) { DWORD isr; USB_Device *usb; usb = (USB_Device *)data; if ((isr = io_inpdw(usb->ISR)) != 0x00L) { // Bus reset interrupt if (isr & IBRST) { io_outpdw(usb->ISR, IALL); usb_Reset(usb); } // SOF interrupt if (isr & ISOF) { io_outpdw(usb->ISR, ISOF); if (usb->ReadySetAddr == true) { io_outpb(usb->DAR, usb->DevAddr | 0x80); usb->ReadySetAddr = false; } #ifdef DMP_86DUINO_MODE if(tx_led_count && !(--tx_led_count)) TX_LED_OFF(); if(rx_led_count && !(--rx_led_count)) RX_LED_OFF(); #endif } // Suspend interrupt if (isr & ISUSP) { io_outpdw(usb->ISR, ISUSP); usb->IsSet = 0; usb->state = USB_DEV_POWERED; #ifdef DMP_86DUINO_MODE TX_LED_OFF(); RX_LED_OFF(); #endif } // Resume interrupt if (isr & IRESM) { io_outpdw(usb->ISR, IRESM); } // System error interrupt if (isr & SYSERR) { io_outpdw(usb->ISR, SYSERR); } // EP0 Setup interrupt if (isr & IEP0SETUP) { io_outpdw(usb->ISR, IEP0SETUP); EP0_SetupHandler(usb); } // EP0 RX interrupt if (isr & IEP0RX) { io_outpdw(usb->ISR, IEP0RX); EP0_OutHandler(usb); } // EP0 TX interrupt if (isr & IEP0TX) { io_outpdw(usb->ISR, IEP0TX); EP0_InHandler(usb); } // EP1 RX interrupt if (isr & IEP1RX) { io_outpdw(usb->ISR, IEP1RX); } // EP1 TX interrupt if (isr & IEP1TX) { io_outpdw(usb->ISR, IEP1TX); EP1_InHandler(usb); } // EP2 RX interrupt if (isr & IEP2RX) { io_outpdw(usb->ISR, IEP2RX); EP2_OutHandler(usb); } // EP2 TX interrupt if (isr & IEP2TX) { io_outpdw(usb->ISR, IEP2TX); usb->bulk_in_transmitting = false; EP2_InHandler(usb); } // EP3 RX interrupt if (isr & IEP3RX) { io_outpdw(usb->ISR, IEP3RX); } // EP3 TX interrupt if (isr & IEP3TX) { io_outpdw(usb->ISR, IEP3TX); } #ifdef DMP_86DUINO_MODE // the below behavier is only for compatible of Arduino Leonado (windows) if(usb->ling_coding.dwDTERate == 1200 && (usb->control_line_state & 0x01) == 0) { io_outpb(usb_on_off_data, io_inpb(usb_on_off_data) | (1 << usb_on_off_pin)); io_outpb(0xf21A, 0x5a); // write soft reset key io_outpb(0x64, 0xfe); // reboot } #endif } else return ISR_NONE; return ISR_HANDLED; }
DMPAPI(void *) CreateUSBDevice(void) { USB_Device *usb = NULL; if ((usb = (USB_Device *)ker_Malloc(sizeof(USB_Device))) == NULL) return NULL; if (io_Init() == false) { err_print((char*)"%s: Init IO lib error!!\n", __FUNCTION__); ker_Mfree((void *)usb); return NULL; } usb->addr = vx86_GetUSBDevAddr(); usb->nIRQ = vx86_GetUSBDevIRQ(); if (usb->addr == 0x0000 || usb->nIRQ == 0) { io_Close(); ker_Mfree((void *)usb); return NULL; } usb->DevAddr = 0x00; usb->ReadySetAddr = false; usb->state = USB_DEV_NOT_ATTACHED; usb->stall = false; usb->InUse = 0; usb->IsSet = 0; usb->setup_in_handled = false; usb->setup_out_handled = false; usb->bulk_in_transmitting = false; usb->TimeOut = USB_NO_TIMEOUT; usb->InDataPtr = NULL; usb->OutDataPtr = NULL; usb->InDataSize = 0; usb->OutDataSize = 0; if ((usb->rcvd = CreateQueue(RX_QUEUE_SIZE)) == NULL) goto CREATE_RX_QUEUE_FAIL; if ((usb->xmit = CreateQueue(TX_QUEUE_SIZE)) == NULL) goto CREATE_TX_QUEUE_FAIL; usb->Setup.bmRequestType = 0; usb->Setup.bRequest = 0; usb->Setup.wValue.Value = 0; usb->Setup.wIndex.Value = 0; usb->Setup.wLength = 0; usb->ling_coding.dwDTERate = 0; usb->ling_coding.bCharFormat = 0; usb->ling_coding.bParityType = 0; usb->ling_coding.bDataBits = 0; usb->control_line_state = 0; usb->serial_state = 0; usb->DAR = usb->addr + 0x00; usb->CFR = usb->addr + 0x02; usb->FNR = usb->addr + 0x06; usb->IER = usb->addr + 0x08; usb->ISR = usb->addr + 0x0C; usb->TMR = usb->addr + 0x68; memset((Endpoint *)usb->EP, 0, sizeof(usb->EP)); usb->EP[0].CtrlTR = usb->addr + 0x10; usb->EP[1].OutTR = usb->addr + 0x12; usb->EP[1].InTR = usb->addr + 0x14; usb->EP[2].OutTR = usb->addr + 0x16; usb->EP[2].InTR = usb->addr + 0x18; usb->EP[3].OutTR = usb->addr + 0x1A; usb->EP[3].InTR = usb->addr + 0x1C; usb->EP[0].SetupDLR = usb->addr + 0x20; usb->EP[0].OutDLR = usb->addr + 0x24; usb->EP[0].InDLR = usb->addr + 0x28; usb->EP[1].OutDLR = usb->addr + 0x2C; usb->EP[1].InDLR = usb->addr + 0x30; usb->EP[2].OutDLR = usb->addr + 0x34; usb->EP[2].InDLR = usb->addr + 0x38; usb->EP[3].OutDLR = usb->addr + 0x3C; usb->EP[3].InDLR = usb->addr + 0x40; usb->EP[0].SetupDSR = usb->addr + 0x44; usb->EP[0].OutDSR = usb->addr + 0x48; usb->EP[0].InDSR = usb->addr + 0x4C; usb->EP[1].OutDSR = usb->addr + 0x50; usb->EP[1].InDSR = usb->addr + 0x54; usb->EP[2].OutDSR = usb->addr + 0x58; usb->EP[2].InDSR = usb->addr + 0x5C; usb->EP[3].OutDSR = usb->addr + 0x60; usb->EP[3].InDSR = usb->addr + 0x64; #ifdef DMP_86DUINO_MODE set_gpio_config_addr(GPIO_CONFIG_ADDR); // for 86duino set_tx_led(7, 2); set_rx_led(7, 3); TX_LED_OFF(); RX_LED_OFF(); #endif return (void *)usb; CREATE_TX_QUEUE_FAIL: DestoryQueue(usb->rcvd); CREATE_RX_QUEUE_FAIL: io_Close(); ker_Mfree((void *)usb); return NULL; }