From ce093df4e68856f90bd0e24283aaafd3d702af2c Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Mon, 19 May 2025 20:47:44 +0200 Subject: [PATCH 1/4] Lengthen timeouts for lower baud rates --- src/urclock.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/urclock.c b/src/urclock.c index cb1f838b..4abfd572 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -1679,7 +1679,7 @@ static int urclock_paged_rdwr(const PROGRAMMER *pgm, const AVRPART *part, char r // STK500v1 only: tell the bootloader which address should be used by next paged command if(!ur.urprotocol && urclock_load_baddr(pgm, part, mchr, badd) < 0) - return -1; + return -1; if(mchr == 'F' && rwop == Cmnd_STK_PROG_PAGE) { if(len != ur.uP.pagesize) @@ -1935,7 +1935,8 @@ static int urclock_getsync(const PROGRAMMER *pgm) { AVRPART *part; // Reduce timeout for establishing comms - serial_recv_timeout = 25; // ms + double kbd = pgm->baudrate <= 0? 115.200: pgm->baudrate/1000.0; + serial_recv_timeout = 25 + (kbd < 115? 160/kbd: 0); // ms: longer for low baud rates part = partdesc? locate_part(part_list, partdesc): NULL; /* * The urboot autosync detection uses a loop @@ -1954,7 +1955,7 @@ static int urclock_getsync(const PROGRAMMER *pgm) { autobaud_sync = part && part->autobaud_sync? part->autobaud_sync: Cmnd_STK_GET_SYNC; ur.sync_silence = 2; - serial_drain_timeout = 20; // ms + serial_drain_timeout = 20 + (kbd < 115? 80/kbd: 0); // ms: longer for low baud rates for(attempt = 0; attempt < MAX_SYNC_ATTEMPTS; attempt++) { /* @@ -2003,7 +2004,7 @@ static int urclock_getsync(const PROGRAMMER *pgm) { urclock_send(pgm, iob, 1); // So, send the concluding byte } } - serial_drain(&pgm->fd, 0); // And either way drain the reply + serial_drain(&pgm->fd, 0); // And either way drain the reply ur.sync_silence = 0; @@ -2044,6 +2045,9 @@ static int urclock_getsync(const PROGRAMMER *pgm) { } } + if(kbd < 115) // Increase timeout for low baud rates + serial_recv_timeout += (ur.uP.pagesize + 5)*10/kbd; + return 0; } From 1d978db9e6ef9657961a230060ffc5891df23763 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 20 May 2025 02:16:28 +0200 Subject: [PATCH 2/4] Skip unnecessary disable() call --- src/urclock.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/urclock.c b/src/urclock.c index 4abfd572..c29a2090 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -2208,6 +2208,9 @@ static int urclock_initialize(const PROGRAMMER *pgm, const AVRPART *p) { static void urclock_disable(const PROGRAMMER *pgm) { unsigned char buf[16]; + if(ur.urprotocol) + return; + buf[0] = Cmnd_STK_LEAVE_PROGMODE; buf[1] = Sync_CRC_EOP; From 3ff62b42d5c53e3ddcd2c1d845a3be4f6e32edac Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Tue, 20 May 2025 02:17:09 +0200 Subject: [PATCH 3/4] Read in chunks that bootloader can send within WDT timeout --- src/urclock.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/urclock.c b/src/urclock.c index c29a2090..c500d865 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -1790,15 +1790,26 @@ static int ur_readEF(const PROGRAMMER *pgm, const AVRPART *p, uint8_t *buf, uint int odd = !ur.urprotocol && classic && (badd&1); if(odd) { // Need to read one extra byte len++; - badd &= ~1; + badd--; if(len > urmax(ur.uP.pagesize, 256)) Return("len+1 = %d odd address exceeds range [1, %d]", len, urmax(ur.uP.pagesize, 256)); } - if(urclock_paged_rdwr(pgm, p, Cmnd_STK_READ_PAGE, badd, len, mchr, NULL) < 0) - return -1; + // Read in chunks that the bootloader can send within 800 ms lest it triggers WDT + int bd = pgm->baudrate <= 0? 115200: pgm->baudrate, rdchunk = urmax(4*bd/5/10 - 2, 2) & ~1; + while(len > 0) { + int thislen = len < rdchunk? len: rdchunk; - return urclock_res_check(pgm, __func__, odd, buf, len-odd); + if(urclock_paged_rdwr(pgm, p, Cmnd_STK_READ_PAGE, badd, thislen, mchr, NULL) < 0) + return -1; + if(urclock_res_check(pgm, __func__, odd, buf, thislen-odd) < 0) + return -1; + buf += thislen-odd; + badd += thislen; + len -= thislen; + odd = 0; // At most ignore first byte + } + return 0; } @@ -1935,7 +1946,7 @@ static int urclock_getsync(const PROGRAMMER *pgm) { AVRPART *part; // Reduce timeout for establishing comms - double kbd = pgm->baudrate <= 0? 115.200: pgm->baudrate/1000.0; + double kbd = pgm->baudrate <= 0? 115.2: pgm->baudrate/1000.0; serial_recv_timeout = 25 + (kbd < 115? 160/kbd: 0); // ms: longer for low baud rates part = partdesc? locate_part(part_list, partdesc): NULL; /* @@ -2315,6 +2326,11 @@ static int urclock_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVR int mchr, chunk; unsigned int n; + // Read in chunks that the bootloader can send within 800 ms lest it triggers WDT + int bd = pgm->baudrate <= 0? 115200: pgm->baudrate, rdchunk = urmax(4*bd/5/10 - 2, 2) & ~1; + if((unsigned) rdchunk < page_size) + page_size = rdchunk; + if(n_bytes) { // Paged reads only valid for flash and eeprom mchr = mem_is_in_flash(m)? 'F': 'E'; @@ -2337,9 +2353,9 @@ static int urclock_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVR if(urclock_res_check(pgm, __func__, 0, &m->buf[addr], chunk) < 0) return -4; - if(addr == 0 && mchr == 'F') { // Ensure reset vector points to bl + if(addr == 0 && mchr == 'F') { // Point reset vector to bootloader if needed and possible int vecsz = ur.uP.flashsize <= 8192? 2: 4; - if(chunk >= vecsz && ur.boothigh && ur.blstart && ur.vbllevel == 1) { + if(chunk == ur.uP.pagesize && ur.boothigh && ur.blstart && ur.vbllevel == 1) { unsigned char jmptoboot[4]; int resetsize = set_reset(pgm, jmptoboot, vecsz); int resetdest; From 3dcc775c49cf5b791a2dd73ec12fceb3427b54e9 Mon Sep 17 00:00:00 2001 From: stefanrueger Date: Wed, 21 May 2025 08:03:02 +0200 Subject: [PATCH 4/4] Skip disable() only for low baud rates Bootloader can WDT reset swiftly on disable, which is too little time for low baud rates to send handshake OK byte. --- src/urclock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/urclock.c b/src/urclock.c index c500d865..32126cc3 100644 --- a/src/urclock.c +++ b/src/urclock.c @@ -2219,7 +2219,7 @@ static int urclock_initialize(const PROGRAMMER *pgm, const AVRPART *p) { static void urclock_disable(const PROGRAMMER *pgm) { unsigned char buf[16]; - if(ur.urprotocol) + if(pgm->baudrate && pgm->baudrate < 115000 && ur.urprotocol) return; buf[0] = Cmnd_STK_LEAVE_PROGMODE;