Skip to content

Commit

Permalink
Merge pull request #1474 from MCUdude/megaavr-chiprev
Browse files Browse the repository at this point in the history
Read chip silicon revision and add IO memory on chips with PDI and UPDI
  • Loading branch information
stefanrueger authored Aug 5, 2023
2 parents ea7eed8 + 28d4aa6 commit d5d4c35
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 15 deletions.
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

0 comments on commit d5d4c35

Please sign in to comment.