Skip to content

Commit baaad71

Browse files
authored
Support optiboot, optiboot_dx and optiboot_x bootloaders for -c arduino (#1140)
* If bootloaders are served, send word addresses for classic parts and byte addresses for newer parts, eg, UPDI and PDI * Load ext addr for stk500v1 bootloaders after grazing 64k boundaries * Fix bootloader stk500v1 EEPROM r/w for classic parts with page size 1
1 parent 1692284 commit baaad71

File tree

1 file changed

+76
-44
lines changed

1 file changed

+76
-44
lines changed

src/stk500.c

+76-44
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,12 @@ static void stk500_disable(const PROGRAMMER *pgm) {
625625
}
626626

627627
static void stk500_enable(PROGRAMMER *pgm, const AVRPART *p) {
628+
AVRMEM *mem;
629+
if(pgm->prog_modes & PM_SPM) // For bootloaders (eg, arduino)
630+
if(!(p->prog_modes & (PM_UPDI | PM_PDI | PM_aWire))) // Classic parts, eg, optiboot with word addresses
631+
if((mem = avr_locate_mem(p, "eeprom")))
632+
if(mem->page_size == 1) // Increase pagesize if it is 1
633+
mem->page_size = 16;
628634
return;
629635
}
630636

@@ -666,27 +672,56 @@ static void stk500_close(PROGRAMMER * pgm)
666672
}
667673

668674

669-
static int stk500_loadaddr(const PROGRAMMER *pgm, const AVRMEM *mem, const unsigned int addr) {
675+
// Address is byte address; a_div == 2: send word address; a_div == 1: send byte address
676+
static int stk500_loadaddr(const PROGRAMMER *pgm, const AVRMEM *mem, unsigned int addr, int a_div) {
670677
unsigned char buf[16];
671678
int tries;
672679
unsigned char ext_byte;
673-
OPCODE * lext;
680+
681+
addr /= a_div;
674682

675683
tries = 0;
676684
retry:
677685
tries++;
678686

679-
/* To support flash > 64K words the correct Extended Address Byte is needed */
680-
lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
681-
if (lext != NULL) {
682-
ext_byte = (addr >> 16) & 0xff;
683-
if (ext_byte != PDATA(pgm)->ext_addr_byte) {
684-
/* Either this is the first addr load, or a different 64K word section */
685-
memset(buf, 0, 4);
686-
avr_set_bits(lext, buf);
687-
avr_set_addr(lext, buf, addr);
688-
stk500_cmd(pgm, buf, buf);
689-
PDATA(pgm)->ext_addr_byte = ext_byte;
687+
// Support large flash by sending the correct extended address byte when needed
688+
689+
if(pgm->prog_modes & PM_SPM) { // Bootloaders, eg, optiboot, optiboot_dx, optiboot_x
690+
if(mem->size/a_div > 64*1024) { // Extended addressing needed
691+
ext_byte = (addr >> 16) & 0xff;
692+
if(ext_byte != PDATA(pgm)->ext_addr_byte) { // First addr load or a different 64k section
693+
buf[0] = 0x4d; // Protocol bytes that bootloaders expect
694+
buf[1] = 0x00;
695+
buf[2] = ext_byte;
696+
buf[3] = 0x00;
697+
if(stk500_cmd(pgm, buf, buf) == 0)
698+
PDATA(pgm)->ext_addr_byte = ext_byte;
699+
}
700+
/*
701+
* Ensure next paged r/w will load ext addr again if page sits just below a 64k boundary
702+
*
703+
* Some bootloaders increment their copy of ext_addr_byte in that situation, eg, when they
704+
* use elpm rx,Z+ to read a byte from flash or spm Z+ to write to flash whilst they keep
705+
* ext_addr_byte in RAMPZ, which in turn gets incremented by Z+ at 64k page boundaries. So,
706+
* if an upload with automated verify finishes just below 64k, AVRDUDE still holds
707+
* ext_addr_byte at the current 64k segment whilst its copy in the bootloader has been
708+
* auto-incremented. Verifying the code from start exposes the discrepancy.
709+
*/
710+
if((addr & 0xffff0000) != ((addr+mem->page_size/a_div) & 0xffff0000))
711+
PDATA(pgm)->ext_addr_byte = 0xff;
712+
}
713+
} else { // Programmer *not* for bootloaders? Original stk500v1 protocol!
714+
OPCODE *lext = mem->op[AVR_OP_LOAD_EXT_ADDR];
715+
716+
if(lext) {
717+
ext_byte = (addr >> 16) & 0xff;
718+
if(ext_byte != PDATA(pgm)->ext_addr_byte) { // First addr load or a different 64k section
719+
memset(buf, 0, 4); // Part's load_ext_addr command is typically 4d 00 ext_addr 00
720+
avr_set_bits(lext, buf);
721+
avr_set_addr(lext, buf, addr);
722+
if(stk500_cmd(pgm, buf, buf) == 0)
723+
PDATA(pgm)->ext_addr_byte = ext_byte;
724+
}
690725
}
691726
}
692727

@@ -724,6 +759,29 @@ static int stk500_loadaddr(const PROGRAMMER *pgm, const AVRMEM *mem, const unsig
724759
}
725760

726761

762+
static int set_memtype_a_div(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int *memtypep, int *a_divp) {
763+
if(avr_mem_is_flash_type(m)) {
764+
*memtypep = 'F';
765+
if(!(pgm->prog_modes & PM_SPM)) // Programmer *not* for bootloaders: original stk500v1 protocol
766+
*a_divp = m->op[AVR_OP_LOADPAGE_LO] || m->op[AVR_OP_READ_LO]? 2: 1;
767+
else if(!(p->prog_modes & (PM_UPDI | PM_PDI | PM_aWire)))
768+
*a_divp = 2; // Bootloader where part is a "classic" part (eg, optiboot)
769+
else
770+
*a_divp = 1; // Bootloader where part is Xmega or "new" families (optiboot_x, optiboot_dx)
771+
return 0;
772+
}
773+
774+
if(avr_mem_is_eeprom_type(m)) {
775+
*memtypep = 'E';
776+
// Word addr for bootloaders where part is a "classic" part (eg, optiboot, arduinoisp, ...), byte addr otherwise
777+
*a_divp = (pgm->prog_modes & PM_SPM) && !(p->prog_modes & (PM_UPDI | PM_PDI))? 2: 1;
778+
return 0;
779+
}
780+
781+
return -1;
782+
}
783+
784+
727785
static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
728786
unsigned int page_size,
729787
unsigned int addr, unsigned int n_bytes)
@@ -736,25 +794,12 @@ static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
736794
unsigned int n;
737795
unsigned int i;
738796

739-
if (strcmp(m->desc, "flash") == 0) {
740-
memtype = 'F';
741-
a_div = 2;
742-
} else if (strcmp(m->desc, "eeprom") == 0) {
743-
memtype = 'E';
744-
/*
745-
* The STK original 500 v1 protocol actually expects a_div = 1, but the
746-
* v1.x FW of the STK500 kit has been superseded by v2 FW in the mid
747-
* 2000s. Since optiboot, arduino as ISP and others assume a_div = 2,
748-
* better use that. See https://github.com/avrdudes/avrdude/issues/967
749-
*/
750-
a_div = 2;
751-
} else {
797+
if(set_memtype_a_div(pgm, p, m, &memtype, &a_div) < 0)
752798
return -2;
753-
}
754799

755800
n = addr + n_bytes;
756801
#if 0
757-
msg_info(
802+
msg_debug(
758803
"n_bytes = %d\n"
759804
"n = %u\n"
760805
"a_div = %d\n"
@@ -775,7 +820,7 @@ static int stk500_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
775820
tries = 0;
776821
retry:
777822
tries++;
778-
stk500_loadaddr(pgm, m, addr/a_div);
823+
stk500_loadaddr(pgm, m, addr, a_div);
779824

780825
/* build command block and avoid multiple send commands as it leads to a crash
781826
of the silabs usb serial driver on mac os x */
@@ -830,21 +875,8 @@ static int stk500_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
830875
unsigned int n;
831876
int block_size;
832877

833-
if (strcmp(m->desc, "flash") == 0) {
834-
memtype = 'F';
835-
a_div = 2;
836-
} else if (strcmp(m->desc, "eeprom") == 0) {
837-
memtype = 'E';
838-
/*
839-
* The STK original 500 v1 protocol actually expects a_div = 1, but the
840-
* v1.x FW of the STK500 kit has been superseded by v2 FW in the mid
841-
* 2000s. Since optiboot, arduino as ISP and others assume a_div = 2,
842-
* better use that. See https://github.com/avrdudes/avrdude/issues/967
843-
*/
844-
a_div = 2;
845-
} else {
878+
if(set_memtype_a_div(pgm, p, m, &memtype, &a_div) < 0)
846879
return -2;
847-
}
848880

849881
n = addr + n_bytes;
850882
for (; addr < n; addr += block_size) {
@@ -861,7 +893,7 @@ static int stk500_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
861893
tries = 0;
862894
retry:
863895
tries++;
864-
stk500_loadaddr(pgm, m, addr/a_div);
896+
stk500_loadaddr(pgm, m, addr, a_div);
865897
buf[0] = Cmnd_STK_READ_PAGE;
866898
buf[1] = (block_size >> 8) & 0xff;
867899
buf[2] = block_size & 0xff;

0 commit comments

Comments
 (0)