Merge pull request #1198 from stefanrueger/delay

Tie up loose ends for urclock programmer
This commit is contained in:
Stefan Rueger 2022-11-27 19:04:07 +00:00 committed by GitHub
commit 2ac582fa02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 411 additions and 169 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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=<string>
@ -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=<size>
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=<arg>
@ -1250,8 +1253,12 @@ frame is programmed.
.It Ar delay=<n>
Add a <n> ms delay after reset. This can be useful if a board takes a
particularly long time to exit from external reset. <n> can be negative,
in which case the default 80 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
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

View File

@ -130,19 +130,22 @@
# programfusepolltimeout = <num> ;
# programlockpulsewidth = <num> ; # PP only
# programlockpolltimeout = <num> ;
# # JTAG ICE mkII parameters, also from ATDF files
# # debugWIRE and/or JTAG ICE mkII parameters, also from ATDF files
# allowfullpagebitstream = <yes/no> ;
# enablepageprogramming = <yes/no> ;
# idr = <num> ; # IO addr of IDR (OCD) reg
# rampz = <num> ; # IO addr of RAMPZ reg
# spmcr = <num> ; # mem addr of SPMC[S]R reg
# eecr = <num> ; # mem addr of EECR reg only when != 0x3f
# eind = <num> ; # mem addr of EIND reg
# mcu_base = <num> ;
# nvm_base = <num> ;
# ocd_base = <num> ;
# ocdrev = <num> ;
# pgm_enable = <instruction format> ;
# chip_erase = <instruction format> ;
# # parameters for bootloaders
# autobaud_sync = <num> ; # autobaud detection byte, default 0x30
#
# memory <memtype>
# paged = <yes/no> ; # yes/no (flash only, do not use for EEPROM)
@ -175,12 +178,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
@ -4674,6 +4678,7 @@ part parent "m324p"
desc = "ATmega324PB";
id = "m324pb";
mcuid = 113;
n_interrupts = 51;
signature = 0x1e 0x95 0x17;
;
@ -9433,7 +9438,6 @@ part parent "m1280"
desc = "ATmega1281";
id = "m1281";
mcuid = 139;
n_interrupts = 51;
signature = 0x1e 0x97 0x04;
;
@ -9571,7 +9575,6 @@ part parent "m2560"
desc = "ATmega2561";
id = "m2561";
mcuid = 144;
n_interrupts = 51;
signature = 0x1e 0x98 0x02;
;
@ -10875,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";
@ -10965,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;
@ -10999,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";
@ -11123,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";
@ -11247,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";
@ -11337,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;
@ -11371,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";
@ -11617,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?
@ -11764,7 +11772,6 @@ part parent "m325"
desc = "ATmega325PA";
id = "m325pa";
mcuid = 117;
n_interrupts = 22;
signature = 0x1e 0x95 0x0d;
;
@ -11777,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?
@ -12011,6 +12018,7 @@ part
n_boot_sections = 1;
mcu_base = 0x0090;
nvm_base = 0x01c0;
autobaud_sync = 0x20;
memory "fuse1"
size = 1;
@ -13561,6 +13569,7 @@ part parent ".reduced_core_tiny"
desc = "ATtiny102";
id = "t102";
mcuid = 6;
n_interrupts = 16;
signature = 0x1e 0x90 0x0c;
memory "flash"
@ -13579,6 +13588,7 @@ part parent ".reduced_core_tiny"
desc = "ATtiny104";
id = "t104";
mcuid = 7;
n_interrupts = 16;
signature = 0x1e 0x90 0x0b;
memory "flash"
@ -14527,6 +14537,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny424";
id = "t424";
mcuid = 292;
n_interrupts = 30;
signature = 0x1e 0x92 0x2c;
memory "eeprom"
@ -14552,6 +14563,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny426";
id = "t426";
mcuid = 293;
n_interrupts = 30;
signature = 0x1e 0x92 0x2b;
memory "eeprom"
@ -14577,6 +14589,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny427";
id = "t427";
mcuid = 294;
n_interrupts = 30;
signature = 0x1e 0x92 0x2a;
memory "eeprom"
@ -14602,6 +14615,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny824";
id = "t824";
mcuid = 301;
n_interrupts = 30;
signature = 0x1e 0x93 0x29;
memory "eeprom"
@ -14627,6 +14641,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny826";
id = "t826";
mcuid = 302;
n_interrupts = 30;
signature = 0x1e 0x93 0x28;
memory "eeprom"
@ -14652,6 +14667,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny827";
id = "t827";
mcuid = 303;
n_interrupts = 30;
signature = 0x1e 0x93 0x27;
memory "eeprom"
@ -14677,6 +14693,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny1624";
id = "t1624";
mcuid = 310;
n_interrupts = 30;
signature = 0x1e 0x94 0x2a;
memory "eeprom"
@ -14702,6 +14719,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny1626";
id = "t1626";
mcuid = 311;
n_interrupts = 30;
signature = 0x1e 0x94 0x29;
memory "eeprom"
@ -14727,6 +14745,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny1627";
id = "t1627";
mcuid = 312;
n_interrupts = 30;
signature = 0x1e 0x94 0x28;
memory "eeprom"
@ -14752,6 +14771,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny3224";
id = "t3224";
mcuid = 316;
n_interrupts = 30;
signature = 0x1e 0x95 0x28;
memory "eeprom"
@ -14777,6 +14797,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny3226";
id = "t3226";
mcuid = 317;
n_interrupts = 30;
signature = 0x1e 0x95 0x27;
memory "eeprom"
@ -14802,6 +14823,7 @@ part parent ".avr8x_tiny"
desc = "ATtiny3227";
id = "t3227";
mcuid = 318;
n_interrupts = 30;
signature = 0x1e 0x95 0x26;
memory "eeprom"
@ -15194,6 +15216,7 @@ part parent ".avrdx"
id = "avr32da28";
family_id = " AVR";
mcuid = 338;
n_interrupts = 41;
signature = 0x1e 0x95 0x34;
memory "eeprom"
@ -15219,6 +15242,7 @@ part parent ".avrdx"
id = "avr32da32";
family_id = " AVR";
mcuid = 342;
n_interrupts = 44;
signature = 0x1e 0x95 0x33;
memory "eeprom"
@ -15244,6 +15268,7 @@ part parent ".avrdx"
id = "avr32da48";
family_id = " AVR";
mcuid = 346;
n_interrupts = 58;
signature = 0x1e 0x95 0x32;
memory "eeprom"
@ -15269,6 +15294,7 @@ part parent ".avrdx"
id = "avr64da28";
family_id = " AVR";
mcuid = 351;
n_interrupts = 41;
signature = 0x1e 0x96 0x15;
memory "eeprom"
@ -15294,6 +15320,7 @@ part parent ".avrdx"
id = "avr64da32";
family_id = " AVR";
mcuid = 355;
n_interrupts = 44;
signature = 0x1e 0x96 0x14;
memory "eeprom"
@ -15319,6 +15346,7 @@ part parent ".avrdx"
id = "avr64da48";
family_id = " AVR";
mcuid = 359;
n_interrupts = 58;
signature = 0x1e 0x96 0x13;
memory "eeprom"
@ -15344,6 +15372,7 @@ part parent ".avrdx"
id = "avr64da64";
family_id = " AVR";
mcuid = 362;
n_interrupts = 64;
signature = 0x1e 0x96 0x12;
memory "eeprom"
@ -15369,6 +15398,7 @@ part parent ".avrdx"
id = "avr128da28";
family_id = " AVR";
mcuid = 364;
n_interrupts = 41;
signature = 0x1e 0x97 0x0a;
memory "eeprom"
@ -15394,6 +15424,7 @@ part parent ".avrdx"
id = "avr128da32";
family_id = " AVR";
mcuid = 366;
n_interrupts = 44;
signature = 0x1e 0x97 0x09;
memory "eeprom"
@ -15419,6 +15450,7 @@ part parent ".avrdx"
id = "avr128da48";
family_id = " AVR";
mcuid = 368;
n_interrupts = 58;
signature = 0x1e 0x97 0x08;
memory "eeprom"
@ -15444,6 +15476,7 @@ part parent ".avrdx"
id = "avr128da64";
family_id = " AVR";
mcuid = 370;
n_interrupts = 64;
signature = 0x1e 0x97 0x07;
memory "eeprom"
@ -15468,6 +15501,7 @@ part parent ".avrdx"
desc = "AVR32DB28";
id = "avr32db28";
mcuid = 339;
n_interrupts = 42;
signature = 0x1e 0x95 0x37;
memory "eeprom"
@ -15492,6 +15526,7 @@ part parent ".avrdx"
desc = "AVR32DB32";
id = "avr32db32";
mcuid = 343;
n_interrupts = 44;
signature = 0x1e 0x95 0x36;
memory "eeprom"
@ -15516,6 +15551,7 @@ part parent ".avrdx"
desc = "AVR32DB48";
id = "avr32db48";
mcuid = 347;
n_interrupts = 61;
signature = 0x1e 0x95 0x35;
memory "eeprom"
@ -15540,6 +15576,7 @@ part parent ".avrdx"
desc = "AVR64DB28";
id = "avr64db28";
mcuid = 352;
n_interrupts = 42;
signature = 0x1e 0x96 0x19;
memory "eeprom"
@ -15564,6 +15601,7 @@ part parent ".avrdx"
desc = "AVR64DB32";
id = "avr64db32";
mcuid = 356;
n_interrupts = 44;
signature = 0x1e 0x96 0x18;
memory "eeprom"
@ -15588,6 +15626,7 @@ part parent ".avrdx"
desc = "AVR64DB48";
id = "avr64db48";
mcuid = 360;
n_interrupts = 61;
signature = 0x1e 0x96 0x17;
memory "eeprom"
@ -15612,6 +15651,7 @@ part parent ".avrdx"
desc = "AVR64DB64";
id = "avr64db64";
mcuid = 363;
n_interrupts = 65;
signature = 0x1e 0x96 0x16;
memory "eeprom"
@ -15636,6 +15676,7 @@ part parent ".avrdx"
desc = "AVR128DB28";
id = "avr128db28";
mcuid = 365;
n_interrupts = 42;
signature = 0x1e 0x97 0x0e;
memory "eeprom"
@ -15660,6 +15701,7 @@ part parent ".avrdx"
desc = "AVR128DB32";
id = "avr128db32";
mcuid = 367;
n_interrupts = 44;
signature = 0x1e 0x97 0x0d;
memory "eeprom"
@ -15684,6 +15726,7 @@ part parent ".avrdx"
desc = "AVR128DB48";
id = "avr128db48";
mcuid = 369;
n_interrupts = 61;
signature = 0x1e 0x97 0x0c;
memory "eeprom"
@ -15708,6 +15751,7 @@ part parent ".avrdx"
desc = "AVR128DB64";
id = "avr128db64";
mcuid = 371;
n_interrupts = 65;
signature = 0x1e 0x97 0x0b;
memory "eeprom"
@ -15732,6 +15776,7 @@ part parent ".avrdx"
desc = "AVR16DD14";
id = "avr16dd14";
mcuid = 329;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x94 0x34;
@ -15757,6 +15802,7 @@ part parent ".avrdx"
desc = "AVR16DD20";
id = "avr16dd20";
mcuid = 330;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x94 0x33;
@ -15782,6 +15828,7 @@ part parent ".avrdx"
desc = "AVR16DD28";
id = "avr16dd28";
mcuid = 331;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x94 0x32;
@ -15807,6 +15854,7 @@ part parent ".avrdx"
desc = "AVR16DD32";
id = "avr16dd32";
mcuid = 333;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x94 0x31;
@ -15832,6 +15880,7 @@ part parent ".avrdx"
desc = "AVR32DD14";
id = "avr32dd14";
mcuid = 336;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x95 0x3b;
@ -15857,6 +15906,7 @@ part parent ".avrdx"
desc = "AVR32DD20";
id = "avr32dd20";
mcuid = 337;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x95 0x3a;
@ -15882,6 +15932,7 @@ part parent ".avrdx"
desc = "AVR32DD28";
id = "avr32dd28";
mcuid = 340;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x95 0x39;
@ -15907,6 +15958,7 @@ part parent ".avrdx"
desc = "AVR32DD32";
id = "avr32dd32";
mcuid = 344;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x95 0x38;
@ -15932,6 +15984,7 @@ part parent ".avrdx"
desc = "AVR64DD14";
id = "avr64dd14";
mcuid = 349;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x96 0x1d;
@ -15957,6 +16010,7 @@ part parent ".avrdx"
desc = "AVR64DD20";
id = "avr64dd20";
mcuid = 350;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x96 0x1c;
@ -15982,6 +16036,7 @@ part parent ".avrdx"
desc = "AVR64DD28";
id = "avr64dd28";
mcuid = 353;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x96 0x1b;
@ -16007,6 +16062,7 @@ part parent ".avrdx"
desc = "AVR64DD32";
id = "avr64dd32";
mcuid = 357;
n_interrupts = 36;
hvupdi_variant = 2;
signature = 0x1e 0x96 0x1a;
@ -16253,6 +16309,7 @@ part parent ".avrex"
desc = "AVR64EA28";
id = "avr64ea28";
mcuid = 354;
n_interrupts = 37;
signature = 0x1e 0x96 0x20;
memory "eeprom"
@ -16278,6 +16335,7 @@ part parent ".avrex"
desc = "AVR64EA32";
id = "avr64ea32";
mcuid = 358;
n_interrupts = 37;
signature = 0x1e 0x96 0x1f;
memory "eeprom"
@ -16303,6 +16361,7 @@ part parent ".avrex"
desc = "AVR64EA48";
id = "avr64ea48";
mcuid = 361;
n_interrupts = 45;
signature = 0x1e 0x96 0x1e;
memory "eeprom"
@ -16329,6 +16388,7 @@ part parent "m88"
id = "lgt8f88p";
mcuid = 227;
signature = 0x1e 0x93 0x0f;
autobaud_sync = 0x1c;
;
#------------------------------------------------------------
@ -16340,6 +16400,7 @@ part parent "m168"
id = "lgt8f168p";
mcuid = 228;
signature = 0x1e 0x94 0x0b;
autobaud_sync = 0x1c;
;
#------------------------------------------------------------
@ -16351,4 +16412,5 @@ part parent "m328"
id = "lgt8f328p";
mcuid = 229;
signature = 0x1e 0x95 0x0f;
autobaud_sync = 0x1c;
;

View File

@ -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;

View File

@ -72,6 +72,12 @@ 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),
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),

View File

@ -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;

View File

@ -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,10 +712,12 @@ 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);
_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))

View File

@ -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=<E|F>.<addr>.<len>}
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=<E|F>.<addr>.<len>} 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=<string>}
When set, <string> 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=<size>}
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=<arg>}
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=<n>}
Add a <n> ms delay after reset. This can be useful if a board takes a
particularly long time to exit from external reset. <n> can be negative,
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
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
@ -1925,19 +2044,22 @@ part
programfusepolltimeout = <num> ;
programlockpulsewidth = <num> ; # PP only
programlockpolltimeout = <num> ;
# JTAG ICE mkII parameters, also from ATDF files
# debugWIRE and/or JTAG ICE mkII parameters, also from ATDF files
allowfullpagebitstream = <yes/no> ;
enablepageprogramming = <yes/no> ;
idr = <num> ; # IO addr of IDR (OCD) reg
rampz = <num> ; # IO addr of RAMPZ reg
spmcr = <num> ; # mem addr of SPMC[S]R reg
eecr = <num> ; # mem addr of EECR reg only when != 0x3f
eind = <num> ; # mem addr of EIND reg
mcu_base = <num> ;
nvm_base = <num> ;
ocd_base = <num> ;
ocdrev = <num> ;
pgm_enable = <instruction format> ;
chip_erase = <instruction format> ;
# parameters for bootloaders
autobaud_sync = <num> ; # autobaud detection byte, default 0x30
memory <memtype>
paged = <yes/no> ; # yes/no (flash only, do not use for EEPROM)
@ -1970,14 +2092,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::

View File

@ -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);

View File

@ -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 | 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; }

View File

@ -252,56 +252,64 @@ 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 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 */
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 {
@ -879,6 +887,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);

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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");

View File

@ -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)
@ -544,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
@ -1153,6 +1153,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 +1871,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 -xstrict and/or vary -xdelay=100\n");
return -1;
}
@ -1878,7 +1879,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 +1888,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 +1985,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 +2190,22 @@ 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
#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 = 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 +2421,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 +2447,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;