/* main program starts here */ int main(void) { uint8_t ch; /* * Making these local and in registers prevents the need for initializing * them, and also saves space because code no longer stores to memory. * (initializing address keeps the compiler happy, but isn't really * necessary, and uses 4 bytes of flash.) */ register uint16_t address = 0; register uint8_t length; // After the zero init loop, this is the first code to run. // // This code makes the following assumptions: // No interrupts will execute // SP points to RAMEND // r1 contains zero // // If not, uncomment the following instructions: // cli(); asm volatile ("clr __zero_reg__"); #ifdef __AVR_ATmega8__ SP=RAMEND; // This is done by hardware reset #endif // Adaboot no-wait mod ch = MCUSR; MCUSR = 0; if (!(ch & _BV(EXTRF))) appStart(); #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 #endif #ifndef SOFT_UART #ifdef __AVR_ATmega8__ UCSRA = _BV(U2X); //Double speed mode USART UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #else UCSR0A = _BV(U2X0); //Double speed mode USART0 UCSR0B = _BV(RXEN0) | _BV(TXEN0); UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #endif #endif // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_1S); /* Set LED pin as output */ LED_DDR |= _BV(LED); #ifdef SOFT_UART /* Set TX pin as output */ UART_DDR |= _BV(UART_TX_BIT); #endif #if LED_START_FLASHES > 0 /* Flash onboard LED to signal entering of bootloader */ flash_led(LED_START_FLASHES * 2); #endif /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { unsigned char which = getch(); verifySpace(); if (which == 0x82) { /* * Send optiboot version as "minor SW version" */ putch(OPTIBOOT_MINVER); } else if (which == 0x81) { putch(OPTIBOOT_MAJVER); } else { /* * GET PARAMETER returns a generic 0x03 reply for * other parameters - enough to keep Avrdude happy */ putch(0x03); } } else if(ch == STK_SET_DEVICE) { // SET DEVICE is ignored getNch(20); } else if(ch == STK_SET_DEVICE_EXT) { // SET DEVICE EXT is ignored getNch(5); } else if(ch == STK_LOAD_ADDRESS) { // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); newAddress = (newAddress & 0xff) | (getch() << 8); #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address address = newAddress; verifySpace(); } else if(ch == STK_UNIVERSAL) { // UNIVERSAL command is ignored getNch(4); putch(0x00); } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getch(); /* getlen() */ length = getch(); getch(); // If we are in RWW section, immediately start page erase if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); while (--length); // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); // Read command terminator, start reply verifySpace(); // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); #ifdef VIRTUAL_BOOT_PARTITION if ((uint16_t)(void*)address == 0) { // This is the reset vector page. We need to live-patch the code so the // bootloader runs. // // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1]<<8); rstVect = vect; wdtVect = buff[8] | (buff[9]<<8); vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. buff[8] = vect & 0xff; buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0x7f; buff[1] = 0xce; // rjmp 0x1d00 instruction } #endif // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; __boot_page_fill_short((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer __boot_page_write_short((uint16_t)(void*)address); boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); #endif }
/* main program starts here */ int main(void) { // After the zero init loop, this is the first code to run. // // This code makes the following assumptions: // No interrupts will execute // SP points to RAMEND // r1 contains zero // // If not, uncomment the following instructions: cli(); SP=RAMEND; // This is done by hardware reset asm volatile ("clr __zero_reg__"); uint8_t ch; // Adaboot no-wait mod ch = MCUSR; MCUSR = 0; if (!(ch & _BV(EXTRF))) appStart(); // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_OFF); DDRD = 0; PORTD = 0; PORTC = 0; DDRC = C3_WR | C2_RD; /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); putch(0x03); } else if(ch == STK_SET_DEVICE) { // SET DEVICE is ignored getNch(20); } else if(ch == STK_SET_DEVICE_EXT) { // SET DEVICE EXT is ignored getNch(5); } else if(ch == STK_LOAD_ADDRESS) { // LOAD ADDRESS address = getch(); address = (address & 0xff) | (getch() << 8); address += address; // Convert from word address to byte address verifySpace(); } else if(ch == STK_UNIVERSAL) { // UNIVERSAL command is ignored getNch(4); putch(0x00); } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint16_t addrPtr; getLen(); // Immediately start page erase - this will 4.5ms boot_page_erase((uint16_t)(void*)address); // While that is going on, read in page contents bufPtr = buff; do *bufPtr++ = getch(); while (--length); // Read command terminator, start reply verifySpace(); // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; boot_page_fill((uint16_t)(void*)addrPtr,a); addrPtr += 2; } while (--ch); // Write from programming buffer boot_page_write((uint16_t)(void*)address); boot_spm_busy_wait(); // Reenable read access to flash boot_rww_enable(); } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { // READ PAGE - we only read flash getLen(); verifySpace(); do putch(pgm_read_byte_near(address++)); while (--length); } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { // READ SIGN - return what Avrdude wants to hear verifySpace(); putch(SIGNATURE_0); putch(SIGNATURE_1); putch(SIGNATURE_2); } else if (ch == 'Q') { // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); } putch(STK_OK); } }
uint8_t proccessCommand() { uint8_t ch; ch = getch(); if(ch == STK_GET_PARAMETER) { unsigned char which = getch(); verifySpace(); if(which == 0x82) { /* * Send tftpboot version as "minor SW version" */ putch(ARIADNE_MINVER); } else if(which == 0x81) { putch(ARIADNE_MAJVER); } else { /* * GET PARAMETER returns a generic 0x03 reply for * other parameters - enough to keep Avrdude happy */ putch(0x03); } } else if(ch == STK_SET_DEVICE) { // SET DEVICE is ignored getNch(20); } else if(ch == STK_SET_DEVICE_EXT) { // SET DEVICE EXT is ignored getNch(4); } else if(ch == STK_LOAD_ADDRESS) { // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); newAddress = (newAddress & 0xff) | (getch() << 8); #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address address = newAddress; verifySpace(); } else if(ch == STK_UNIVERSAL) { // UNIVERSAL command is ignored getNch(4); putch(0x00); } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { // This should probably go somewhere but I don't yet know it's place //eeprom_write_byte(EEPROM_IMG_STAT, EEPROM_IMG_BAD_VALUE); // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t buff[256]; uint8_t* bufPtr; uint16_t addrPtr; getch(); /* getlen() */ length = getch(); getch(); // If we are in RWW section, immediately start page erase if(address < NRWWSTART) boot_page_erase((uint16_t)(void*)address); // While that is going on, read in page contents bufPtr = buff; do* bufPtr++ = getch(); while(--length); // If we are in NRWW section, page erase has to be delayed until now. // Todo: Take RAMPZ into account if(address >= NRWWSTART) boot_page_erase((uint16_t)(void*)address); // Read command terminator, start reply verifySpace(); // If only a partial page is to be programmed, the erase might not be complete. // So check that here boot_spm_busy_wait(); // Copy buffer into programming buffer bufPtr = buff; addrPtr = (uint16_t)(void*)address; ch = SPM_PAGESIZE / 2; do { uint16_t a; a = *bufPtr++; a |= (*bufPtr++) << 8; boot_page_fill((uint16_t)(void*)addrPtr, a); addrPtr += 2; } while(--ch); // Write from programming buffer boot_page_write((uint16_t)(void*)address); boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash boot_rww_enable(); #endif } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { // READ PAGE - we only read flash getch(); /* getlen() */ length = getch(); getch(); verifySpace(); #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560) // do putch(pgm_read_byte_near(address++)); // while (--length); do { uint8_t result; __asm__("elpm %0,Z\n":"=r"(result):"z"(address)); putch(result); address++; } while(--length); #else do putch(pgm_read_byte_near(address++)); while(--length); #endif }
/* main program starts here */ int main(void) { uint8_t ch; uint16_t pmask; /* * Making these local and in registers prevents the need for initializing * them, and also saves space because code no longer stores to memory. * (initializing address keeps the compiler happy, but isn't really * necessary, and uses 4 bytes of flash.) */ register uint16_t address = 0; register uint16_t length; // After the zero init loop, this is the first code to run. // // This code makes the following assumptions: // No interrupts will execute // SP points to RAMEND // r1 contains zero // // If not, uncomment the following instructions: // cli(); asm volatile ("clr __zero_reg__"); SP=RAMEND; // This is done by hardware reset // Adaboot no-wait mod ch = MCUSR; MCUSR = 0; if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF))) appStart(ch); // WDT clock by 32KHz IRC PMCR = 0x80; PMCR = 0x93; #if EXT_OSC == 1 #warning Using external crystal now!!! // for case of 16MHz crystall, no clock divider PMCR = 0x80; PMCR = 0x97; for(ch = 0xf; ch > 0; --ch); PMCR = 0x80; PMCR = 0xb7; CLKPR = 0x80; CLKPR = 0x00; // external crsyall flag VDTCR = 0x80; VDTCR = 0x4C; #else // system clock: 16MHz system clock CLKPR = 0x80; CLKPR = 0x01; #endif #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 #endif #ifndef SOFT_UART #if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) UCSRA = _BV(U2X); //Double speed mode USART UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #else //UART_SRA = _BV(U2X0); //Double speed mode USART0 ch = PMXCR | 0x03; PMXCR = 0x80; PMXCR = ch; UART_SRB = _BV(RXEN0) | _BV(TXEN0); UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); UART_SRL = (uint8_t)( F_CPU / (BAUD_RATE * 16L) - 1 ); //UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #endif #endif // Set up watchdog to trigger after 500ms watchdogConfig(WATCHDOG_16MS); #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) /* Set LED pin as output */ LED_DDR |= _BV(LED); #endif #ifdef SOFT_UART /* Set TX pin as output */ UART_DDR |= _BV(UART_TX_BIT); #endif #if LED_START_FLASHES > 0 /* Flash onboard LED to signal entering of bootloader */ flash_led(LED_START_FLASHES * 2); #endif // page erased flag pmask = 0; /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); if(ch == STK_GET_PARAMETER) { unsigned char which = getch(); verifySpace(); if (which == 0x82) { /* * Send optiboot version as "minor SW version" */ putch(OPTIBOOT_MINVER); } else if (which == 0x81) { putch(OPTIBOOT_MAJVER); } else { /* * GET PARAMETER returns a generic 0x03 reply for * other parameters - enough to keep Avrdude happy */ putch(0x03); } } else if(ch == STK_SET_DEVICE) { // SET DEVICE is ignored getNch(20); } else if(ch == STK_SET_DEVICE_EXT) { // SET DEVICE EXT is ignored getNch(5); } else if(ch == STK_LOAD_ADDRESS) { // LOAD ADDRESS uint16_t newAddress; newAddress = getch(); newAddress = (newAddress & 0xff) | (getch() << 8); #ifdef RAMPZ // Transfer top bit to RAMPZ RAMPZ = (newAddress & 0x8000) ? 1 : 0; #endif newAddress += newAddress; // Convert from word address to byte address address = newAddress; verifySpace(); } else if(ch == STK_UNIVERSAL) { // UNIVERSAL command is ignored getNch(4); putch(0x00); } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t *bufPtr; uint8_t bval; uint16_t len; length = (uint16_t)getch() << 8; /* getlen() */ length += getch(); bval = getch(); // If we are in RWW section, immediately start page erase //if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); // While that is going on, read in page contents bufPtr = buff; len = length; do *bufPtr++ = getch(); while (--len); EEARL = 0; EEARH = address >> 8; ch = EEARH >> 2; // 1KB page size if((0 == (pmask & (((uint16_t)1 << ch)))) && bval == 'F') { pmask |= ((uint16_t)1 << ch); // do page erase here EECR = 0x94; EECR = 0x92; asm("nop"); asm("nop"); } // Read command terminator, start reply verifySpace(); // If only a partial page is to be programmed, the erase might not be complete. // So check that here //boot_spm_busy_wait(); if (bval == 'E') { for(len = 0; len < length; len++) { if(address >= 512) break; EEARL = address++; EEARH = address >> 8; EEDR = buff[len]; EECR = 0x04; EECR = 0x02; } } else { #ifdef VIRTUAL_BOOT_PARTITION if ((uint16_t)(void*)address == 0) { // This is the reset vector page. We need to live-patch the code so the // bootloader runs. // // Move RESET vector to WDT vector uint16_t vect = buff[0] | (buff[1] << 8); rstVect = vect; wdtVect = buff[8] | (buff[9] << 8); vect -= 4; buff[8] = vect & 0xff; buff[9] = vect >> 8; // Add jump to bootloader at RESET vector buff[0] = 0xff; buff[1] = 0xcd; // jmp } #endif // Write from programming buffer bufPtr = buff; for(length = 0; length < SPM_PAGESIZE; length+=2) { EEARL = 0; EEDR = *bufPtr++; EEARL = 1; EEDR = *bufPtr++; EEARL = (address + length) & 0xff; EECR = 0xA4; EECR = 0xA2; } }
/* main program starts here */ void optiboot(void) { uint8_t ch; /* Forever loop */ for (;;) { /* get character from UART */ ch = getch(); uint8_t reply = STK_OK; if(ch == STK_GET_PARAMETER) { // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy getNch(1); putch(0x03); } else if(ch == STK_SET_DEVICE) { // SET DEVICE is ignored getNch(20); } else if(ch == STK_SET_DEVICE_EXT) { // SET DEVICE EXT is ignored getNch(5); } else if(ch == STK_LOAD_ADDRESS) { // LOAD ADDRESS uint16_t address = getch(); address = (address & 0xff) | (getch() << 8); verifySpace(); // address is in words right now if (address % (SPM_PAGESIZE / 2)) { reply = STK_FAILED; } else { // Convert to page address page = address / (SPM_PAGESIZE / 2); } } else if(ch == STK_UNIVERSAL) { // UNIVERSAL command is ignored getNch(4); putch(0x00); } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { // PROGRAM PAGE uint8_t *bufPtr = buff; // we support flash programming only, not EEPROM if ((getLen() == 'E') || (length > SPM_PAGESIZE) || (page >= (CONFIG_BOOTLDR_START_ADDR / SPM_PAGESIZE))) { reply = STK_FAILED; } // Clear the buffer memset(buff, 0xff, sizeof(buff)); // Read in page contents do *bufPtr++ = getch(); while (--length); // Read command terminator, start reply verifySpace(); if (reply == STK_OK) { // Write the page stubboot_write_page(page, buff); } } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { // READ PAGE - we only read flash if (getLen() == 'E') { reply = STK_FAILED; } verifySpace(); #if (FLASHEND > USHRT_MAX) uint_farptr_t address = (uint_farptr_t)page * SPM_PAGESIZE; #else uint16_t address = page * SPM_PAGESIZE; #endif while (length--) { #if (FLASHEND > USHRT_MAX) putch(pgm_read_byte_far(address++)); #else putch(pgm_read_byte_near(address++)); #endif } } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { // READ SIGN - return what Avrdude wants to hear verifySpace(); putch(SIGNATURE_0); putch(SIGNATURE_1); putch(SIGNATURE_2); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); } putch(reply); } }
/* main program starts here */ void bootloader(void) { #ifdef ADABOOT char firstcharzero=0; #endif uint8_t ch,ch2; uint16_t w; error_count = 0; initSerial(); /* forever loop */ for (;;) { bitTgl(UsbLed); if (error_count >= MAX_ERROR_COUNT) // Probably normal serial traffic is causing this. { releaseChipAccess(); return; //initSerial(); //error_count = 0; } /* get character from UART */ //bitSet(BluLed); ch = bootldrgetch(); if (ch ==0) { releaseChipAccess(); return; } //bitClr(BluLed); //blinkLed(GrnLedId,100*mSec,1); /* A bunch of if...else if... gives smaller code than switch...case ! */ #if 0 //def ADABOOT // Hello is anyone home ? lady ada hack - BBR if(ch=='0') { firstcharzero = 1; // we got an appropriate bootloader instruction nothing_response(); } else if (firstcharzero == 0) { // the first character we got is not '0', lets bail! // autoreset via watchdog (sneaky!) // return(); } #else /* Hello is anyone home ? */ if(ch=='0') { nothing_response(); } #endif /* Request programmer ID */ /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */ /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */ else if(ch=='1') { if (bootldrgetch() == ' ') { putNch(pgmrId,9); } else { ++error_count; } } /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */ else if(ch=='@') { ch2 = bootldrgetch(); if (ch2>0x85) bootldrgetch(); nothing_response(); } /* AVR ISP/STK500 board requests */ /* Cmnd_STK_GET_PARAMETER 0x41 */ else if(ch=='A') { ch2 = bootldrgetch(); if(ch2==0x80) byte_response(HW_VER); // Hardware version else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56 else byte_response(0x00); // Covers various unnecessary responses we don't care about } /* Cmnd_STK_SET_DEVICE 0x42 Device Parameters DON'T CARE, DEVICE IS FIXED */ else if(ch=='B') { getNch(20); nothing_response(); } /* Cmnd_SET_DEVICE_EXT 0x45 */ else if(ch=='E') { getNch(5); nothing_response(); } /* P: Enter programming mode */ else if(ch=='P') { if (!initChipAccess(&devId[1])) { failed_response(); } else nothing_response(); } /* R: Erase device, don't care as we will erase one page at a time anyway. */ else if(ch=='R') { eraseDevice(); nothing_response(); } /* Leave programming mode */ else if(ch=='Q') { nothing_response(); delay(5*mSec); releaseChipAccess(); allDone(); return; #ifdef WATCHDOG_MODS assert(0); #endif } /* Set address, little endian. EEPROM in bytes, FLASH in words */ /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */ /* This might explain why little endian was used here, big endian used everywhere else. */ else if(ch=='U') { address.word = myget2LE(); //address.byte[0] = bootldrgetch(); //address.byte[1] = bootldrgetch(); nothing_response(); } /* Universal SPI programming command. Used for fuses and lock bits. */ else if(ch=='V') { unsigned char spicmdbuf[4]; bootldrgetNch(spicmdbuf,4); if (0) { // spicmdbuf[0] == 0x30) { if (spicmdbuf[2] == 0) { byte_response(SIG1); } else if (spicmdbuf[2] == 1) { byte_response(SIG2); } else { byte_response(SIG3); } } // Call my erase device embedded routine if the erase device SPI cmd comes in else if ((spicmdbuf[0] == 0xac) && (spicmdbuf[1] == 0x80)) { eraseDevice(); byte_response(0); } // Don't let them program the fuse bits into a non-working clock // This SPI on this chip can't go slow enough to work with very slow AVR clocks (<=1mhz) else if ((spicmdbuf[0] == 0xAC) && (spicmdbuf[1] == 0xA0) && (((spicmdbuf[3]&0x80) == 0) || ((spicmdbuf[3]&0x0f) == 3))) { failed_response(); } else { byte_response(issueSpiCmd(spicmdbuf)); } } /* Write memory, length is big endian and is in bytes */ else if(ch=='d') { length.word = myget2BE(); //length.byte[1] = bootldrgetch(); //length.byte[0] = bootldrgetch(); flags.eeprom = 0; if (bootldrgetch() == 'E') flags.eeprom = 1; for (w=0;w<length.word;w++) { buff[w] = bootldrgetch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages } if (bootldrgetch() == ' ') { if (flags.eeprom) { //Write to EEPROM one byte at a time address.word <<= 1; for(w=0;w<length.word;w++) { eeprom_write_byte((void *)address.word,buff[w]); address.word++; } } else { //Write to FLASH one page at a time if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME else address_high = 0x00; address.word = address.word << 1; //address * 2 -> byte location /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */ //if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes if (length.word&1) length.word++; // Even up an odd number of bytes flash_write((void*)address.word, length.word, address_high, buff); } putNch(endStmt,2); //myputch(0x14); //myputch(0x10); } else { ++error_count; } } /* Read memory block mode, length is big endian. */ else if(ch=='t') { length.word = myget2BE(); //length.byte[1] = bootldrgetch(); //length.byte[0] = bootldrgetch(); #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME else flags.rampz = 0; #endif address.word = address.word << 1; // address * 2 -> byte location if (bootldrgetch() == 'E') flags.eeprom = 1; else flags.eeprom = 0; if (bootldrgetch() == ' ') { // Command terminator myputch(0x14); if (1) { // Can handle odd and even lengths okay if (flags.eeprom) { // Byte access EEPROM read for (w=0;w < length.word;w++,address.word++) { myputch(eeprom_read_byte((void *)address.word)); } } else { int bpos = 0; for (w=0;w < length.word;w++,address.word++,bpos++) { if (!flags.rampz) buff[bpos] = pgm_read_byte_near((void*)address.word); #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) else buff[bpos] = pgm_read_byte_far(address.word + 0x10000); // Hmmmm, yuck FIXME when m256 arrvies #endif if (bpos == 63) { putNch(buff,64); bpos = -1; } } if (bpos > 0) { putNch(buff,bpos); } } } myputch(0x10); } } /* Get device signature bytes */ else if(ch=='u') { if (bootldrgetch() == ' ') { bitSet(UsbLed); putNch(devId,5); } else { ++error_count; } } /* Read oscillator calibration byte */ else if(ch=='v') { byte_response(0x00); } #ifdef MONITOR /* here come the extended monitor commands by Erik Lins */ /* check for three times exclamation mark pressed */ else if(ch=='!') monitor(); #endif else /* Garbled 1st character */ { //printf("garbled character %d %c\n",ch,ch); ++error_count; } } /* end of forever loop */ }