bug #28744: Can't load bootloader to xmega128a1 (part 2, fix for

firmware >= V7.x)
* jtagmkII.c: Add firmware-version dependent handling of Xmega parameters.
V7.x firmware expects the NVM offsets being specified through the Xmega
parameters command, but left out as part of the memory address itself.
* jtagmkII_private.h: Add CMND_SET_XMEGA_PARAMS, and struct xmega_device_desc.
* config_gram.y: Add mcu_base keyword.
* avrpart.h: (Dito.)
* lexer.l: (Dito.)
* avrdude.conf.in (.xmega): add mcu_base, and data memory segment.



git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1078 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
Joerg Wunsch 2012-04-13 15:25:41 +00:00
parent df6f97d78c
commit 3a4b48b583
8 changed files with 174 additions and 6 deletions

View File

@ -1,3 +1,16 @@
2012-04-13 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #28744: Can't load bootloader to xmega128a1 (part 2, fix for
firmware >= V7.x)
* jtagmkII.c: Add firmware-version dependent handling of Xmega parameters.
V7.x firmware expects the NVM offsets being specified through the Xmega
parameters command, but left out as part of the memory address itself.
* jtagmkII_private.h: Add CMND_SET_XMEGA_PARAMS, and struct xmega_device_desc.
* config_gram.y: Add mcu_base keyword.
* avrpart.h: (Dito.)
* lexer.l: (Dito.)
* avrdude.conf.in (.xmega): add mcu_base, and data memory segment.
2012-03-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de> 2012-03-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #28744: Can't load bootloader to xmega128a1 (part 1, fix for bug #28744: Can't load bootloader to xmega128a1 (part 1, fix for

1
NEWS
View File

@ -57,6 +57,7 @@ Current:
- bug #34027: avrdude AT90S1200 Problem - bug #34027: avrdude AT90S1200 Problem
- bug #30451: Accessing some Xmega memory sections gives not - bug #30451: Accessing some Xmega memory sections gives not
supported error supported error
- bug #28744: Can't load bootloader to xmega128a1
* Keep track of input file contents * Keep track of input file contents

View File

@ -12286,6 +12286,7 @@ part
has_jtag = yes; has_jtag = yes;
has_pdi = yes; has_pdi = yes;
nvm_base = 0x01c0; nvm_base = 0x01c0;
mcu_base = 0x0090;
memory "prodsig" memory "prodsig"
size = 0x200; size = 0x200;
@ -12335,6 +12336,11 @@ part
size = 1; size = 1;
offset = 0x8f0027; offset = 0x8f0027;
; ;
memory "data"
# SRAM, only used to supply the offset
offset = 0x1000000;
;
; ;

View File

@ -156,6 +156,7 @@ typedef struct avrpart {
unsigned char rampz; /* 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 spmcr; /* JTAG ICE mkII XML file parameter */
unsigned short eecr; /* JTAC ICE mkII XML file parameter */ unsigned short 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 nvm_base; /* Base address of NVM controller in ATxmega devices */
OPCODE * op[AVR_OP_MAX]; /* opcodes */ OPCODE * op[AVR_OP_MAX]; /* opcodes */

View File

@ -93,6 +93,7 @@ static int pin_name;
%token K_IO %token K_IO
%token K_LOADPAGE %token K_LOADPAGE
%token K_MAX_WRITE_DELAY %token K_MAX_WRITE_DELAY
%token K_MCU_BASE
%token K_MIN_WRITE_DELAY %token K_MIN_WRITE_DELAY
%token K_MISO %token K_MISO
%token K_MOSI %token K_MOSI
@ -1079,6 +1080,12 @@ part_parm :
free_token($3); free_token($3);
} | } |
K_MCU_BASE TKN_EQUAL TKN_NUMBER
{
current_part->mcu_base = $3->value.number;
free_token($3);
} |
K_NVM_BASE TKN_EQUAL TKN_NUMBER K_NVM_BASE TKN_EQUAL TKN_NUMBER
{ {
current_part->nvm_base = $3->value.number; current_part->nvm_base = $3->value.number;

View File

@ -82,6 +82,9 @@ struct pdata
/* Start address of Xmega boot area */ /* Start address of Xmega boot area */
unsigned long boot_start; unsigned long boot_start;
/* Major firmware version (needed for Xmega programming) */
unsigned int fwver;
}; };
#define PDATA(pgm) ((struct pdata *)(pgm->cookie)) #define PDATA(pgm) ((struct pdata *)(pgm->cookie))
@ -143,6 +146,7 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int page_size,
unsigned int addr, unsigned int n_bytes); unsigned int addr, unsigned int n_bytes);
static unsigned char jtagmkII_memtype(PROGRAMMER * pgm, AVRPART * p, unsigned long addr); static unsigned char jtagmkII_memtype(PROGRAMMER * pgm, AVRPART * p, unsigned long addr);
static unsigned int jtagmkII_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr);
// AVR32 // AVR32
#define ERROR_SAB 0xFFFFFFFF #define ERROR_SAB 0xFFFFFFFF
@ -724,6 +728,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
if (status > 0) { if (status > 0) {
if ((c = resp[0]) == RSP_SIGN_ON) { if ((c = resp[0]) == RSP_SIGN_ON) {
fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7]; fwver = ((unsigned)resp[8] << 8) | (unsigned)resp[7];
PDATA(pgm)->fwver = fwver;
hwver = (unsigned)resp[9]; hwver = (unsigned)resp[9];
memcpy(PDATA(pgm)->serno, resp + 10, 6); memcpy(PDATA(pgm)->serno, resp + 10, 6);
if (verbose >= 1 && status > 17) { if (verbose >= 1 && status > 17) {
@ -1035,6 +1040,83 @@ static void jtagmkII_set_devdescr(PROGRAMMER * pgm, AVRPART * p)
} }
} }
static void jtagmkII_set_xmega_params(PROGRAMMER * pgm, AVRPART * p)
{
int status;
unsigned char *resp, c;
LNODEID ln;
AVRMEM * m;
struct {
unsigned char cmd;
struct xmega_device_desc dd;
} sendbuf;
memset(&sendbuf, 0, sizeof sendbuf);
sendbuf.cmd = CMND_SET_XMEGA_PARAMS;
u16_to_b2(sendbuf.dd.whatever, 0x0002);
sendbuf.dd.datalen = 47;
u16_to_b2(sendbuf.dd.nvm_base_addr, p->nvm_base);
u16_to_b2(sendbuf.dd.mcu_base_addr, p->mcu_base);
for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) {
PDATA(pgm)->flash_pagesize = m->page_size;
u16_to_b2(sendbuf.dd.flash_page_size, m->page_size * 2);
} else if (strcmp(m->desc, "eeprom") == 0) {
sendbuf.dd.eeprom_page_size = m->page_size;
u16_to_b2(sendbuf.dd.eeprom_size, m->size);
u32_to_b4(sendbuf.dd.nvm_eeprom_offset, m->offset);
} else if (strcmp(m->desc, "application") == 0) {
u32_to_b4(sendbuf.dd.app_size, m->size);
u32_to_b4(sendbuf.dd.nvm_app_offset, m->offset);
} else if (strcmp(m->desc, "boot") == 0) {
u16_to_b2(sendbuf.dd.boot_size, m->size);
u32_to_b4(sendbuf.dd.nvm_boot_offset, m->offset);
} else if (strcmp(m->desc, "fuse0") == 0) {
u32_to_b4(sendbuf.dd.nvm_fuse_offset, m->offset);
} else if (strcmp(m->desc, "lock") == 0) {
u32_to_b4(sendbuf.dd.nvm_lock_offset, m->offset);
} else if (strcmp(m->desc, "usersig") == 0) {
u32_to_b4(sendbuf.dd.nvm_user_sig_offset, m->offset);
} else if (strcmp(m->desc, "prodsig") == 0) {
u32_to_b4(sendbuf.dd.nvm_prod_sig_offset, m->offset);
} else if (strcmp(m->desc, "data") == 0) {
u32_to_b4(sendbuf.dd.nvm_data_offset, m->offset);
}
}
if (verbose >= 2)
fprintf(stderr, "%s: jtagmkII_set_xmega_params(): "
"Sending set Xmega params command: ",
progname);
jtagmkII_send(pgm, (unsigned char *)&sendbuf, sizeof sendbuf);
status = jtagmkII_recv(pgm, &resp);
if (status <= 0) {
if (verbose >= 2)
putc('\n', stderr);
fprintf(stderr,
"%s: jtagmkII_set_xmega_params(): "
"timeout/error communicating with programmer (status %d)\n",
progname, status);
return;
}
if (verbose >= 3) {
putc('\n', stderr);
jtagmkII_prmsg(pgm, resp, status);
} else if (verbose == 2)
fprintf(stderr, "0x%02x (%d bytes msg)\n", resp[0], status);
c = resp[0];
free(resp);
if (c != RSP_OK) {
fprintf(stderr,
"%s: jtagmkII_set_xmega_params(): "
"bad response to set device descriptor command: %s\n",
progname, jtagmkII_get_rc(c));
}
}
/* /*
* Reset the target. * Reset the target.
*/ */
@ -1287,6 +1369,9 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
/* /*
* Must set the device descriptor before entering programming mode. * Must set the device descriptor before entering programming mode.
*/ */
if (PDATA(pgm)->fwver >= 0x700 && (p->flags & AVRPART_HAS_PDI) != 0)
jtagmkII_set_xmega_params(pgm, p);
else
jtagmkII_set_devdescr(pgm, p); jtagmkII_set_devdescr(pgm, p);
PDATA(pgm)->boot_start = ULONG_MAX; PDATA(pgm)->boot_start = ULONG_MAX;
@ -1850,7 +1935,7 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[1] = jtagmkII_memtype(pgm, p, addr); cmd[1] = jtagmkII_memtype(pgm, p, addr);
u32_to_b4(cmd + 2, page_size); u32_to_b4(cmd + 2, page_size);
u32_to_b4(cmd + 6, addr+m->offset ); u32_to_b4(cmd + 6, jtagmkII_memaddr(pgm, p, m, addr));
/* /*
* The JTAG ICE will refuse to write anything but a full page, at * The JTAG ICE will refuse to write anything but a full page, at
@ -1924,7 +2009,7 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int maxaddr = addr + n_bytes; unsigned int maxaddr = addr + n_bytes;
unsigned char cmd[10]; unsigned char cmd[10];
unsigned char *resp; unsigned char *resp;
int status, tries; int status, tries, dynamic_memtype = 0;
long otimeout = serial_recv_timeout; long otimeout = serial_recv_timeout;
if (verbose >= 2) if (verbose >= 2)
@ -1937,8 +2022,12 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
page_size = m->readsize; page_size = m->readsize;
cmd[0] = CMND_READ_MEMORY; cmd[0] = CMND_READ_MEMORY;
cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE; cmd[1] = jtagmkII_memtype(pgm, p, addr);
if (strcmp(m->desc, "eeprom") == 0) { if (strcmp(m->desc, "flash") == 0) {
if (p->flags & AVRPART_HAS_PDI)
/* dynamically decide between flash/boot memtype */
dynamic_memtype = 1;
} else if (strcmp(m->desc, "eeprom") == 0) {
cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; cmd[1] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
if (pgm->flag & PGM_FL_IS_DW) if (pgm->flag & PGM_FL_IS_DW)
return -1; return -1;
@ -1958,8 +2047,11 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
"block_size at addr %d is %d\n", "block_size at addr %d is %d\n",
progname, addr, block_size); progname, addr, block_size);
if (dynamic_memtype)
cmd[1] = jtagmkII_memtype(pgm, p, addr);
u32_to_b4(cmd + 2, block_size); u32_to_b4(cmd + 2, block_size);
u32_to_b4(cmd + 6, addr+m->offset ); u32_to_b4(cmd + 6, jtagmkII_memaddr(pgm, p, m, addr));
tries = 0; tries = 0;
@ -2544,6 +2636,31 @@ static unsigned char jtagmkII_memtype(PROGRAMMER * pgm, AVRPART * p, unsigned lo
} }
} }
static unsigned int jtagmkII_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned long addr)
{
/*
* Xmega devices handled by V7+ firmware don't want to be told their
* m->offset within the write memory command.
*/
if (PDATA(pgm)->fwver >= 0x700 && (p->flags & AVRPART_HAS_PDI) != 0) {
if (addr >= PDATA(pgm)->boot_start)
/*
* all memories but "flash" are smaller than boot_start anyway, so
* no need for an extra check we are operating on "flash"
*/
return addr - PDATA(pgm)->boot_start;
else
/* normal flash, or anything else */
return addr;
}
/*
* Old firmware, or non-Xmega device. Non-Xmega (and non-AVR32)
* devices always have an m->offset of 0, so we don't have to
* distinguish them here.
*/
return addr + m->offset;
}
#ifdef __OBJC__ #ifdef __OBJC__
#pragma mark - #pragma mark -

View File

@ -111,6 +111,7 @@
#define CMND_WRITE_MEMORY32 0x2D #define CMND_WRITE_MEMORY32 0x2D
#define CMND_ISP_PACKET 0x2F #define CMND_ISP_PACKET 0x2F
#define CMND_XMEGA_ERASE 0x34 #define CMND_XMEGA_ERASE 0x34
#define CMND_SET_XMEGA_PARAMS 0x36 // undocumented in AVR067
/* ICE responses */ /* ICE responses */
@ -355,6 +356,27 @@ struct device_descriptor
/* new as of early 2005, firmware 4.x */ /* new as of early 2005, firmware 4.x */
unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */ unsigned char EECRAddress[2]; /* EECR memory-mapped IO address */
}; };
/* New Xmega device descriptor, for firmware version 7 and above */
struct xmega_device_desc {
unsigned char whatever[2]; // cannot guess; must be 0x0002
unsigned char datalen; // length of the following data, = 47
unsigned char nvm_app_offset[4]; // NVM offset for application flash
unsigned char nvm_boot_offset[4]; // NVM offset for boot flash
unsigned char nvm_eeprom_offset[4]; // NVM offset for EEPROM
unsigned char nvm_fuse_offset[4]; // NVM offset for fuses
unsigned char nvm_lock_offset[4]; // NVM offset for lock bits
unsigned char nvm_user_sig_offset[4]; // NVM offset for user signature row
unsigned char nvm_prod_sig_offset[4]; // NVM offset for production sign. row
unsigned char nvm_data_offset[4]; // NVM offset for data memory (SRAM + IO)
unsigned char app_size[4]; // size of application flash
unsigned char boot_size[2]; // size of boot flash
unsigned char flash_page_size[2]; // flash page size
unsigned char eeprom_size[2]; // size of EEPROM
unsigned char eeprom_page_size; // EEPROM page size
unsigned char nvm_base_addr[2]; // IO space base address of NVM controller
unsigned char mcu_base_addr[2]; // IO space base address of MCU control
};
#endif /* JTAGMKII_PRIVATE_EXPORTED */ #endif /* JTAGMKII_PRIVATE_EXPORTED */
/* return code from jtagmkII_getsync() to indicate a "graceful" /* return code from jtagmkII_getsync() to indicate a "graceful"

View File

@ -167,6 +167,7 @@ load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); return K_LOAD_EXT_ADDR; }
loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; } loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; }
loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; } loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; }
max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; } max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; }
mcu_base { yylval=NULL; return K_MCU_BASE; }
memory { yylval=NULL; return K_MEMORY; } memory { yylval=NULL; return K_MEMORY; }
min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; } min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; }
miso { yylval=NULL; return K_MISO; } miso { yylval=NULL; return K_MISO; }