From 231e88aaf94c48959053ea315e369dcc6eb74ec9 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 25 Nov 2022 19:20:45 +0000 Subject: [PATCH 1/8] Add autobaud_sync to avrdude.conf part description --- src/avrdude.conf.in | 21 +++++++---- src/avrpart.c | 1 + src/config.c | 1 + src/developer_opts.c | 1 + src/doc/avrdude.texi | 20 +++++----- src/lexer.l | 2 +- src/libavrdude.h | 89 ++++++++++++++++++++++++-------------------- 7 files changed, 77 insertions(+), 58 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 2e04f8e3..b97e4479 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -130,7 +130,7 @@ # programfusepolltimeout = ; # programlockpulsewidth = ; # PP only # programlockpolltimeout = ; -# # JTAG ICE mkII parameters, also from ATDF files +# # debugWIRE and/or JTAG ICE mkII parameters, also from ATDF files # allowfullpagebitstream = ; # enablepageprogramming = ; # idr = ; # IO addr of IDR (OCD) reg @@ -143,6 +143,8 @@ # ocdrev = ; # pgm_enable = ; # chip_erase = ; +# # parameters for bootloaders +# autobaud_sync = ; # autobaud detection byte, default 0x30 # # memory # paged = ; # yes/no (flash only, do not use for EEPROM) @@ -175,12 +177,13 @@ # # If any of the above parameters are not specified, the default value # of 0 is used for numerics (except for mcuid, hvupdi_variant and -# ocdrev, where the default value is -1) or the empty string "" for -# string values. If a required parameter is left empty, AVRDUDE will -# complain. Almost all occurrences of numbers (with the exception of -# pin numbers and where they are separated by space, eg, in signature -# and readback) can also be given as simple expressions involving -# arithemtic and bitwise operators. +# ocdrev, where the default value is -1, and for autobaud_sync which +# defaults to 0x30), or the empty string "" for string values. If a +# required parameter is left empty, AVRDUDE will complain. Almost all +# occurrences of numbers (with the exception of pin numbers and where +# they are separated by space, eg, in signature and readback) can also +# be given as simple expressions involving arithemtic and bitwise +# operators. # # Parts can also inherit parameters from previously defined parts # using the following syntax. In this case specified integer and @@ -12011,6 +12014,7 @@ part n_boot_sections = 1; mcu_base = 0x0090; nvm_base = 0x01c0; + autobaud_sync = 0x20; memory "fuse1" size = 1; @@ -16329,6 +16333,7 @@ part parent "m88" id = "lgt8f88p"; mcuid = 227; signature = 0x1e 0x93 0x0f; + autobaud_sync = 0x1c; ; #------------------------------------------------------------ @@ -16340,6 +16345,7 @@ part parent "m168" id = "lgt8f168p"; mcuid = 228; signature = 0x1e 0x94 0x0b; + autobaud_sync = 0x1c; ; #------------------------------------------------------------ @@ -16351,4 +16357,5 @@ part parent "m328" id = "lgt8f328p"; mcuid = 229; signature = 0x1e 0x95 0x0f; + autobaud_sync = 0x1c; ; diff --git a/src/avrpart.c b/src/avrpart.c index cf4fa996..4f03efb2 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -578,6 +578,7 @@ AVRPART *avr_new_part(void) { // Default values p->mcuid = -1; p->hvupdi_variant = -1; + p->autobaud_sync = 0x30; // STK_GET_SYNC memset(p->signature, 0xFF, 3); p->reset_disposition = RESET_DEDICATED; p->retry_pulse = PIN_AVR_SCK; diff --git a/src/config.c b/src/config.c index ba31ceee..2c512d00 100644 --- a/src/config.c +++ b/src/config.c @@ -72,6 +72,7 @@ Component_t avr_comp[] = { part_comp_desc(n_page_erase, COMP_INT), part_comp_desc(n_boot_sections, COMP_INT), part_comp_desc(boot_section_size, COMP_INT), + part_comp_desc(autobaud_sync, COMP_CHAR), // AVRMEM mem_comp_desc(n_word_writes, COMP_INT), diff --git a/src/developer_opts.c b/src/developer_opts.c index 5f25b654..8d8674a5 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -716,6 +716,7 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool _if_partout(intcmp, "0x%04x", nvm_base); _if_partout(intcmp, "0x%04x", ocd_base); _if_partout(intcmp, "%d", ocdrev); + _if_partout(intcmp, "0x%02x", autobaud_sync); for(int i=0; i < AVR_OP_MAX; i++) if(!base || opcodecmp(p->op[i], base->op[i], i)) diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 539e9b4c..6127b936 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1925,7 +1925,7 @@ part programfusepolltimeout = ; programlockpulsewidth = ; # PP only programlockpolltimeout = ; - # JTAG ICE mkII parameters, also from ATDF files + # debugWIRE and/or JTAG ICE mkII parameters, also from ATDF files allowfullpagebitstream = ; enablepageprogramming = ; idr = ; # IO addr of IDR (OCD) reg @@ -1938,6 +1938,8 @@ part ocdrev = ; pgm_enable = ; chip_erase = ; + # parameters for bootloaders + autobaud_sync = ; # autobaud detection byte, default 0x30 memory paged = ; # yes/no (flash only, do not use for EEPROM) @@ -1970,14 +1972,14 @@ part @end smallexample @noindent -If any of the above parameters are not specified, the default value -of 0 is used for numerics (except for @code{mcuid}, @code{hvupdi_variant} and @code{ocdrev}, -where the default value is -1) or the empty string @code{""} for string -values. If a required parameter is left empty, AVRDUDE will complain. -Almost all occurrences of numbers (with the exception of pin numbers -and where they are separated by space, eg, in signature and readback) -can also be given as simple expressions involving arithemtic and -bitwise operators. +If any of the above parameters are not specified, the default value of 0 +is used for numerics (except for @code{mcuid}, @code{hvupdi_variant} and +@code{ocdrev}, where the default value is -1, and for @code{autobaud_sync} +which defaults to 0x30) or the empty string @code{""} for string values. +If a required parameter is left empty, AVRDUDE will complain. Almost all +occurrences of numbers (with the exception of pin numbers and where they +are separated by space, eg, in signature and readback) can also be given +as simple expressions involving arithemtic and bitwise operators. @menu * Parent Part:: diff --git a/src/lexer.l b/src/lexer.l index 1d80594d..65cb3b4a 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -122,7 +122,7 @@ SIGN [+-] (?x: prog_modes | mcuid | n_interrupts | n_page_erase | n_word_writes | n_boot_sections | - boot_section_size ) { /* Components for assignment */ + boot_section_size | autobaud_sync) { /* Components for assignment */ Component_t *cp = cfg_comp_search(yytext, current_strct); if(!cp) { diff --git a/src/libavrdude.h b/src/libavrdude.h index d9e84be1..cb01f7a8 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -252,56 +252,63 @@ typedef struct avrpart { this pin (PIN_AVR_*) */ unsigned flags; /* see AVRPART_ masks */ - int timeout; /* stk500 v2 xml file parameter */ - int stabdelay; /* stk500 v2 xml file parameter */ - int cmdexedelay; /* stk500 v2 xml file parameter */ - int synchloops; /* stk500 v2 xml file parameter */ - int bytedelay; /* stk500 v2 xml file parameter */ - int pollindex; /* stk500 v2 xml file parameter */ - unsigned char pollvalue; /* stk500 v2 xml file parameter */ - int predelay; /* stk500 v2 xml file parameter */ - int postdelay; /* stk500 v2 xml file parameter */ - int pollmethod; /* stk500 v2 xml file parameter */ + /* STK500 v2 parameters from ATDF files */ + int timeout; + int stabdelay; + int cmdexedelay; + int synchloops; + int bytedelay; + int pollindex; + unsigned char pollvalue; + int predelay; + int postdelay; + int pollmethod; enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */ unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */ unsigned char flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */ unsigned char eeprom_instr[EEPROM_INSTR_SIZE]; /* EEPROM instructions (debugWire, JTAG) */ - int hventerstabdelay; /* stk500 v2 hv mode parameter */ - int progmodedelay; /* stk500 v2 hv mode parameter */ - int latchcycles; /* stk500 v2 hv mode parameter */ - int togglevtg; /* stk500 v2 hv mode parameter */ - int poweroffdelay; /* stk500 v2 hv mode parameter */ - int resetdelayms; /* stk500 v2 hv mode parameter */ - int resetdelayus; /* stk500 v2 hv mode parameter */ - int hvleavestabdelay; /* stk500 v2 hv mode parameter */ - int resetdelay; /* stk500 v2 hv mode parameter */ - int chiperasepulsewidth; /* stk500 v2 hv mode parameter */ - int chiperasepolltimeout; /* stk500 v2 hv mode parameter */ - int chiperasetime; /* stk500 v2 hv mode parameter */ - int programfusepulsewidth; /* stk500 v2 hv mode parameter */ - int programfusepolltimeout; /* stk500 v2 hv mode parameter */ - int programlockpulsewidth; /* stk500 v2 hv mode parameter */ - int programlockpolltimeout; /* stk500 v2 hv mode parameter */ - int synchcycles; /* stk500 v2 hv mode parameter */ - int hvspcmdexedelay; /* stk500 v2 hv mode file parameter */ + /* STK500 v2 hv mode parameters */ + int hventerstabdelay; + int progmodedelay; + int latchcycles; + int togglevtg; + int poweroffdelay; + int resetdelayms; + int resetdelayus; + int hvleavestabdelay; + int resetdelay; + int chiperasepulsewidth; + int chiperasepolltimeout; + int chiperasetime; + int programfusepulsewidth; + int programfusepolltimeout; + int programlockpulsewidth; + int programlockpolltimeout; + int synchcycles; + int hvspcmdexedelay; - unsigned char idr; /* JTAG ICE mkII XML file parameter */ - unsigned char rampz; /* JTAG ICE mkII XML file parameter */ - unsigned char spmcr; /* JTAG ICE mkII XML file parameter */ - unsigned char eecr; /* JTAC ICE mkII XML file parameter */ - unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */ - unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */ - unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */ - int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */ - OPCODE * op[AVR_OP_MAX]; /* opcodes */ + /* debugWIRE and/or JTAG ICE mkII XML file parameters */ + unsigned char idr; /* I/O address of IDR (OCD) reg */ + unsigned char rampz; /* I/O address of RAMPZ reg */ + unsigned char spmcr; /* memory address of SPMCR reg */ + unsigned char eecr; /* memory address of EECR reg */ + unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */ + unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */ + unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */ + int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */ - LISTID mem; /* avr memory definitions */ - LISTID mem_alias; /* memory alias definitions */ - const char * config_file; /* config file where defined */ - int lineno; /* config file line number */ + /* Bootloader paramater */ + unsigned char autobaud_sync; /* Sync byte for bootloader autobaud, must be <= 0x30 */ + + OPCODE * op[AVR_OP_MAX]; /* opcodes */ + + LISTID mem; /* avr memory definitions */ + LISTID mem_alias; /* memory alias definitions */ + const char * config_file; /* config file where defined */ + int lineno; /* config file line number */ } AVRPART; typedef struct avrmem { From 1cb169ec93e157993264ef56b8ce5c0b069c64f6 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 25 Nov 2022 22:09:02 +0000 Subject: [PATCH 2/8] Establish avr_*timestamp() routines for timing --- src/avr.c | 43 +++++++++++++++++++++++++++++++++++-------- src/jtagmkII.c | 7 ++----- src/libavrdude.h | 6 ++++++ src/main.c | 2 ++ src/serialupdi.c | 14 ++++---------- src/stk500v2.c | 9 +++------ src/updi_nvm.c | 7 ++----- 7 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/avr.c b/src/avr.c index 370f09fb..732b284a 100644 --- a/src/avr.c +++ b/src/avr.c @@ -529,6 +529,38 @@ int avr_write_page(const PROGRAMMER *pgm, const AVRPART *p_unused, const AVRMEM } +// Return us since program start, rolls over after ca 1h 12min +unsigned long avr_ustimestamp() { + struct timeval tv; + + memset(&tv, 0, sizeof tv); + if(gettimeofday(&tv, NULL) == 0) { + static unsigned long long epoch; + static int init; + unsigned long long now; + + now = tv.tv_sec*1000000ULL + tv.tv_usec; + if(!init) { + epoch = now; + init = 1; + } + return now - epoch; + } + + return 0; +} + +// Return ms since program start, rolls over after ca 49d 17h +unsigned long avr_mstimestamp() { + return avr_ustimestamp()/1000; +} + +// Return s since program start as double +double avr_timestamp() { + return avr_ustimestamp()/1e6; +} + + int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data) { @@ -544,7 +576,6 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM OPCODE * writeop; int rc; int readok=0; - struct timeval tv; if (pgm->cmd == NULL) { pmsg_error("%s programmer uses avr_write_byte_default() but does not\n", pgm->type); @@ -706,8 +737,7 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM } } else { - gettimeofday (&tv, NULL); - start_time = (tv.tv_sec * 1000000) + tv.tv_usec; + start_time = avr_ustimestamp(); do { // Do polling, but timeout after max_write_delay rc = pgm->read_byte(pgm, p, mem, addr, &r); @@ -716,8 +746,7 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM pgm->err_led(pgm, ON); return -4; } - gettimeofday (&tv, NULL); - prog_time = (tv.tv_sec * 1000000) + tv.tv_usec; + prog_time = avr_ustimestamp(); } while (r != data && mem->max_write_delay >= 0 && prog_time - start_time < (unsigned long) mem->max_write_delay); } @@ -1399,7 +1428,6 @@ void report_progress(int completed, int total, const char *hdr) { static int last; static double start_time; int percent; - struct timeval tv; double t; if (update_progress == NULL) @@ -1410,8 +1438,7 @@ void report_progress(int completed, int total, const char *hdr) { completed < 0? 0: completed < INT_MAX/100? 100*completed/total: completed/(total/100); - gettimeofday(&tv, NULL); - t = tv.tv_sec + ((double)tv.tv_usec)/1000000; + t = avr_timestamp(); if(hdr || !start_time) start_time = t; diff --git a/src/jtagmkII.c b/src/jtagmkII.c index 6cc5e01f..1a157afa 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -481,14 +481,12 @@ static int jtagmkII_recv_frame(const PROGRAMMER *pgm, unsigned char **msg, unsigned char c, *buf = NULL, header[8]; unsigned short r_seqno = 0; - struct timeval tv; double timeoutval = 100; /* seconds */ double tstart, tnow; pmsg_trace("jtagmkII_recv():\n"); - gettimeofday(&tv, NULL); - tstart = tv.tv_sec; + tstart = avr_timestamp(); while ( (state != sDONE ) && (!timeout) ) { if (state == sDATA) { @@ -583,8 +581,7 @@ static int jtagmkII_recv_frame(const PROGRAMMER *pgm, unsigned char **msg, return -5; } - gettimeofday(&tv, NULL); - tnow = tv.tv_sec; + tnow = avr_timestamp(); if (tnow - tstart > timeoutval) { pmsg_error("timeout\n"); free(buf); diff --git a/src/libavrdude.h b/src/libavrdude.h index cb01f7a8..e86407c3 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -886,6 +886,12 @@ int avr_read(const PROGRAMMER * pgm, const AVRPART *p, const char *memtype, cons int avr_write_page(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr); +unsigned long avr_ustimestamp(); + +unsigned long avr_mstimestamp(); + +double avr_timestamp(); + int avr_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data); diff --git a/src/main.c b/src/main.c index 86291013..691369cf 100644 --- a/src/main.c +++ b/src/main.c @@ -499,6 +499,8 @@ int main(int argc, char * argv []) char * logfile; /* Use logfile rather than stderr for diagnostics */ enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */ + (void) avr_ustimestamp(); + #ifdef _MSC_VER _set_printf_count_output(1); #endif diff --git a/src/serialupdi.c b/src/serialupdi.c index cdff0a0a..5d221f88 100644 --- a/src/serialupdi.c +++ b/src/serialupdi.c @@ -207,18 +207,15 @@ static int serialupdi_wait_for_unlock(const PROGRAMMER *pgm, unsigned int ms) { */ unsigned long start_time; unsigned long current_time; - struct timeval tv; uint8_t status; - gettimeofday (&tv, NULL); - start_time = (tv.tv_sec * 1000000) + tv.tv_usec; + start_time = avr_ustimestamp(); do { if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) { if (!(status & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS))) { return 0; } } - gettimeofday (&tv, NULL); - current_time = (tv.tv_sec * 1000000) + tv.tv_usec; + current_time = avr_ustimestamp(); } while ((current_time - start_time) < (ms * 1000)); pmsg_error("timeout waiting for device to unlock\n"); @@ -256,10 +253,8 @@ static int serialupdi_wait_for_urow(const PROGRAMMER *pgm, unsigned int ms, urow */ unsigned long start_time; unsigned long current_time; - struct timeval tv; uint8_t status; - gettimeofday (&tv, NULL); - start_time = (tv.tv_sec * 1000000) + tv.tv_usec; + start_time = avr_ustimestamp(); do { if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) { if (mode == WAIT_FOR_UROW_HIGH) { @@ -272,8 +267,7 @@ static int serialupdi_wait_for_urow(const PROGRAMMER *pgm, unsigned int ms, urow } } } - gettimeofday (&tv, NULL); - current_time = (tv.tv_sec * 1000000) + tv.tv_usec; + current_time = avr_ustimestamp(); } while ((current_time - start_time) < (ms * 1000)); pmsg_error("timeout waiting for device to complete UROW WRITE\n"); diff --git a/src/stk500v2.c b/src/stk500v2.c index 6a6085a1..bb086c10 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -603,7 +603,6 @@ static int stk500v2_recv(const PROGRAMMER *pgm, unsigned char *msg, size_t maxsi * https://savannah.nongnu.org/bugs/index.php?43626 */ long timeoutval = SERIAL_TIMEOUT; // seconds - struct timeval tv; double tstart, tnow; if (PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || @@ -616,8 +615,7 @@ static int stk500v2_recv(const PROGRAMMER *pgm, unsigned char *msg, size_t maxsi DEBUG("STK500V2: stk500v2_recv(): "); - gettimeofday(&tv, NULL); - tstart = tv.tv_sec; + tstart = avr_timestamp(); while ( (state != sDONE ) && (!timeout) ) { if (serial_recv(&pgm->fd, &c, 1) < 0) @@ -690,9 +688,8 @@ static int stk500v2_recv(const PROGRAMMER *pgm, unsigned char *msg, size_t maxsi return -5; } /* switch */ - gettimeofday(&tv, NULL); - tnow = tv.tv_sec; - if (tnow-tstart > timeoutval) { // wuff - signed/unsigned/overflow + tnow = avr_timestamp(); + if (tnow-tstart > timeoutval) { timedout: pmsg_error("timeout\n"); return -1; diff --git a/src/updi_nvm.c b/src/updi_nvm.c index 93118437..a853b6c2 100644 --- a/src/updi_nvm.c +++ b/src/updi_nvm.c @@ -1201,10 +1201,8 @@ int updi_nvm_wait_ready(const PROGRAMMER *pgm, const AVRPART *p) { */ unsigned long start_time; unsigned long current_time; - struct timeval tv; uint8_t status; - gettimeofday (&tv, NULL); - start_time = (tv.tv_sec * 1000000) + tv.tv_usec; + start_time = avr_ustimestamp(); do { if (updi_read_byte(pgm, p->nvm_base + UPDI_NVMCTRL_STATUS, &status) >= 0) { if (status & (1 << UPDI_NVM_STATUS_WRITE_ERROR)) { @@ -1216,8 +1214,7 @@ int updi_nvm_wait_ready(const PROGRAMMER *pgm, const AVRPART *p) { return 0; } } - gettimeofday (&tv, NULL); - current_time = (tv.tv_sec * 1000000) + tv.tv_usec; + current_time = avr_ustimestamp(); } while ((current_time - start_time) < 10000000); pmsg_error("wait NVM ready timed out\n"); From 3a5f3735baadbf9bdf14130ce2fbb604b8f1db13 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 26 Nov 2022 12:54:42 +0000 Subject: [PATCH 3/8] Adapt urclock_getsync() to consider legacy bootloaders --- src/urclock.c | 86 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/src/urclock.c b/src/urclock.c index 3e03f193..f4b90214 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -308,7 +308,8 @@ typedef struct { nofilename, // Don't store application filename when writing the application nodate, // Don't store application filename and no date either nometadata, // Don't store any metadata at all (implies no store support) - delay; // Additional delay [ms] after resetting the board, can be negative + delay, // Additional delay [ms] after resetting the board, can be negative + strict; // Use strict synchronisation protocol char title[254]; // Use instead of filename for metadata - same size as filename char iddesc[64]; // Location of Urclock ID, eg F.12324.6 or E.-4.4 (default E.257.6) @@ -1153,6 +1154,7 @@ static void guessblstart(const PROGRAMMER *pgm, const AVRPART *p) { { 256, 0, 0x1451061b, 0x1451061b }, // picobootArduino168v3b2.hex { 512, 0, 0x3242ddd3, 0x53348738 }, // picobootArduino328.hex { 512, 0, 0x858e12de, 0xc80a44a4 }, // picobootArduino328v3beta.hex + { 512, 0, 0x3242ddd3, 0xc254e344 }, // picobootArduino328v3b2.hex { 256, 0, 0xaa62bafc, 0xaa62bafc }, // picobootArduino8v3rc1.hex { 256, 0, 0x56263965, 0x56263965 }, // picobootSTK500-168p.hex { 512, 0, 0x3242ddd3, 0x5ba5f5f6 }, // picobootSTK500-328p.hex @@ -1870,7 +1872,7 @@ static int urclock_recv(const PROGRAMMER *pgm, unsigned char *buf, size_t len) { rv = serial_recv(&pgm->fd, buf, len); if(rv < 0) { if(!ur.sync_silence) - pmsg_warning("programmer is not responding%s\n", ur.uP.name? "": "; try, eg, -xdelay=200"); + pmsg_error("programmer is not responding; try and vary -xdelay=100 and/or -xstrict\n"); return -1; } @@ -1878,7 +1880,7 @@ static int urclock_recv(const PROGRAMMER *pgm, unsigned char *buf, size_t len) { } -#define MAX_SYNC_ATTEMPTS 23 +#define MAX_SYNC_ATTEMPTS 16 /* * The modified protocol makes stk_insync and stk_ok responses variable but fixed for a single @@ -1887,37 +1889,78 @@ static int urclock_recv(const PROGRAMMER *pgm, unsigned char *buf, size_t len) { * sync until the stk_insync/ok responses coincide with the the most recent responses. */ static int urclock_getsync(const PROGRAMMER *pgm) { - unsigned char iob[2]; + unsigned char iob[2], autobaud_sync; int attempt; + AVRPART *part; // Reduce timeout for establishing comms - serial_recv_timeout = 80; // ms + serial_recv_timeout = 10; // ms + part = partdesc? locate_part(part_list, partdesc): NULL; + /* + * The urboot autosync detection uses a loop + * + * 2: adiw r26, 32 + * sbis RX_Pin_Port,RX_Bit + * rjmp 2 + * + * The number of cycles in this loop must be the position of the least significant set bit of the + * first byte sent by AVRDUDE. For a 5-cycle loop (ATmega*) the fifth-lowest bit must be set and + * the four least significant bit unset, eg, 0x30, which by coincidence is Cmnd_STK_GET_SYNC. For + * ATxmega* parts, the sync byte could be 0x20. For LGT8F* parts this loop has three cycles, so + * 0x1c would be appropriate. Care must be taken to not choose a sync byte that is an otherwise + * legitimate command, ie nothing avove 0x30 or below 0x10 should be chosen. + */ + autobaud_sync = part && part->autobaud_sync? part->autobaud_sync: Cmnd_STK_GET_SYNC; ur.sync_silence = 1; - iob[0] = Cmnd_STK_GET_SYNC; // Initial sync for autobaud - drain response - iob[1] = Sync_CRC_EOP; - urclock_send(pgm, iob, 2); - serial_drain(&pgm->fd, 0); for(attempt = 0; attempt < MAX_SYNC_ATTEMPTS; attempt++) { - iob[0] = Cmnd_STK_GET_SYNC; + /* + * The initial byte for autobaud must be the sync byte/Sync_CRC_EOP sequence; thereafter it + * should normally be Cmnd_STK_GET_SYNC/Sync_CRC_EOP. However, both urboot and optiboot are + * "permissive" as to the get sync command: anything that is not a valid, known command is + * acceptable. However, these are less permissive when it comes to the End of command byte + * Sync_CRC_EOP: if that is wrong the bootloader swiftly enters the application. Old but + * popular optiboot v4.4 first initialises the USART and *then* entertains the user for 300 ms + * with a flashing LED, which means that AVRDUDE's initial 2-byte sync sequence will appear as + * one byte Sync_CRC_EOP (because the first byte is overwritten) getting the communication out + * of step through a missing byte. If AVRDUDE then sends the next request starting with a + * Cmnd_STK_GET_SYNC command then optiboot v4.4 will bail as ist's not Sync_CRC_EOP. Hence, the + * strategy here is to send Sync_CRC_EOP/Sync_CRC_EOP for getting a sync. For those bootloaders + * that are strict about the protocol, eg, picoboot, the presence of -xstrict implies that + * comms should use Cmnd_STK_GET_SYNC for getting in sync. + */ + iob[0] = attempt == 0? autobaud_sync: ur.strict? Cmnd_STK_GET_SYNC: Sync_CRC_EOP; iob[1] = Sync_CRC_EOP; urclock_send(pgm, iob, 2); if(urclock_recv(pgm, iob, 2) == 0) { // Expect bootloader to respond with two bytes if(!ur.gs.seen || iob[0] != ur.gs.stk_insync || iob[1] != ur.gs.stk_ok || iob[0] == iob[1]) { ur.gs.stk_insync = iob[0]; ur.gs.stk_ok = iob[1]; - if(ur.gs.seen) - serial_drain(&pgm->fd, 0); ur.gs.seen = 1; } else break; + } else { // Board not yet out of reset or bootloader twiddles lights + int slp = 32<<(attempt<3? attempt: 3); + pmsg_debug("%4d ms: sleeping for %d ms\n", avr_mstimestamp(), slp); + usleep(slp*1000); } - if(attempt > 2) { // Don't report first three attempts + if(attempt > 5) { // Don't report first six attempts ur.sync_silence = 0; - pmsg_warning("attempt %d of %d: not in sync\n", attempt - 2, MAX_SYNC_ATTEMPTS-3); + pmsg_warning("attempt %d of %d: not in sync\n", attempt - 5, MAX_SYNC_ATTEMPTS-6); } } + + if(!ur.strict) { // Could be out of step by one byte + iob[0] = Sync_CRC_EOP; + urclock_send(pgm, iob, 1); // If so must send EOP + if(urclock_recv(pgm, iob, 1) < 0) { + iob[0] = Sync_CRC_EOP; // No reply: we were not out of step, but are now + urclock_send(pgm, iob, 1); // So, send the concluding byte + } + } + serial_drain(&pgm->fd, 0); // And either way drain the reply + ur.sync_silence = 0; serial_recv_timeout = 500; // ms @@ -1943,7 +1986,7 @@ static int urclock_getsync(const PROGRAMMER *pgm) { ur.urfeatures = UB_FEATURES(bootinfo); ur.urprotocol = 1; - set_uP(pgm, partdesc? locate_part(part_list, partdesc): NULL, mcuid, 1); + set_uP(pgm, part, mcuid, 1); if(!ur.uP.name) Return("cannot identify MCU"); if(!partdesc) // Provide partdesc info, so user does not have to set it @@ -2148,15 +2191,17 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) { // Set DTR and RTS back to high serial_set_dtr_rts(&pgm->fd, 1); - if((80+ur.delay) > 0) - usleep((80+ur.delay)*1000); // Wait until board comes out of reset + if((110+ur.delay) > 0) + usleep((110+ur.delay)*1000); // Wait until board comes out of reset // Drain any extraneous input - serial_drain_timeout = 80; // ms + serial_drain_timeout = 20; // ms serial_drain(&pgm->fd, 0); + pmsg_debug("%4d ms: enter urclock_getsync()\n", avr_mstimestamp()); if(urclock_getsync(pgm) < 0) return -1; + pmsg_debug("%4d ms: all good, ready to rock\n", avr_mstimestamp()); return 0; } @@ -2372,6 +2417,7 @@ static int urclock_parseextparms(const PROGRAMMER *pgm, LISTID extparms) { {"nodate", &ur.nodate, NA, "Do not store application filename and no date either"}, {"nometadata", &ur.nometadata, NA, "Do not store metadata at all (ie, no store support)"}, {"delay", &ur.delay, ARG, "Add delay [ms] after reset, can be negative"}, + {"strict", &ur.strict, NA, "Use strict synchronisation protocol"}, {"help", &help, NA, "Show this help menu and exit"}, }; @@ -2397,11 +2443,11 @@ static int urclock_parseextparms(const PROGRAMMER *pgm, LISTID extparms) { char *end; long ret = strtol(arg, &end, 0); if(*end || end == arg) { - pmsg_error("cannot parse -x%s\n", arg); + pmsg_error("cannot parse -x%s\n", extended_param); return -1; } if((int) ret != ret) { - pmsg_error("out of integer range -x%s\n", arg); + pmsg_error("out of integer range -x%s\n", extended_param); return -1; } *options[i].optionp = ret; From d774e87a59663c9db1a95e37b61a8feda7505ea0 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 26 Nov 2022 13:23:25 +0000 Subject: [PATCH 4/8] Update documentation re the urclock programmer --- src/avrdude.1 | 19 ++++--- src/doc/avrdude.texi | 123 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 8 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index efdaff5d..25c42263 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -158,7 +158,7 @@ to be backwards compatible with STK500 v1.x, and allows bootloaders to be much smaller, eg, as implemented in the urboot project https://github.com/stefanrueger/urboot. The programmer type ``urclock'' caters for these urboot programmers. Owing to its backward compatibility, -any bootloader that can be served by the arduino programmer can normally +bootloaders that can be served by the arduino programmer can normally also be served by the urclock programmer. .Pp The BusPirate is a versatile tool that can also be used as an AVR programmer. @@ -1174,7 +1174,9 @@ Urclock ID can be between 1 and 8 bytes. .It Ar showdate Show the last-modified date of the input file for the flash application, then exit. If the input file was stdin, the date will be that of the -programming. +programming. Date and filename are part of the metadata that the urclock +programmer stores by default in high flash just under the bootloader; see also +-xnometadata. .It Ar showfilename Show the input filename (or title) of the last flash writing session, then exit. .It Ar title= @@ -1200,9 +1202,10 @@ just behind the vector table with the name VBL_ADDITIONAL_VECTOR. .It Ar showpart Show the part for which the bootloader was compiled, then exit. .It Ar bootsize= -Manual override for bootloader size. Urboot bootloaders put the number of used -bootloader pages into a table at the top of flash, so the urclock programmer can -look up the bootloader size itself. In backward-compatibility mode, when programming +Manual override for bootloader size. Urboot bootloaders put the number of +used bootloader pages into a table at the top of the bootloader section, +ie, typically top of flash, so the urclock programmer can look up the +bootloader size itself. In backward-compatibility mode, when programming via other bootloaders, this option can be used to tell the programmer the size, and therefore the location, of the bootloader. .It Ar vectornum= @@ -1250,8 +1253,12 @@ frame is programmed. .It Ar delay= Add a ms delay after reset. This can be useful if a board takes a particularly long time to exit from external reset. can be negative, -in which case the default 80 ms delay after issuing reset will be +in which case the default 110 ms delay after issuing reset will be shortened accordingly. +.It Ar strict +Urclock has a faster, but slightly different strategy than -c arduino to +synchronise with the bootloader; some stk500v1 bootloaders cannot cope +with this, and they need the -xstrict option. .It Ar help Show this help menu and exit .El diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 6127b936..a086c2ae 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -280,14 +280,22 @@ the -D option will likely be required in this case, because the bootloader will rewrite the program memory, but no true chip erase can be performed. -The Arduino (which is very similar to the STK500 1.x) is supported via -its own programmer type specification ``arduino''. This programmer works for +Serial bootloaders that run a skeleton of the STK500 1.x protocol are supported via +their own programmer type specification ``arduino''. This programmer works for the Arduino Uno Rev3 or any AVR that runs the Optiboot bootloader. The number of connection retry attempts can be specified as an extended parameter. See the section on @emph{extended parameters} below for details. +Urprotocol is a leaner version of the STK500 1.x protocol that is designed +to be backwards compatible with STK500 v1.x; it allows bootloaders to be +much smaller, eg, as implemented in the urboot project +@uref{https://github.com/stefanrueger/urboot}. The programmer type ``urclock'' +caters for these urboot programmers. Owing to its backward compatibility, +bootloaders that can be served by the arduino programmer can normally +also be served by the urclock programmer. + The BusPirate is a versatile tool that can also be used as an AVR programmer. A single BusPirate can be connected to up to 3 independent AVRs. See the section on @@ -940,6 +948,117 @@ The Arduino programmer type accepts the following extended parameter: Overide the default number of connection retry attempt by using @var{VALUE}. @end table +@cindex @code{-x} Urclock +@item Urclock + +The urclock programmer type accepts the following extended parameters: +@table @code +@item @samp{showall} +Show all info for the connected part, then exit. The @code{-xshow...} options +below can be used to assemble a bespoke response consisting of a subset +(or only one item) of all available relevant information about the +connected part and bootloader. +@item @samp{showid} +Show a unique Urclock ID stored in either flash or EEPROM of the MCU, then exit. +@item @samp{id=..} +Historically, the Urclock ID was a six-byte unique little-endian number +stored in Urclock boards at EEPROM address 257. The location of this +number can be set by the @code{-xid=..} extended parameter. @code{E} +stands for EEPROM and @code{F} stands for flash. A negative address addr counts +from the end of EEPROM and flash, respectively. The length len of the +Urclock ID can be between 1 and 8 bytes. +@item @samp{showdate} +Show the last-modified date of the input file for the flash application, +then exit. If the input file was stdin, the date will be that of the +programming. Date and filename are part of the metadata that the urclock +programmer stores by default in high flash just under the bootloader; see also +@code{-xnometadata}. +@item @samp{showfilename} +Show the input filename (or title) of the last flash writing session, then exit. +@item @samp{title=} +When set, will be used in lieu of the input filename. The maximum +string length for the title/filename field is 254 bytes including +terminating nul. +@item @samp{showapp} +Show the size of the programmed application, then exit. +@item @samp{showstore} +Show the size of the unused flash between the application and metadata, then exit. +@item @samp{showmeta} +Show the size of the metadata just below the bootloader, then exit. +@item @samp{showboot} +Show the size of the bootloader, then exit. +@item @samp{showversion} +Show bootloader version and capabilities, then exit. +@item @samp{showvector} +Show the vector number and name of the interrupt table vector used by the +bootloader for starting the application, then exit. For hardware-supported +bootloaders this will be vector 0 (Reset), and for vector bootloaders this +will be any other vector number of the interrupt vector table or the slot +just behind the vector table with the name @code{VBL_ADDITIONAL_VECTOR}. +@item @samp{showpart} +Show the part for which the bootloader was compiled, then exit. +@item @samp{bootsize=} +Manual override for bootloader size. Urboot bootloaders put the number of +used bootloader pages into a table at the top of the bootloader section, +ie, typically top of flash, so the urclock programmer can look up the +bootloader size itself. In backward-compatibility mode, when programming +via other bootloaders, this option can be used to tell the programmer the +size, and therefore the location, of the bootloader. +@item @samp{vectornum=} +Manual override for vector number. Urboot bootloaders put the vector +number used by a vector bootloader into a table at the top of flash, so +this option is normally not needed for urboot bootloaders. However, it is +useful in backward-compatibility mode (or when the urboot bootloader does +not offer flash read). Specifying a vector number in these circumstances +implies a vector bootloader whilst the default assumption would be a +hardware-supported bootloader. +@item @samp{eepromrw} +Manual override for asserting EEPROM read/write capability. Not normally +needed for urboot bootloaders, but useful for in backward-compatibility +mode if the bootloader offers EEPROM read/write. +@item @samp{emulate_ce} +If an urboot bootloader does not offer a chip erase command it will tell +the urclock programmer so during handshake. In this case the urclock +programmer emulates a chip erase, if warranted by user command line +options, by filling the remainder of unused flash below the bootloader +with 0xff. If this option is specified, the urclock programmer will assume +that the bootloader cannot erase the chip itself. The option is useful +for backwards-compatible bootloaders that do not implement chip erase. +@item @samp{restore} +Upload unchanged flash input files and trim below the bootloader if +needed. This is most useful when one has a backup of the full flash and +wants to play that back onto the device. No metadata are written in this +case and no vector patching happens either if it is a vector bootloader. +However, for vector bootloaders, even under the option @code{-xrestore} an +input file will not be uploaded for which the reset vector does not point +to the vector bootloader. This is to avoid writing an input file to the +device that would render the vector bootloader not functional as it would +not be reached after reset. +@item @samp{initstore} +On writing to flash fill the store space between the flash application and +the metadata section with 0xff. +@item @samp{nofilename} +On writing to flash do not store the application input filename (nor a title). +@item @samp{nodate} +On writing to flash do not store the application input filename (nor a +title) and no date either. +@item @samp{nometadata} +On writing to flash do not store any metadata. The full flash below the +bootloader is available for the application. In particular, no data store +frame is programmed. +@item @samp{delay=} +Add a ms delay after reset. This can be useful if a board takes a +particularly long time to exit from external reset. can be negative, +in which case the default 110 ms delay after issuing reset will be +shortened accordingly. +@item @samp{strict} +Urclock has a faster, but slightly different strategy than -c arduino to +synchronise with the bootloader; some stk500v1 bootloaders cannot cope +with this, and they need the @code{-xstrict} option. +@item @samp{help} +Show this help menu and exit +@end table + @cindex @code{-x} Buspirate @item BusPirate From 0e0a0ba0eb28b99b0af71e7318b7d5204fedff47 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 26 Nov 2022 13:53:46 +0000 Subject: [PATCH 5/8] Get boot section info from avrdude.conf and not from avrintel.c --- src/avrcache.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/avrcache.c b/src/avrcache.c index 638ac46f..98370827 100644 --- a/src/avrcache.c +++ b/src/avrcache.c @@ -318,12 +318,8 @@ static int guessBootStart(const PROGRAMMER *pgm, const AVRPART *p) { int bootstart = 0; const AVR_Cache *cp = pgm->cp_flash; - for(size_t i = 0; i < sizeof uP_table/sizeof*uP_table; i++) - if(p->mcuid == uP_table[i].mcuid) { - if(uP_table[i].nboots > 0 && uP_table[i].bootsize > 0 && uP_table[i].flashsize == cp->size) - bootstart = cp->size - uP_table[i].nboots * uP_table[i].bootsize; - break; - } + if(p->n_boot_sections > 0 && p->boot_section_size > 0) + bootstart = cp->size - (p->boot_section_size<<(p->n_boot_sections-1)); if(bootstart <= cp->size/2 || bootstart >= cp->size) bootstart = cp->size > 32768? cp->size - 16384: cp->size*3/4; From 0c96f5d6dc376ecd0e1f6c0ddfbaa2826b8caecc Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 27 Nov 2022 13:57:37 +0000 Subject: [PATCH 6/8] Calibrate urboot's -xdelay for windows --- src/avrdude.1 | 2 +- src/doc/avrdude.texi | 2 +- src/urclock.c | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index 25c42263..660f21c8 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1253,7 +1253,7 @@ frame is programmed. .It Ar delay= Add a ms delay after reset. This can be useful if a board takes a particularly long time to exit from external reset. can be negative, -in which case the default 110 ms delay after issuing reset will be +in which case the default 110-140 ms delay after issuing reset will be shortened accordingly. .It Ar strict Urclock has a faster, but slightly different strategy than -c arduino to diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index a086c2ae..71e1e272 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1049,7 +1049,7 @@ frame is programmed. @item @samp{delay=} Add a ms delay after reset. This can be useful if a board takes a particularly long time to exit from external reset. can be negative, -in which case the default 110 ms delay after issuing reset will be +in which case the default 110-140 ms delay after issuing reset will be shortened accordingly. @item @samp{strict} Urclock has a faster, but slightly different strategy than -c arduino to diff --git a/src/urclock.c b/src/urclock.c index f4b90214..45f9d9e7 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -1872,7 +1872,7 @@ static int urclock_recv(const PROGRAMMER *pgm, unsigned char *buf, size_t len) { rv = serial_recv(&pgm->fd, buf, len); if(rv < 0) { if(!ur.sync_silence) - pmsg_error("programmer is not responding; try and vary -xdelay=100 and/or -xstrict\n"); + pmsg_error("programmer is not responding; try -xstrict and/or vary -xdelay=100\n"); return -1; } @@ -2191,8 +2191,13 @@ static int urclock_open(PROGRAMMER *pgm, const char *port) { // Set DTR and RTS back to high serial_set_dtr_rts(&pgm->fd, 1); +#ifndef WIN32 if((110+ur.delay) > 0) usleep((110+ur.delay)*1000); // Wait until board comes out of reset +#else + if((137+ur.delay) > 0) + usleep((137+ur.delay)*1000); // Wait until board starts up accommodating effective drain time +#endif // Drain any extraneous input serial_drain_timeout = 20; // ms From 5a0975aee732e0be99f485d7de39341a2c18deea Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 27 Nov 2022 14:44:46 +0000 Subject: [PATCH 7/8] Allow / as path deliminator in Windows for urclock metadata --- src/urclock.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/urclock.c b/src/urclock.c index 45f9d9e7..f2710b20 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -545,11 +545,10 @@ static void set_date_filename(const PROGRAMMER *pgm, const char *fname) { else { ur.filename[0] = 0; if(fname && *fname) { -#if !defined (WIN32) if((base=strrchr(fname, '/'))) base++; -#else - if((base=strrchr(fname, '\\'))) +#ifdef WIN32 + else if((base=strrchr(fname, '\\'))) base++; #endif else From 58e2bca42cfb0944a69dfa9254338d3ac43bc83f Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 27 Nov 2022 16:56:49 +0000 Subject: [PATCH 8/8] Update n_interrupts in avrdude.conf.in and introduce eind --- src/avrdude.conf.in | 69 +++++++++++++++++++++++++++++++++++++++----- src/config.c | 5 ++++ src/config_gram.y | 28 ------------------ src/developer_opts.c | 3 +- src/doc/avrdude.texi | 1 + src/lexer.l | 6 +--- src/libavrdude.h | 1 + 7 files changed, 72 insertions(+), 41 deletions(-) diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index b97e4479..43d51de7 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -137,6 +137,7 @@ # rampz = ; # IO addr of RAMPZ reg # spmcr = ; # mem addr of SPMC[S]R reg # eecr = ; # mem addr of EECR reg only when != 0x3f +# eind = ; # mem addr of EIND reg # mcu_base = ; # nvm_base = ; # ocd_base = ; @@ -4677,6 +4678,7 @@ part parent "m324p" desc = "ATmega324PB"; id = "m324pb"; mcuid = 113; + n_interrupts = 51; signature = 0x1e 0x95 0x17; ; @@ -9436,7 +9438,6 @@ part parent "m1280" desc = "ATmega1281"; id = "m1281"; mcuid = 139; - n_interrupts = 51; signature = 0x1e 0x97 0x04; ; @@ -9574,7 +9575,6 @@ part parent "m2560" desc = "ATmega2561"; id = "m2561"; mcuid = 144; - n_interrupts = 51; signature = 0x1e 0x98 0x02; ; @@ -10878,6 +10878,7 @@ part programlockpolltimeout = 5; spmcr = 0x57; eecr = 0x3f; + eind = 0x5c; ocdrev = 1; chip_erase = "1010.1100--100x.xxxx--xxxx.xxxx--xxxx.xxxx"; pgm_enable = "1010.1100--0101.0011--xxxx.xxxx--xxxx.xxxx"; @@ -10968,7 +10969,7 @@ part id = "usb82"; prog_modes = PM_SPM | PM_ISP | PM_HVPP | PM_debugWIRE; mcuid = 174; - n_interrupts = 58; + n_interrupts = 29; n_boot_sections = 4; boot_section_size = 512; chip_erase_delay = 9000; @@ -11002,6 +11003,7 @@ part programlockpolltimeout = 5; spmcr = 0x57; eecr = 0x3f; + eind = 0x5c; ocdrev = 1; chip_erase = "1010.1100--100x.xxxx--xxxx.xxxx--xxxx.xxxx"; pgm_enable = "1010.1100--0101.0011--xxxx.xxxx--xxxx.xxxx"; @@ -11126,6 +11128,7 @@ part programlockpolltimeout = 5; spmcr = 0x57; eecr = 0x3f; + eind = 0x5c; ocdrev = 1; chip_erase = "1010.1100--100x.xxxx--xxxx.xxxx--xxxx.xxxx"; pgm_enable = "1010.1100--0101.0011--xxxx.xxxx--xxxx.xxxx"; @@ -11250,6 +11253,7 @@ part programlockpolltimeout = 5; spmcr = 0x57; eecr = 0x3f; + eind = 0x5c; ocdrev = 1; chip_erase = "1010.1100--100x.xxxx--xxxx.xxxx--xxxx.xxxx"; pgm_enable = "1010.1100--0101.0011--xxxx.xxxx--xxxx.xxxx"; @@ -11340,7 +11344,7 @@ part id = "m8u2"; prog_modes = PM_SPM | PM_ISP | PM_HVPP | PM_debugWIRE; mcuid = 48; - n_interrupts = 58; + n_interrupts = 29; n_boot_sections = 4; boot_section_size = 512; chip_erase_delay = 9000; @@ -11374,6 +11378,7 @@ part programlockpolltimeout = 5; spmcr = 0x57; eecr = 0x3f; + eind = 0x5c; ocdrev = 1; chip_erase = "1010.1100--100x.xxxx--xxxx.xxxx--xxxx.xxxx"; pgm_enable = "1010.1100--0101.0011--xxxx.xxxx--xxxx.xxxx"; @@ -11620,7 +11625,7 @@ part id = "m325"; prog_modes = PM_SPM | PM_ISP | PM_HVPP | PM_JTAG; mcuid = 114; - n_interrupts = 23; + n_interrupts = 22; n_boot_sections = 4; boot_section_size = 512; # stk500_devcode = 0x??; # No STK500v1 support? @@ -11767,7 +11772,6 @@ part parent "m325" desc = "ATmega325PA"; id = "m325pa"; mcuid = 117; - n_interrupts = 22; signature = 0x1e 0x95 0x0d; ; @@ -11780,7 +11784,7 @@ part id = "m645"; prog_modes = PM_SPM | PM_ISP | PM_HVPP | PM_JTAG; mcuid = 132; - n_interrupts = 23; + n_interrupts = 22; n_boot_sections = 4; boot_section_size = 1024; # stk500_devcode = 0x??; # No STK500v1 support? @@ -13565,6 +13569,7 @@ part parent ".reduced_core_tiny" desc = "ATtiny102"; id = "t102"; mcuid = 6; + n_interrupts = 16; signature = 0x1e 0x90 0x0c; memory "flash" @@ -13583,6 +13588,7 @@ part parent ".reduced_core_tiny" desc = "ATtiny104"; id = "t104"; mcuid = 7; + n_interrupts = 16; signature = 0x1e 0x90 0x0b; memory "flash" @@ -14531,6 +14537,7 @@ part parent ".avr8x_tiny" desc = "ATtiny424"; id = "t424"; mcuid = 292; + n_interrupts = 30; signature = 0x1e 0x92 0x2c; memory "eeprom" @@ -14556,6 +14563,7 @@ part parent ".avr8x_tiny" desc = "ATtiny426"; id = "t426"; mcuid = 293; + n_interrupts = 30; signature = 0x1e 0x92 0x2b; memory "eeprom" @@ -14581,6 +14589,7 @@ part parent ".avr8x_tiny" desc = "ATtiny427"; id = "t427"; mcuid = 294; + n_interrupts = 30; signature = 0x1e 0x92 0x2a; memory "eeprom" @@ -14606,6 +14615,7 @@ part parent ".avr8x_tiny" desc = "ATtiny824"; id = "t824"; mcuid = 301; + n_interrupts = 30; signature = 0x1e 0x93 0x29; memory "eeprom" @@ -14631,6 +14641,7 @@ part parent ".avr8x_tiny" desc = "ATtiny826"; id = "t826"; mcuid = 302; + n_interrupts = 30; signature = 0x1e 0x93 0x28; memory "eeprom" @@ -14656,6 +14667,7 @@ part parent ".avr8x_tiny" desc = "ATtiny827"; id = "t827"; mcuid = 303; + n_interrupts = 30; signature = 0x1e 0x93 0x27; memory "eeprom" @@ -14681,6 +14693,7 @@ part parent ".avr8x_tiny" desc = "ATtiny1624"; id = "t1624"; mcuid = 310; + n_interrupts = 30; signature = 0x1e 0x94 0x2a; memory "eeprom" @@ -14706,6 +14719,7 @@ part parent ".avr8x_tiny" desc = "ATtiny1626"; id = "t1626"; mcuid = 311; + n_interrupts = 30; signature = 0x1e 0x94 0x29; memory "eeprom" @@ -14731,6 +14745,7 @@ part parent ".avr8x_tiny" desc = "ATtiny1627"; id = "t1627"; mcuid = 312; + n_interrupts = 30; signature = 0x1e 0x94 0x28; memory "eeprom" @@ -14756,6 +14771,7 @@ part parent ".avr8x_tiny" desc = "ATtiny3224"; id = "t3224"; mcuid = 316; + n_interrupts = 30; signature = 0x1e 0x95 0x28; memory "eeprom" @@ -14781,6 +14797,7 @@ part parent ".avr8x_tiny" desc = "ATtiny3226"; id = "t3226"; mcuid = 317; + n_interrupts = 30; signature = 0x1e 0x95 0x27; memory "eeprom" @@ -14806,6 +14823,7 @@ part parent ".avr8x_tiny" desc = "ATtiny3227"; id = "t3227"; mcuid = 318; + n_interrupts = 30; signature = 0x1e 0x95 0x26; memory "eeprom" @@ -15198,6 +15216,7 @@ part parent ".avrdx" id = "avr32da28"; family_id = " AVR"; mcuid = 338; + n_interrupts = 41; signature = 0x1e 0x95 0x34; memory "eeprom" @@ -15223,6 +15242,7 @@ part parent ".avrdx" id = "avr32da32"; family_id = " AVR"; mcuid = 342; + n_interrupts = 44; signature = 0x1e 0x95 0x33; memory "eeprom" @@ -15248,6 +15268,7 @@ part parent ".avrdx" id = "avr32da48"; family_id = " AVR"; mcuid = 346; + n_interrupts = 58; signature = 0x1e 0x95 0x32; memory "eeprom" @@ -15273,6 +15294,7 @@ part parent ".avrdx" id = "avr64da28"; family_id = " AVR"; mcuid = 351; + n_interrupts = 41; signature = 0x1e 0x96 0x15; memory "eeprom" @@ -15298,6 +15320,7 @@ part parent ".avrdx" id = "avr64da32"; family_id = " AVR"; mcuid = 355; + n_interrupts = 44; signature = 0x1e 0x96 0x14; memory "eeprom" @@ -15323,6 +15346,7 @@ part parent ".avrdx" id = "avr64da48"; family_id = " AVR"; mcuid = 359; + n_interrupts = 58; signature = 0x1e 0x96 0x13; memory "eeprom" @@ -15348,6 +15372,7 @@ part parent ".avrdx" id = "avr64da64"; family_id = " AVR"; mcuid = 362; + n_interrupts = 64; signature = 0x1e 0x96 0x12; memory "eeprom" @@ -15373,6 +15398,7 @@ part parent ".avrdx" id = "avr128da28"; family_id = " AVR"; mcuid = 364; + n_interrupts = 41; signature = 0x1e 0x97 0x0a; memory "eeprom" @@ -15398,6 +15424,7 @@ part parent ".avrdx" id = "avr128da32"; family_id = " AVR"; mcuid = 366; + n_interrupts = 44; signature = 0x1e 0x97 0x09; memory "eeprom" @@ -15423,6 +15450,7 @@ part parent ".avrdx" id = "avr128da48"; family_id = " AVR"; mcuid = 368; + n_interrupts = 58; signature = 0x1e 0x97 0x08; memory "eeprom" @@ -15448,6 +15476,7 @@ part parent ".avrdx" id = "avr128da64"; family_id = " AVR"; mcuid = 370; + n_interrupts = 64; signature = 0x1e 0x97 0x07; memory "eeprom" @@ -15472,6 +15501,7 @@ part parent ".avrdx" desc = "AVR32DB28"; id = "avr32db28"; mcuid = 339; + n_interrupts = 42; signature = 0x1e 0x95 0x37; memory "eeprom" @@ -15496,6 +15526,7 @@ part parent ".avrdx" desc = "AVR32DB32"; id = "avr32db32"; mcuid = 343; + n_interrupts = 44; signature = 0x1e 0x95 0x36; memory "eeprom" @@ -15520,6 +15551,7 @@ part parent ".avrdx" desc = "AVR32DB48"; id = "avr32db48"; mcuid = 347; + n_interrupts = 61; signature = 0x1e 0x95 0x35; memory "eeprom" @@ -15544,6 +15576,7 @@ part parent ".avrdx" desc = "AVR64DB28"; id = "avr64db28"; mcuid = 352; + n_interrupts = 42; signature = 0x1e 0x96 0x19; memory "eeprom" @@ -15568,6 +15601,7 @@ part parent ".avrdx" desc = "AVR64DB32"; id = "avr64db32"; mcuid = 356; + n_interrupts = 44; signature = 0x1e 0x96 0x18; memory "eeprom" @@ -15592,6 +15626,7 @@ part parent ".avrdx" desc = "AVR64DB48"; id = "avr64db48"; mcuid = 360; + n_interrupts = 61; signature = 0x1e 0x96 0x17; memory "eeprom" @@ -15616,6 +15651,7 @@ part parent ".avrdx" desc = "AVR64DB64"; id = "avr64db64"; mcuid = 363; + n_interrupts = 65; signature = 0x1e 0x96 0x16; memory "eeprom" @@ -15640,6 +15676,7 @@ part parent ".avrdx" desc = "AVR128DB28"; id = "avr128db28"; mcuid = 365; + n_interrupts = 42; signature = 0x1e 0x97 0x0e; memory "eeprom" @@ -15664,6 +15701,7 @@ part parent ".avrdx" desc = "AVR128DB32"; id = "avr128db32"; mcuid = 367; + n_interrupts = 44; signature = 0x1e 0x97 0x0d; memory "eeprom" @@ -15688,6 +15726,7 @@ part parent ".avrdx" desc = "AVR128DB48"; id = "avr128db48"; mcuid = 369; + n_interrupts = 61; signature = 0x1e 0x97 0x0c; memory "eeprom" @@ -15712,6 +15751,7 @@ part parent ".avrdx" desc = "AVR128DB64"; id = "avr128db64"; mcuid = 371; + n_interrupts = 65; signature = 0x1e 0x97 0x0b; memory "eeprom" @@ -15736,6 +15776,7 @@ part parent ".avrdx" desc = "AVR16DD14"; id = "avr16dd14"; mcuid = 329; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x94 0x34; @@ -15761,6 +15802,7 @@ part parent ".avrdx" desc = "AVR16DD20"; id = "avr16dd20"; mcuid = 330; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x94 0x33; @@ -15786,6 +15828,7 @@ part parent ".avrdx" desc = "AVR16DD28"; id = "avr16dd28"; mcuid = 331; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x94 0x32; @@ -15811,6 +15854,7 @@ part parent ".avrdx" desc = "AVR16DD32"; id = "avr16dd32"; mcuid = 333; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x94 0x31; @@ -15836,6 +15880,7 @@ part parent ".avrdx" desc = "AVR32DD14"; id = "avr32dd14"; mcuid = 336; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x95 0x3b; @@ -15861,6 +15906,7 @@ part parent ".avrdx" desc = "AVR32DD20"; id = "avr32dd20"; mcuid = 337; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x95 0x3a; @@ -15886,6 +15932,7 @@ part parent ".avrdx" desc = "AVR32DD28"; id = "avr32dd28"; mcuid = 340; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x95 0x39; @@ -15911,6 +15958,7 @@ part parent ".avrdx" desc = "AVR32DD32"; id = "avr32dd32"; mcuid = 344; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x95 0x38; @@ -15936,6 +15984,7 @@ part parent ".avrdx" desc = "AVR64DD14"; id = "avr64dd14"; mcuid = 349; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x96 0x1d; @@ -15961,6 +16010,7 @@ part parent ".avrdx" desc = "AVR64DD20"; id = "avr64dd20"; mcuid = 350; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x96 0x1c; @@ -15986,6 +16036,7 @@ part parent ".avrdx" desc = "AVR64DD28"; id = "avr64dd28"; mcuid = 353; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x96 0x1b; @@ -16011,6 +16062,7 @@ part parent ".avrdx" desc = "AVR64DD32"; id = "avr64dd32"; mcuid = 357; + n_interrupts = 36; hvupdi_variant = 2; signature = 0x1e 0x96 0x1a; @@ -16257,6 +16309,7 @@ part parent ".avrex" desc = "AVR64EA28"; id = "avr64ea28"; mcuid = 354; + n_interrupts = 37; signature = 0x1e 0x96 0x20; memory "eeprom" @@ -16282,6 +16335,7 @@ part parent ".avrex" desc = "AVR64EA32"; id = "avr64ea32"; mcuid = 358; + n_interrupts = 37; signature = 0x1e 0x96 0x1f; memory "eeprom" @@ -16307,6 +16361,7 @@ part parent ".avrex" desc = "AVR64EA48"; id = "avr64ea48"; mcuid = 361; + n_interrupts = 45; signature = 0x1e 0x96 0x1e; memory "eeprom" diff --git a/src/config.c b/src/config.c index 2c512d00..9f5d9122 100644 --- a/src/config.c +++ b/src/config.c @@ -73,6 +73,11 @@ Component_t avr_comp[] = { part_comp_desc(n_boot_sections, COMP_INT), part_comp_desc(boot_section_size, COMP_INT), part_comp_desc(autobaud_sync, COMP_CHAR), + part_comp_desc(idr, COMP_CHAR), + part_comp_desc(rampz, COMP_CHAR), + part_comp_desc(spmcr, COMP_CHAR), + part_comp_desc(eecr, COMP_CHAR), + part_comp_desc(eind, COMP_CHAR), // AVRMEM mem_comp_desc(n_word_writes, COMP_INT), diff --git a/src/config_gram.y b/src/config_gram.y index a90d2373..3052eaa3 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -196,12 +196,8 @@ static int pin_name; %token K_HAS_PDI /* MCU has PDI i/f rather than ISP (ATxmega). */ %token K_HAS_UPDI /* MCU has UPDI i/f (AVR8X). */ %token K_HAS_TPI /* MCU has TPI i/f rather than ISP (ATtiny4/5/9/10). */ -%token K_IDR /* address of OCD register in IO space */ %token K_IS_AT90S1200 /* chip is an AT90S1200 (needs special treatment) */ %token K_IS_AVR32 /* chip is in the avr32 family */ -%token K_RAMPZ /* address of RAMPZ reg. in IO space */ -%token K_SPMCR /* address of SPMC[S]R in memory space */ -%token K_EECR /* address of EECR in memory space */ %token K_FLASH_INSTR /* flash instructions */ %token K_EEPROM_INSTR /* EEPROM instructions */ @@ -1201,30 +1197,6 @@ part_parm : free_token($3); } | - K_IDR TKN_EQUAL numexpr - { - current_part->idr = $3->value.number; - free_token($3); - } | - - K_RAMPZ TKN_EQUAL numexpr - { - current_part->rampz = $3->value.number; - free_token($3); - } | - - K_SPMCR TKN_EQUAL numexpr - { - current_part->spmcr = $3->value.number; - free_token($3); - } | - - K_EECR TKN_EQUAL numexpr - { - current_part->eecr = $3->value.number; - free_token($3); - } | - K_MCU_BASE TKN_EQUAL numexpr { current_part->mcu_base = $3->value.number; diff --git a/src/developer_opts.c b/src/developer_opts.c index 8d8674a5..cb42e30e 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -56,7 +56,7 @@ // Inject part parameters into a semi-automated rewrite of avrdude.conf // - Add entries to the tables below; they get written on -p*/si or -c*/si // - Use the output in a new avrdude.conf -// - Output again with -p* or -c* (no /i) and use that for final avrdude.conf +// - Output again with -p*/s or -c*/s (no /i) and use that for final avrdude.conf // - Remove entries from below tables static struct { @@ -712,6 +712,7 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool _if_partout(intcmp, "0x%02x", rampz); _if_partout(intcmp, "0x%02x", spmcr); _if_partout(intcmp, "0x%02x", eecr); + _if_partout(intcmp, "0x%02x", eind); _if_partout(intcmp, "0x%04x", mcu_base); _if_partout(intcmp, "0x%04x", nvm_base); _if_partout(intcmp, "0x%04x", ocd_base); diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 71e1e272..0ffb58c0 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -2051,6 +2051,7 @@ part rampz = ; # IO addr of RAMPZ reg spmcr = ; # mem addr of SPMC[S]R reg eecr = ; # mem addr of EECR reg only when != 0x3f + eind = ; # mem addr of EIND reg mcu_base = ; nvm_base = ; ocd_base = ; diff --git a/src/lexer.l b/src/lexer.l index 65cb3b4a..88413a72 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -122,7 +122,7 @@ SIGN [+-] (?x: prog_modes | mcuid | n_interrupts | n_page_erase | n_word_writes | n_boot_sections | - boot_section_size | autobaud_sync) { /* Components for assignment */ + boot_section_size | autobaud_sync | idr | rampz | spmcr | eecr | eind ) { /* struct components */ Component_t *cp = cfg_comp_search(yytext, current_strct); if(!cp) { @@ -166,7 +166,6 @@ default_spi { yylval=NULL; return K_DEFAULT_SPI; } delay { yylval=NULL; ccap(); return K_DELAY; } desc { yylval=NULL; ccap(); return K_DESC; } devicecode { yylval=NULL; ccap(); return K_DEVICECODE; } -eecr { yylval=NULL; ccap(); return K_EECR; } eeprom { yylval=NULL; return K_EEPROM; } eeprom_instr { yylval=NULL; ccap(); return K_EEPROM_INSTR; } enablepageprogramming { yylval=NULL; ccap(); return K_ENABLEPAGEPROGRAMMING; } @@ -186,7 +185,6 @@ hvspcmdexedelay { yylval=NULL; ccap(); return K_HVSPCMDEXEDELAY; } hvupdi_support { yylval=NULL; ccap(); return K_HVUPDI_SUPPORT; } hvupdi_variant { yylval=NULL; ccap(); return K_HVUPDI_VARIANT; } id { yylval=NULL; ccap(); return K_ID; } -idr { yylval=NULL; ccap(); return K_IDR; } io { yylval=new_token(K_IO); return K_IO; } is_at90s1200 { yylval=NULL; ccap(); return K_IS_AT90S1200; } is_avr32 { yylval=NULL; ccap(); return K_IS_AVR32; } @@ -232,7 +230,6 @@ programlockpulsewidth { yylval=NULL; ccap(); return K_PROGRAMLOCKPULSEWIDTH; } programmer { yylval=NULL; ccap(); return K_PROGRAMMER; } pseudo { yylval=new_token(K_PSEUDO); return K_PSEUDO; } pwroff_after_write { yylval=NULL; ccap(); return K_PWROFF_AFTER_WRITE; } -rampz { yylval=NULL; ccap(); return K_RAMPZ; } rdyled { yylval=NULL; ccap(); return K_RDYLED; } read { yylval=new_token(K_READ); ccap(); return K_READ; } read_hi { yylval=new_token(K_READ_HI); ccap(); return K_READ_HI; } @@ -253,7 +250,6 @@ serial { yylval=NULL; ccap(); return K_SERIAL; } signature { yylval=NULL; ccap(); return K_SIGNATURE; } size { yylval=NULL; ccap(); return K_SIZE; } spi { yylval=NULL; return K_SPI; } -spmcr { yylval=NULL; ccap(); return K_SPMCR; } stabdelay { yylval=NULL; ccap(); return K_STABDELAY; } stk500_devcode { yylval=NULL; ccap(); return K_STK500_DEVCODE; } synchcycles { yylval=NULL; ccap(); return K_SYNCHCYCLES; } diff --git a/src/libavrdude.h b/src/libavrdude.h index e86407c3..c9a92f0e 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -295,6 +295,7 @@ typedef struct avrpart { unsigned char rampz; /* I/O address of RAMPZ reg */ unsigned char spmcr; /* memory address of SPMCR reg */ unsigned char eecr; /* memory address of EECR reg */ + unsigned char eind; /* memory address of EIND reg */ unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */ unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */ unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */