diff --git a/ChangeLog b/ChangeLog index e71cecc5..3dc10e57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-08-29 Joerg Wunsch + + bug #34027: avrdude AT90S1200 Problem (part 1 - bitbang + programmers) + * config_gram.y: Introduce new keyword "is_at90s1200". + * lexer.l: (Ditto.) + * avrdude.conf.in: Applew new keyword to the AT90S1200 device. + * avrpart.h: Introduce new flag AVRPART_IS_AT90S1200, reflecting + the is_at90s1200 configuration keyword. + * bitbang.c (bitbang_initialize): Replace existing test for + AT90S1200 by AVRPART_IS_AT90S1200 + * avr.c (avr_write_byte_default): Avoid the pre-write reading for + the AT90S1200, as this appears to sometimes corrupt the high byte + by pre-programming the low byte just written into it. + 2011-08-27 Joerg Wunsch * configure.ac: Bump version for post-5.11. diff --git a/avr.c b/avr.c index 09dab1fe..961487db 100644 --- a/avr.c +++ b/avr.c @@ -443,11 +443,17 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, return 0; } - if (!mem->paged) { + if (!mem->paged && + (p->flags & AVRPART_IS_AT90S1200) == 0) { /* * check to see if the write is necessary by reading the existing * value and only write if we are changing the value; we can't * use this optimization for paged addressing. + * + * For mysterious reasons, on the AT90S1200, this read operation + * sometimes causes the high byte of the same word to be + * programmed to the value of the low byte that has just been + * programmed before. Avoid that optimization on this device. */ rc = pgm->read_byte(pgm, p, mem, addr, &b); if (rc != 0) { diff --git a/avrdude.conf.in b/avrdude.conf.in index 39e21568..5d2d2d1a 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -1523,6 +1523,7 @@ part part id = "1200"; desc = "AT90S1200"; + is_at90s1200 = yes; stk500_devcode = 0x33; avr910_devcode = 0x13; signature = 0x1e 0x90 0x01; diff --git a/avrpart.h b/avrpart.h index 04334609..f868e948 100644 --- a/avrpart.h +++ b/avrpart.h @@ -93,6 +93,7 @@ typedef struct opcode { #define AVRPART_INIT_SMC 0x0200 /* part will undergo chip erase */ #define AVRPART_WRITE 0x0400 /* at least one write operation specified */ #define AVRPART_HAS_TPI 0x0800 /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */ +#define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */ #define AVR_DESCLEN 64 #define AVR_IDLEN 32 diff --git a/bitbang.c b/bitbang.c index ada885ac..00eb8277 100644 --- a/bitbang.c +++ b/bitbang.c @@ -606,7 +606,7 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p) * order to possibly get back into sync with the chip if we are out * of sync. */ - if (strcmp(p->desc, "AT90S1200")==0) { + if (p->flags & AVRPART_IS_AT90S1200) { pgm->program_enable(pgm, p); } else { diff --git a/config_gram.y b/config_gram.y index 3e10cd46..c676c828 100644 --- a/config_gram.y +++ b/config_gram.y @@ -225,6 +225,7 @@ static int parse_cmdbits(OPCODE * op); %token K_HAS_PDI /* MCU has PDI i/f rather than ISP (ATxmega). */ %token K_HAS_TPI /* MCU has TPI i/f rather than ISP (ATtiny4/5/9/10). */ %token K_IDR /* address of OCD register in IO space */ +%token K_IS_AT90S1200 /* chip is an AT90S1200 (needs special treatment) */ %token K_IS_AVR32 /* chip is in the avr32 family */ %token K_RAMPZ /* address of RAMPZ reg. in IO space */ %token K_SPMCR /* address of SPMC[S]R in memory space */ @@ -1166,6 +1167,16 @@ part_parm : free_token($3); } | + K_IS_AT90S1200 TKN_EQUAL yesno + { + if ($3->primary == K_YES) + current_part->flags |= AVRPART_IS_AT90S1200; + else if ($3->primary == K_NO) + current_part->flags &= AVRPART_IS_AT90S1200; + + free_token($3); + } | + K_IS_AVR32 TKN_EQUAL yesno { if ($3->primary == K_YES) @@ -1175,7 +1186,7 @@ part_parm : free_token($3); } | - + K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno { if ($3->primary == K_YES) diff --git a/lexer.l b/lexer.l index 6f1698f8..9870e7c6 100644 --- a/lexer.l +++ b/lexer.l @@ -155,6 +155,7 @@ has_pdi { yylval=NULL; return K_HAS_PDI; } has_tpi { yylval=NULL; return K_HAS_TPI; } id { yylval=NULL; return K_ID; } idr { yylval=NULL; return K_IDR; } +is_at90s1200 { yylval=NULL; return K_IS_AT90S1200; } is_avr32 { yylval=NULL; return K_IS_AVR32; } jtagmki { yylval=NULL; return K_JTAG_MKI; } jtagmkii { yylval=NULL; return K_JTAG_MKII; }