Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read chip silicon revision and add IO memory on chips with PDI and UPDI #1474

Merged
merged 21 commits into from
Aug 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/avrdude.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
# mcu_base = <num> ; # MCU control block in ATxmega devices
# nvm_base = <num> ; # NVM controller in ATxmega devices
# ocd_base = <num> ; # OCD module in AVR8X/UPDI devices
# syscfg_base = <num> ; # Chip revision ID in AVR8X/UPDI devices
# ocdrev = <num> ; # JTAGICE3 parameter from ATDF files
# pgm_enable = <instruction format> ;
# chip_erase = <instruction format> ;
Expand Down Expand Up @@ -15959,6 +15960,11 @@ part
# SRAM, only used to supply the offset
offset = 0x1000000;
;

memory "io"
size = 4096;
readsize = 1;
;
;

#------------------------------------------------------------
Expand Down Expand Up @@ -18509,6 +18515,7 @@ part
boot_section_size = 256;
nvm_base = 0x1000;
ocd_base = 0x0f80;
syscfg_base = 0x0f00;

memory "fuse0"
size = 1;
Expand Down Expand Up @@ -18632,7 +18639,7 @@ part

memory "sernum"
size = 10;
offset = 0x1104;
offset = 0x1103;
readsize = 1;
;

Expand Down Expand Up @@ -18665,6 +18672,11 @@ part
offset = 0x1000000;
;

memory "io"
size = 4352;
readsize = 1;
;

memory "sib"
size = 32;
readsize = 1;
Expand Down Expand Up @@ -20709,6 +20721,7 @@ part
hvupdi_variant = 1;
nvm_base = 0x1000;
ocd_base = 0x0f80;
syscfg_base = 0x0f00;

memory "fuse0"
size = 1;
Expand Down Expand Up @@ -20852,6 +20865,11 @@ part
offset = 0x1000000;
;

memory "io"
size = 4160;
readsize = 1;
;

memory "sib"
size = 32;
readsize = 1;
Expand Down
1 change: 1 addition & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ Component_t avr_comp[] = {
part_comp_desc(mcu_base, COMP_INT),
part_comp_desc(nvm_base, COMP_INT),
part_comp_desc(ocd_base, COMP_INT),
part_comp_desc(syscfg_base, COMP_INT),
part_comp_desc(ocdrev, COMP_INT),
part_comp_desc(autobaud_sync, COMP_CHAR),

Expand Down
1 change: 1 addition & 0 deletions src/developer_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool
_if_partout(intcmp, "0x%04x", mcu_base);
_if_partout(intcmp, "0x%04x", nvm_base);
_if_partout(intcmp, "0x%04x", ocd_base);
_if_partout(intcmp, "0x%04x", syscfg_base);
_if_partout(intcmp, "%d", ocdrev);
_if_partout(intcmp, "0x%02x", autobaud_sync);

Expand Down
1 change: 1 addition & 0 deletions src/doc/avrdude.texi
Original file line number Diff line number Diff line change
Expand Up @@ -2922,6 +2922,7 @@ part
mcu_base = <num> ; # MCU control block in ATxmega devices
nvm_base = <num> ; # NVM controller in ATxmega devices
ocd_base = <num> ; # OCD module in AVR8X/UPDI devices
syscfg_base = <num> ; # Chip revision ID in AVR8X/UPDI devices
ocdrev = <num> ; # JTAGICE3 parameter from ATDF files
pgm_enable = <instruction format> ;
chip_erase = <instruction format> ;
Expand Down
54 changes: 43 additions & 11 deletions src/jtag3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,13 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
}
}

// Read chip silicon revision
if(pgm->read_chip_rev && p->prog_modes & (PM_PDI | PM_UPDI)) {
char chip_rev[AVR_CHIP_REVLEN];
pgm->read_chip_rev(pgm, p, chip_rev);
pmsg_notice("silicon revision: %x.%x\n", chip_rev[0] >> 4, chip_rev[0] & 0x0f);
}

PDATA(pgm)->boot_start = ULONG_MAX;
if (p->prog_modes & PM_PDI) {
// Find the border between application and boot area
Expand Down Expand Up @@ -2128,17 +2135,17 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
paddr = addr & ~(pagesize - 1);
paddr_ptr = &PDATA(pgm)->eeprom_pageaddr;
cache_ptr = PDATA(pgm)->eeprom_pagecache;
} else if (strcmp(mem->desc, "lfuse") == 0) {
} else if (str_eq(mem->desc, "lfuse")) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 0;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "hfuse") == 0) {
} else if (str_eq(mem->desc, "hfuse")) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 1;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "efuse") == 0) {
} else if (str_eq(mem->desc, "efuse")) {
cmd[3] = MTYPE_FUSE_BITS;
addr = 2;
if (pgm->flag & PGM_FL_IS_DW)
Expand All @@ -2151,18 +2158,18 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
cmd[3] = MTYPE_FUSE_BITS;
if (!(p->prog_modes & PM_UPDI))
addr = mem->offset & 7;
} else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
} else if (str_eq(mem->desc, "usersig") ||
str_eq(mem->desc, "userrow")) {
cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) {
} else if (str_eq(mem->desc, "prodsig")) {
cmd[3] = MTYPE_PRODSIG;
} else if (strcmp(mem->desc, "sernum") == 0) {
} else if (str_eq(mem->desc, "sernum")) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osccal16") == 0) {
} else if (str_eq(mem->desc, "osccal16")) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osccal20") == 0) {
} else if (str_eq(mem->desc, "osccal20")) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "tempsense") == 0) {
} else if (str_eq(mem->desc, "tempsense")) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osc16err") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
Expand All @@ -2172,6 +2179,8 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
cmd[3] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "io") == 0) {
cmd[3] = MTYPE_SRAM;
} else if (str_eq(mem->desc, "sib")) {
if(addr >= AVR_SIBLEN) {
pmsg_error("cannot read byte from %s sib as address 0x%04lx outside range [0, 0x%04x]\n",
Expand Down Expand Up @@ -2338,7 +2347,9 @@ static int jtag3_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME
cmd[3] = MTYPE_LOCK_BITS;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
}
} else if (strcmp(mem->desc, "io") == 0)
cmd[3] = MTYPE_SRAM;

// Read-only memories or unsupported by debugWire
if(str_eq(mem->desc, "calibration") || str_eq(mem->desc, "osc16err") ||
str_eq(mem->desc, "osccal16") || str_eq(mem->desc, "osc20err") ||
Expand Down Expand Up @@ -2522,6 +2533,24 @@ int jtag3_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) {
return 0;
}

int jtag3_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, char *chip_rev) {
// XMEGA using JTAG or PDI, tinyAVR0/1/2, megaAVR0, AVR-Dx, AVR-Ex using UPDI
if(p->prog_modes & (PM_PDI | PM_UPDI)) {
AVRMEM *m = avr_locate_mem(p, "io");
int status = pgm->read_byte(pgm, p, m,
p->prog_modes & PM_PDI? p->mcu_base+3 :p->syscfg_base+1,
(unsigned char *)chip_rev);
if (status < 0)
return status;
} else {
pmsg_error("target does not have a chip revision that can be read\n");
return -1;
}

pmsg_debug("jtag3_read_chip_rev(): received chip silicon revision: 0x%02x\n", *chip_rev);
return 0;
}

int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) {
unsigned uaref, utarg;
unsigned char buf[2];
Expand Down Expand Up @@ -3213,6 +3242,7 @@ void jtag3_initpgm(PROGRAMMER *pgm) {
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_JTAG;
pgm->read_chip_rev = jtag3_read_chip_rev;

/*
* hardware dependent functions
Expand Down Expand Up @@ -3292,6 +3322,7 @@ void jtag3_pdi_initpgm(PROGRAMMER *pgm) {
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_PDI;
pgm->read_chip_rev = jtag3_read_chip_rev;

/*
* hardware dependent functions
Expand Down Expand Up @@ -3334,6 +3365,7 @@ void jtag3_updi_initpgm(PROGRAMMER *pgm) {
pgm->flag = PGM_FL_IS_UPDI;
pgm->unlock = jtag3_unlock_erase_key;
pgm->read_sib = jtag3_read_sib;
pgm->read_chip_rev = jtag3_read_chip_rev;

/*
* hardware dependent functions
Expand Down
36 changes: 36 additions & 0 deletions src/jtagmkII.c
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,12 @@ static int jtagmkII_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
"single-byte EEPROM updates not possible\n");
}

if (pgm->read_chip_rev && p->prog_modes & (PM_PDI | PM_UPDI)) {
char chip_rev[AVR_CHIP_REVLEN];
pgm->read_chip_rev(pgm, p, chip_rev);
pmsg_notice("silicon revision: %x.%x\n", chip_rev[0] >> 4, chip_rev[0] & 0x0f);
}

return 0;
}

Expand Down Expand Up @@ -2129,6 +2135,23 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV
return n_bytes;
}

static int jtagmkII_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, char *chip_rev) {
// XMEGA using JTAG or PDI, tinyAVR0/1/2, megaAVR0, AVR-Dx, AVR-Ex using UPDI
if(p->prog_modes & (PM_PDI | PM_UPDI)) {
AVRMEM *m = avr_locate_mem(p, "io");
int status = pgm->read_byte(pgm, p, m,
p->prog_modes & PM_PDI? p->mcu_base+3 :p->syscfg_base+1,
(unsigned char *)chip_rev);
if (status < 0)
return status;
} else {
pmsg_error("target does not have a chip revision that can be read\n");
return -1;
}

pmsg_debug("jtagmkII_read_chip_rev(): received chip silicon revision: 0x%02x\n", *chip_rev);
return 0;
}

static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char * value)
Expand Down Expand Up @@ -2195,6 +2218,10 @@ static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVR
cmd[1] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "io") == 0) {
cmd[1] = MTYPE_FLASH;
AVRMEM *data = avr_locate_mem(p, "data");
addr += data->offset;
} else if (strcmp(mem->desc, "signature") == 0) {
cmd[1] = MTYPE_SIGN_JTAG;

Expand Down Expand Up @@ -2361,6 +2388,10 @@ static int jtagmkII_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AV
cmd[1] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (strcmp(mem->desc, "io") == 0) {
cmd[1] = MTYPE_FLASH; // Works with jtag2updi, does not work with any xmega
AVRMEM *data = avr_locate_mem(p, "data");
addr += data->offset;
} else if (strcmp(mem->desc, "signature") == 0) {
cmd[1] = MTYPE_SIGN_JTAG;
if (pgm->flag & PGM_FL_IS_DW)
Expand Down Expand Up @@ -3636,6 +3667,7 @@ void jtagmkII_initpgm(PROGRAMMER *pgm) {
pgm->parseextparams = jtagmkII_parseextparms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->read_chip_rev = jtagmkII_read_chip_rev;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_JTAG;
}
Expand Down Expand Up @@ -3699,6 +3731,7 @@ void jtagmkII_pdi_initpgm(PROGRAMMER *pgm) {
pgm->print_parms = jtagmkII_print_parms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->read_chip_rev = jtagmkII_read_chip_rev;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_PDI;
}
Expand Down Expand Up @@ -3732,6 +3765,7 @@ void jtagmkII_updi_initpgm(PROGRAMMER *pgm) {
pgm->parseextparams = jtagmkII_parseextparms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->read_chip_rev = jtagmkII_read_chip_rev;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_PDI;
}
Expand Down Expand Up @@ -3766,6 +3800,7 @@ void jtagmkII_dragon_initpgm(PROGRAMMER *pgm) {
pgm->parseextparams = jtagmkII_parseextparms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->read_chip_rev = jtagmkII_read_chip_rev;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_JTAG;
}
Expand Down Expand Up @@ -3862,6 +3897,7 @@ void jtagmkII_dragon_pdi_initpgm(PROGRAMMER *pgm) {
pgm->print_parms = jtagmkII_print_parms;
pgm->setup = jtagmkII_setup;
pgm->teardown = jtagmkII_teardown;
pgm->read_chip_rev = jtagmkII_read_chip_rev;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_PDI;
}
2 changes: 1 addition & 1 deletion src/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ INF [Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])?
timeout | stabdelay | cmdexedelay | synchloops | bytedelay | pollindex | pollvalue | predelay | postdelay | pollmethod |
hventerstabdelay | progmodedelay | latchcycles | togglevtg | poweroffdelay | resetdelayms | resetdelayus | resetdelay | hvleavestabdelay |
chiperasetime | (chiperase|program(fuse|lock))(polltimeout|pulsewidth) | synchcycles | hvspcmdexedelay |
mcu_base | nvm_base | ocd_base | ocdrev |
mcu_base | nvm_base | ocd_base | syscfg_base | ocdrev |
autobaud_sync | idr | rampz | spmcr | eecr | eind |
paged | size | num_pages | initval | bitmask | n_word_writes | offset | min_write_delay | max_write_delay | pwroff_after_write |
readback_p1 | readback_p2 | mode | delay | blocksize | readsize ) {
Expand Down
3 changes: 3 additions & 0 deletions src/libavrdude.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ typedef struct opcode {

#define AVR_FAMILYIDLEN 7
#define AVR_SIBLEN 32
#define AVR_CHIP_REVLEN 1
#define CTL_STACK_SIZE 32
#define FLASH_INSTR_SIZE 3
#define EEPROM_INSTR_SIZE 20
Expand Down Expand Up @@ -307,6 +308,7 @@ typedef struct avrpart {
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 */
unsigned int syscfg_base; /* Base address of revision ID in AVR8X/UPDI devices */
int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */

/* Bootloader paramater */
Expand Down Expand Up @@ -813,6 +815,7 @@ typedef struct programmer_t {
unsigned long addr, unsigned char *value);
int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib);
int (*read_chip_rev) (const struct programmer_t *pgm, const AVRPART *p, char *chip_rev);
int (*term_keep_alive)(const struct programmer_t *pgm, const AVRPART *p);
void (*print_parms) (const struct programmer_t *pgm, FILE *fp);
int (*set_vtarget) (const struct programmer_t *pgm, double v);
Expand Down
9 changes: 8 additions & 1 deletion src/serialupdi.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ static int serialupdi_decode_sib(const PROGRAMMER *pgm, updi_sib_info *sib_info)
memset(sib_info->nvm_string, 0, SIB_INFO_NVM_LENGTH+1);
memset(sib_info->debug_string, 0, SIB_INFO_DEBUG_LENGTH+1);
memset(sib_info->pdi_string, 0, SIB_INFO_PDI_LENGTH+1);
memset(sib_info->pdi_string, 0, SIB_INFO_PDI_LENGTH+1);
memset(sib_info->extra_string, 0, SIB_INFO_EXTRA_LENGTH+1);

memcpy(sib_info->family_string, sib_info->sib_string, SIB_INFO_FAMILY_LENGTH);
Expand Down Expand Up @@ -633,6 +632,14 @@ static int serialupdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
return -1;
}

if (updi_read_data(pgm, p->syscfg_base+1, &value, 1) < 0) {
pmsg_error("Reading chip silicon revision failed\n");
return -1;
} else {
pmsg_debug("Received chip silicon revision 0x%02x\n", value);
pmsg_notice("Chip silicon revision: %x.%x\n", value >> 4, value & 0x0f);
}

if (updi_link_init(pgm) < 0) {
pmsg_error("UPDI link initialization failed\n");
return -1;
Expand Down
Loading