diff --git a/bootloader/ATmegaBOOT.c b/bootloader/ATmegaBOOT.c index ce63aea61..17977e676 100755 --- a/bootloader/ATmegaBOOT.c +++ b/bootloader/ATmegaBOOT.c @@ -1,12 +1,12 @@ /**********************************************************/ -/* Serial Bootloader for Atmel megaAVR Controllers */ +/* Serial Bootloader for Atmel mega8 AVR Controller */ /* */ /* ATmegaBOOT.c */ /* */ /* Copyright (c) 2003, Jason P. Kyle */ -/* All rights reserved. */ /* */ /* Hacked by DojoCorp - ZGZ - MMX - IVR */ +/* Hacked by David A. Mellis */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify it under the terms of the GNU General */ @@ -28,12 +28,7 @@ /* Licence can be viewed at */ /* http://www.fsf.org/licenses/gpl.txt */ /* */ -/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */ -/* m8515,m8535. ATmega161 has a very small boot block so */ -/* isn't supported. */ -/* */ -/* Tested with m8 - */ -/* */ +/* Target = Atmel AVR m8 */ /**********************************************************/ #include @@ -41,23 +36,21 @@ #include #include #include +#include -#define F_CPU 16000000 +//#define F_CPU 16000000 /* We, Malmoitians, like slow interaction * therefore the slow baud rate ;-) */ -#define BAUD_RATE 9600 +//#define BAUD_RATE 9600 /* 6.000.000 is more or less 8 seconds at the * speed configured here */ -#define MAX_TIME_COUNT 6000000 -#define MAX_TIME_COUNT_MORATORY 1600000 - -#define DECRYPT 0 -#define ENCRYPT 1 -/* #define DES_ENCRYPTION */ +//#define MAX_TIME_COUNT 6000000 +#define MAX_TIME_COUNT (F_CPU>>1) +///#define MAX_TIME_COUNT_MORATORY 1600000 /* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */ #define HW_VER 0x02 @@ -68,18 +61,18 @@ // avr-gcc compiler v3.1.x and older doesn't support outb() and inb() // if necessary, convert outb and inb to outp and inp #ifndef outb - #define outb(sfr,val) (_SFR_BYTE(sfr) = (val)) + #define outb(sfr,val) (_SFR_BYTE(sfr) = (val)) #endif #ifndef inb - #define inb(sfr) _SFR_BYTE(sfr) + #define inb(sfr) _SFR_BYTE(sfr) #endif /* defines for future compatibility */ #ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif /* Adjust to suit whatever pin your hardware uses to enter the bootloader */ @@ -87,15 +80,6 @@ #define eeprom_rw(addr) eeprom_read_word ((uint16_t *)(addr)) #define eeprom_wb(addr, val) eeprom_write_byte ((uint8_t *)(addr), (uint8_t)(val)) -/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */ -#define BL_DDR DDRD -#define BL_PORT PORTD -#define BL_PIN PIND -#define BL PIND6 - -/* define pin for onboard LED */ -/* depends on product */ - /* Onboard LED is connected to pin PB5 */ #define LED_DDR DDRB #define LED_PORT PORTB @@ -131,12 +115,12 @@ struct flags_struct { } flags; uint8_t buff[256]; -uint8_t address_high; +//uint8_t address_high; uint8_t pagesz=0x80; uint8_t i; -uint8_t bootuart0=0,bootuart1=0; +//uint8_t bootuart0=0,bootuart1=0; void (*app_start)(void) = 0x0000; @@ -146,23 +130,23 @@ int main(void) uint8_t ch,ch2; uint16_t w; - cbi(BL_DDR,BL); - sbi(BL_PORT,BL); + //cbi(BL_DDR,BL); + //sbi(BL_PORT,BL); asm volatile("nop\n\t"); /* check if flash is programmed already, if not start bootloader anyway */ - if(pgm_read_byte_near(0x0000) != 0xFF) { + //if(pgm_read_byte_near(0x0000) != 0xFF) { /* check if bootloader pin is set low */ //if(bit_is_set(BL_PIN,BL)) app_start(); - } + //} /* initialize UART(s) depending on CPU defined */ /* m8 */ UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate UBRRL = (((F_CPU/BAUD_RATE)/16)-1); - UCSRB =(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 - cli(); //Disable interrupts, just to be sure - while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete - asm volatile("clr r17 \n\t" //page_word_count - "lds r30,address \n\t" //Address of FLASH location (in bytes) - "lds r31,address+1 \n\t" - "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM - "ldi r29,hi8(buff) \n\t" - "lds r24,length \n\t" //Length of data to be written (in bytes) - "lds r25,length+1 \n\t" - "length_loop: \n\t" //Main loop, repeat for number of words in block - "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page - "brne no_page_erase \n\t" - "wait_spm1: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm1 \n\t" - "ldi r16,0x03 \n\t" //Erase page pointed to by Z - "sts %0,r16 \n\t" - "spm \n\t" - "wait_spm2: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm2 \n\t" - - "ldi r16,0x11 \n\t" //Re-enable RWW section - "sts %0,r16 \n\t" - "spm \n\t" - "no_page_erase: \n\t" - "ld r0,Y+ \n\t" //Write 2 bytes into page buffer - "ld r1,Y+ \n\t" - - "wait_spm3: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm3 \n\t" - "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer - "sts %0,r16 \n\t" - "spm \n\t" - - "inc r17 \n\t" //page_word_count++ - "cpi r17,%1 \n\t" - "brlo same_page \n\t" //Still same page in FLASH - "write_page: \n\t" - "clr r17 \n\t" //New page, write current one first - "wait_spm4: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm4 \n\t" - "ldi r16,0x05 \n\t" //Write page pointed to by Z - "sts %0,r16 \n\t" - "spm \n\t" - "wait_spm5: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm5 \n\t" - "ldi r16,0x11 \n\t" //Re-enable RWW section - "sts %0,r16 \n\t" - "spm \n\t" - "same_page: \n\t" - "adiw r30,2 \n\t" //Next word in FLASH - "sbiw r24,2 \n\t" //length-2 - "breq final_write \n\t" //Finished - "rjmp length_loop \n\t" - "final_write: \n\t" - "cpi r17,0 \n\t" - "breq block_done \n\t" - "adiw r24,2 \n\t" //length+2, fool above check on length after short page write - "rjmp write_page \n\t" - "block_done: \n\t" - "clr __zero_reg__ \n\t" //restore zero register - : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"); - - /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */ - /* exit the bootloader without a power cycle anyhow */ - } - putch(0x14); - putch(0x10); - } + if (flags.eeprom) { //Write to EEPROM one byte at a time + for(w=0;w127) 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)) length.word++; //Even up an odd number of bytes + cli(); //Disable interrupts, just to be sure + while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete + asm volatile( + "clr r17 \n\t" //page_word_count + "lds r30,address \n\t" //Address of FLASH location (in words) + "lds r31,address+1 \n\t" + "lsl r30 \n\t" //address * 2 -> byte location + "rol r31 \n\t" + "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM + "ldi r29,hi8(buff) \n\t" + "lds r24,length \n\t" //Length of data to be written (in bytes) + "lds r25,length+1 \n\t" + "sbrs r24,0 \n\t" //Even up an odd number of bytes + "rjmp length_loop \n\t" + "adiw r24,1 \n\t" + "length_loop: \n\t" //Main loop, repeat for number of words in block + "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page + "brne no_page_erase \n\t" + "rcall wait_spm \n\t" +// "wait_spm1: \n\t" +// "lds r16,%0 \n\t" //Wait for previous spm to complete +// "andi r16,1 \n\t" +// "cpi r16,1 \n\t" +// "breq wait_spm1 \n\t" + "ldi r16,0x03 \n\t" //Erase page pointed to by Z + "sts %0,r16 \n\t" + "spm \n\t" + "rcall wait_spm \n\t" +// "wait_spm2: \n\t" +// "lds r16,%0 \n\t" //Wait for previous spm to complete +// "andi r16,1 \n\t" +// "cpi r16,1 \n\t" +// "breq wait_spm2 \n\t" + "ldi r16,0x11 \n\t" //Re-enable RWW section + "sts %0,r16 \n\t" + "spm \n\t" + "no_page_erase: \n\t" + "ld r0,Y+ \n\t" //Write 2 bytes into page buffer + "ld r1,Y+ \n\t" + + "rcall wait_spm \n\t" +// "wait_spm3: \n\t" +// "lds r16,%0 \n\t" //Wait for previous spm to complete +// "andi r16,1 \n\t" +// "cpi r16,1 \n\t" +// "breq wait_spm3 \n\t" + "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer + "sts %0,r16 \n\t" + "spm \n\t" + + "inc r17 \n\t" //page_word_count++ + "cpi r17,%1 \n\t" + "brlo same_page \n\t" //Still same page in FLASH + "write_page: \n\t" + "clr r17 \n\t" //New page, write current one first + "rcall wait_spm \n\t" +// "wait_spm4: \n\t" +// "lds r16,%0 \n\t" //Wait for previous spm to complete +// "andi r16,1 \n\t" +// "cpi r16,1 \n\t" +// "breq wait_spm4 \n\t" + "ldi r16,0x05 \n\t" //Write page pointed to by Z + "sts %0,r16 \n\t" + "spm \n\t" + "rcall wait_spm \n\t" +// "wait_spm5: \n\t" +// "lds r16,%0 \n\t" //Wait for previous spm to complete +// "andi r16,1 \n\t" +// "cpi r16,1 \n\t" +// "breq wait_spm5 \n\t" + "ldi r16,0x11 \n\t" //Re-enable RWW section + "sts %0,r16 \n\t" + "spm \n\t" + "same_page: \n\t" + "adiw r30,2 \n\t" //Next word in FLASH + "sbiw r24,2 \n\t" //length-2 + "breq final_write \n\t" //Finished + "rjmp length_loop \n\t" + + "wait_spm: \n\t" + "lds r16,%0 \n\t" //Wait for previous spm to complete + "andi r16,1 \n\t" + "cpi r16,1 \n\t" + "breq wait_spm \n\t" + "ret \n\t" + + "final_write: \n\t" + "cpi r17,0 \n\t" + "breq block_done \n\t" + "adiw r24,2 \n\t" //length+2, fool above check on length after short page write + "rjmp write_page \n\t" + "block_done: \n\t" + "clr __zero_reg__ \n\t" //restore zero register + : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"); + + /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */ + /* exit the bootloader without a power cycle anyhow */ + } + putch(0x14); + putch(0x10); + } } /* Read memory block mode, length is big endian. */ @@ -414,34 +411,32 @@ int main(void) length.byte[0] = getch(); if (getch() == 'E') flags.eeprom = 1; else { - flags.eeprom = 0; - address.word = address.word << 1; // address * 2 -> byte location + flags.eeprom = 0; + address.word = address.word << 1; // address * 2 -> byte location } if (getch() == ' ') { // Command terminator - putch(0x14); - for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay - if (flags.eeprom) { // Byte access EEPROM read - putch(eeprom_rb(address.word)); - address.word++; - } - else { - - if (!flags.rampz) putch(pgm_read_byte_near(address.word)); - address.word++; - } - } - putch(0x10); + putch(0x14); + for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay + if (flags.eeprom) { // Byte access EEPROM read + putch(eeprom_rb(address.word)); + address.word++; + } else { + if (!flags.rampz) putch(pgm_read_byte_near(address.word)); + address.word++; + } + } + putch(0x10); } } /* Get device signature bytes */ else if(ch=='u') { if (getch() == ' ') { - putch(0x14); - putch(SIG1); - putch(SIG2); - putch(SIG3); - putch(0x10); + putch(0x14); + putch(SIG1); + putch(SIG2); + putch(SIG3); + putch(0x10); } } @@ -449,17 +444,13 @@ int main(void) else if(ch=='v') { byte_response(0x00); } - } - else { - time_count++; - if (time_count>=MAX_TIME_COUNT) { - app_start(); - } - } - - } - /* end of forever loop */ - +// } else { +// time_count++; +// if (time_count>=MAX_TIME_COUNT) { +// app_start(); +// } +// } + } /* end of forever loop */ } void putch(char ch) @@ -472,8 +463,12 @@ void putch(char ch) char getch(void) { /* m8 */ + uint32_t count = 0; while(!(inb(UCSRA) & _BV(RXC))) { - /* HACKME:: here is a good place to count times*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); } return (inb(UDR)); } @@ -483,8 +478,9 @@ void getNch(uint8_t count) uint8_t i; for(i=0;i $@ +size: $(PROGRAM).hex + $(SIZE) $^ + # Rules for building the .text rom images text: hex bin srec diff --git a/build/linux/dist/bootloader/burn b/build/linux/dist/bootloader/burn index 6f1b06c77..54214b83c 100755 --- a/build/linux/dist/bootloader/burn +++ b/build/linux/dist/bootloader/burn @@ -25,6 +25,6 @@ PORT=/dev/ttyS0 #PORT=/dev/tty.USA19QW1b1P1.1 uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_lock=0xFF -uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xc8 +uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xca uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --erase --upload if=ATMegaBOOT.hex -v uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_lock=0xCF diff --git a/build/macosx/dist/bootloader/burn.command b/build/macosx/dist/bootloader/burn.command index 622693806..e44d4f71b 100755 --- a/build/macosx/dist/bootloader/burn.command +++ b/build/macosx/dist/bootloader/burn.command @@ -17,13 +17,19 @@ # parametre # -#BINDIR=/usr/local/avr/bin -BINDIR=../build/macosx/work/tools/avr/bin -#PORT=/dev/tty.usbserial0 -#PORT=/dev/tty.USA19QW3b1P1.1 -PORT=/dev/tty.USA19QW1b1P1.1 +BINDIR=../tools/avr/bin +PORT=/dev/tty.USA19QW?b1P1.1 +# unlock bootloader segment $BINDIR/uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_lock=0xFF -$BINDIR/uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xc8 + +# set fuses +# bootloader size of 512 words; from 0xE00-0xFFF +# clock speed of 16 MHz, external quartz +$BINDIR/uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xca + +# upload bootloader $BINDIR/uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --erase --upload if=ATMegaBOOT.hex -v + +# lock bootloader segment $BINDIR/uisp -dpart=ATmega8 -dprog=stk500 -dserial=$PORT -dspeed=115200 --wr_lock=0xCF diff --git a/build/windows/dist/bootloader/burn.bat b/build/windows/dist/bootloader/burn.bat index 8a431729c..bde1853a2 100755 --- a/build/windows/dist/bootloader/burn.bat +++ b/build/windows/dist/bootloader/burn.bat @@ -1,6 +1,6 @@ REM TODO: need way to specify serial port. ..\tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_lock=0xFF -..\tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xc8 +..\tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_fuse_l=0xdf --wr_fuse_h=0xca ..\tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --erase --upload --verify if=ATMegaBOOT.hex ..\tools\avr\bin\uisp -dpart=ATmega8 -dprog=stk500 -dserial=com1 -dspeed=115200 --wr_lock=0xCF