From 88b5fcd0fb280b0fc5093b7aab5844a75b7e61e5 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Mon, 16 Oct 2023 21:06:30 +0100 Subject: [PATCH 1/2] Model prodsig for -c dryrun --- src/dryrun.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/dryrun.c b/src/dryrun.c index 797c343f..a43eb576 100644 --- a/src/dryrun.c +++ b/src/dryrun.c @@ -115,7 +115,7 @@ static void dryrun_enable(PROGRAMMER *pgm, const AVRPART *p) { if(!dry.dp) { unsigned char inifuses[16]; // For fuses, which is made up from fuse0, fuse1, ... - AVRMEM *fusesm = NULL; + AVRMEM *fusesm = NULL, *sernumm = NULL, *tempsensem = NULL, *prodsigm = NULL, *calm; dry.dp = avr_dup_part(p); // Allocate dryrun part memset(inifuses, 0xff, sizeof inifuses); @@ -141,8 +141,48 @@ static void dryrun_enable(PROGRAMMER *pgm, const AVRPART *p) { } } else if(str_eq(m->desc, "signature") && (int) sizeof(dry.dp->signature) == m->size) { memcpy(m->buf, dry.dp->signature, m->size); - } else if(str_contains(m->desc, "calibration")) { - memset(m->buf, 0x55, m->size); // ASCII 0x55 is 'U' for uncalibrated :) + } else if(str_contains(m->desc, "calibration") || str_eq(m->desc, "osc16err") || + str_eq(m->desc, "osccal16") || str_eq(m->desc, "osc20err") || + str_eq(m->desc, "osccal20") || str_eq(m->desc, "sib")) { + memset(m->buf, 'U', m->size); // 'U' for uncalibrated or unknown :) + } else if( str_eq(m->desc, "tempsense")) { + tempsensem = m; + memset(m->buf, 'T', m->size); // 'T' for temperature calibration values + } else if(str_eq(m->desc, "sernum")) { + sernumm = m; + for(int i = 0; i < m->size; i++) // Set serial number UTSRQPONM... + m->buf[i] = 'U'-i >= 'A'? 'U'-i: 0xff; + } else if(str_eq(m->desc, "prodsig") && m->size >= 6) { + prodsigm = m; + memset(m->buf, 0xff, m->size); + if(p->prog_modes & PM_UPDI) { + memcpy(m->buf, dry.dp->signature, 3); + } else if(p->prog_modes & PM_PDI) { + m->buf[0] = m->buf[1] = 'U'; + } else { // Classic parts: signature at even addresses + for(int i=0; i<3; i++) + m->buf[2*i] = dry.dp->signature[i]; + } + } + } + if(prodsigm) { + if(tempsensem) { + int off = tempsensem->offset - prodsigm->offset; + int cpy = tempsensem->size; + if(off+cpy <= prodsigm->size && off+cpy >= 0) + memcpy(prodsigm->buf + off, tempsensem->buf, cpy); + } + if(sernumm) { + int off = sernumm->offset - prodsigm->offset; + int cpy = sernumm->size; + if(off+cpy <= prodsigm->size && off+cpy >= 0) + memcpy(prodsigm->buf + off, sernumm->buf, cpy); + } + if(!(p->prog_modes & (PM_PDI|PM_UPDI)) && (calm = avr_locate_mem(dry.dp, "calibration"))) { + // Calibration bytes of classic parts are interspersed with signature + for(int i=0; isize; i++) + if(2*i+1 < prodsigm->size) + prodsigm->buf[2*i+1] = 'U'; } } if(fusesm) { @@ -320,7 +360,11 @@ int dryrun_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, if(dmem->size != m->size) Return("cannot write byte to %s %s as sizes differ: 0x%04x vs 0x%04x", dry.dp->desc, dmem->desc, dmem->size, m->size); - if(str_contains(dmem->desc, "calibration") || str_eq(dmem->desc, "signature")) + if(str_contains(dmem->desc, "calibration") || str_eq(dmem->desc, "osc16err") || + str_eq(dmem->desc, "osccal16") || str_eq(dmem->desc, "osc20err") || + str_eq(dmem->desc, "osccal20") || str_eq(dmem->desc, "prodsig") || + str_eq(dmem->desc, "sernum") || str_eq(dmem->desc, "sib") || + str_eq(dmem->desc, "signature") || str_eq(dmem->desc, "tempsense")) Return("cannot write to write-protected memory %s %s", dry.dp->desc, dmem->desc); if(addr >= (unsigned long) dmem->size) From c1df5937dbc6c2b7d1548848377788d4334f175a Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 17 Oct 2023 00:51:56 +0100 Subject: [PATCH 2/2] Initialise all prodsig sub-memories for -c dryrun UPDI-parts --- src/dryrun.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/dryrun.c b/src/dryrun.c index a43eb576..f13cf458 100644 --- a/src/dryrun.c +++ b/src/dryrun.c @@ -115,7 +115,7 @@ static void dryrun_enable(PROGRAMMER *pgm, const AVRPART *p) { if(!dry.dp) { unsigned char inifuses[16]; // For fuses, which is made up from fuse0, fuse1, ... - AVRMEM *fusesm = NULL, *sernumm = NULL, *tempsensem = NULL, *prodsigm = NULL, *calm; + AVRMEM *fusesm = NULL, *prodsigm = NULL, *calm; dry.dp = avr_dup_part(p); // Allocate dryrun part memset(inifuses, 0xff, sizeof inifuses); @@ -141,42 +141,46 @@ static void dryrun_enable(PROGRAMMER *pgm, const AVRPART *p) { } } else if(str_eq(m->desc, "signature") && (int) sizeof(dry.dp->signature) == m->size) { memcpy(m->buf, dry.dp->signature, m->size); - } else if(str_contains(m->desc, "calibration") || str_eq(m->desc, "osc16err") || - str_eq(m->desc, "osccal16") || str_eq(m->desc, "osc20err") || - str_eq(m->desc, "osccal20") || str_eq(m->desc, "sib")) { + } else if(str_eq(m->desc, "calibration")) { memset(m->buf, 'U', m->size); // 'U' for uncalibrated or unknown :) + } else if(str_eq(m->desc, "osc16err")) { + memset(m->buf, 'e', m->size); + } else if(str_eq(m->desc, "osc20err")) { + memset(m->buf, 'E', m->size); + } else if(str_eq(m->desc, "osccal16")) { + memset(m->buf, 'o', m->size); + } else if(str_eq(m->desc, "osccal20")) { + memset(m->buf, 'O', m->size); + } else if(str_eq(m->desc, "sib")) { + memset(m->buf, 'S', m->size); } else if( str_eq(m->desc, "tempsense")) { - tempsensem = m; memset(m->buf, 'T', m->size); // 'T' for temperature calibration values } else if(str_eq(m->desc, "sernum")) { - sernumm = m; for(int i = 0; i < m->size; i++) // Set serial number UTSRQPONM... m->buf[i] = 'U'-i >= 'A'? 'U'-i: 0xff; } else if(str_eq(m->desc, "prodsig") && m->size >= 6) { prodsigm = m; memset(m->buf, 0xff, m->size); - if(p->prog_modes & PM_UPDI) { - memcpy(m->buf, dry.dp->signature, 3); - } else if(p->prog_modes & PM_PDI) { + if(p->prog_modes & PM_PDI) { m->buf[0] = m->buf[1] = 'U'; - } else { // Classic parts: signature at even addresses + } else if(!(p->prog_modes & PM_UPDI)) { // Classic parts: signature at even addresses for(int i=0; i<3; i++) m->buf[2*i] = dry.dp->signature[i]; } } } if(prodsigm) { - if(tempsensem) { - int off = tempsensem->offset - prodsigm->offset; - int cpy = tempsensem->size; - if(off+cpy <= prodsigm->size && off+cpy >= 0) - memcpy(prodsigm->buf + off, tempsensem->buf, cpy); - } - if(sernumm) { - int off = sernumm->offset - prodsigm->offset; - int cpy = sernumm->size; - if(off+cpy <= prodsigm->size && off+cpy >= 0) - memcpy(prodsigm->buf + off, sernumm->buf, cpy); + if(p->prog_modes & PM_UPDI) { + for (LNODEID ln=lfirst(dry.dp->mem); ln; ln=lnext(ln)) { + AVRMEM *m = ldata(ln); + if(m->buf == prodsigm->buf) // Skip prodsig memory + continue; + int off = m->offset - prodsigm->offset; + int cpy = m->size; + // Submemory of prodsig, eg, signature and tempsense? Copy into prodsig + if(off >= 0 && off+cpy <= prodsigm->size) + memcpy(prodsigm->buf + off, m->buf, cpy); + } } if(!(p->prog_modes & (PM_PDI|PM_UPDI)) && (calm = avr_locate_mem(dry.dp, "calibration"))) { // Calibration bytes of classic parts are interspersed with signature @@ -360,7 +364,7 @@ int dryrun_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, if(dmem->size != m->size) Return("cannot write byte to %s %s as sizes differ: 0x%04x vs 0x%04x", dry.dp->desc, dmem->desc, dmem->size, m->size); - if(str_contains(dmem->desc, "calibration") || str_eq(dmem->desc, "osc16err") || + if(str_eq(dmem->desc, "calibration") || str_eq(dmem->desc, "osc16err") || str_eq(dmem->desc, "osccal16") || str_eq(dmem->desc, "osc20err") || str_eq(dmem->desc, "osccal20") || str_eq(dmem->desc, "prodsig") || str_eq(dmem->desc, "sernum") || str_eq(dmem->desc, "sib") ||