diff --git a/ChangeLog b/ChangeLog index 6d6c4f6d..462665a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-12-29 Rene Liebscher + + bug #34302: Feature request : device configuration with parent classes + * config_gram.y: Added part parent rule and allow overwriting existing + data at several places + * avrdude.conf.in: Added description comment and m328/m328p as example + * avrpart.c: avr_dup_mem-functions now copy buf and tags memory block + only they are already allocated. + * lexer.l: Added parent as valid token + + (not in original patch) + * avrpart.c: New function avr_dup_opcode. avr_dup_mem/avr_dup_part- + functions now duplicate the opcodes in their op-array to avoid memory leaks. + * doc/avrdude.texi: Added description of part parent feature + 2011-12-29 Rene Liebscher patch #7687: Autogenerating programmers and parts lists for docs diff --git a/avrdude.conf.in b/avrdude.conf.in index 06b82a78..fe727e5c 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -138,6 +138,17 @@ # values. If a required parameter is left empty, AVRDUDE will # complain. # +# Parts can also inherit parameters from previously defined parts +# using the following syntax. In this case specified integer and +# string values override parameter values from the parent part. New +# memory definitions are added to the definitions inherited from the +# parent. +# +# part parent # quoted string +# id = ; # quoted string +# +# ; +# # NOTES: # * 'devicecode' is the device code used by the STK500 (see codes # listed below) @@ -9223,12 +9234,12 @@ part ; #------------------------------------------------------------ -# ATmega328P +# ATmega328 #------------------------------------------------------------ part - id = "m328p"; - desc = "ATmega328P"; + id = "m328"; + desc = "ATmega328"; has_debugwire = yes; flash_instr = 0xB6, 0x01, 0x11; eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, @@ -9236,7 +9247,7 @@ part 0x99, 0xF9, 0xBB, 0xAF; stk500_devcode = 0x86; # avr910_devcode = 0x; - signature = 0x1e 0x95 0x0F; + signature = 0x1e 0x95 0x14; pagel = 0xd7; bs2 = 0xc2; chip_erase_delay = 9000; @@ -9410,6 +9421,12 @@ part ; ; +part parent "m328" + id = "m328p"; + desc = "ATmega328P"; + signature = 0x1e 0x95 0x0F; +; + #------------------------------------------------------------ # ATtiny2313 #------------------------------------------------------------ diff --git a/avrpart.c b/avrpart.c index 90097a91..0dba3f64 100644 --- a/avrpart.c +++ b/avrpart.c @@ -47,6 +47,26 @@ OPCODE * avr_new_opcode(void) return m; } +static OPCODE * avr_dup_opcode(OPCODE * op) +{ + OPCODE * m; + + /* this makes life easier */ + if (op == NULL) { + return NULL; + } + + m = (OPCODE *)malloc(sizeof(*m)); + if (m == NULL) { + fprintf(stderr, "avr_dup_opcode(): out of memory\n"); + exit(1); + } + + memcpy(m, op, sizeof(*m)); + + return m; +} + /* * avr_set_bits() @@ -248,28 +268,37 @@ int avr_initmem(AVRPART * p) AVRMEM * avr_dup_mem(AVRMEM * m) { AVRMEM * n; + int i; n = avr_new_memtype(); *n = *m; - n->buf = (unsigned char *)malloc(n->size); - if (n->buf == NULL) { - fprintf(stderr, - "avr_dup_mem(): out of memory (memsize=%d)\n", - n->size); - exit(1); + if (m->buf != NULL) { + n->buf = (unsigned char *)malloc(n->size); + if (n->buf == NULL) { + fprintf(stderr, + "avr_dup_mem(): out of memory (memsize=%d)\n", + n->size); + exit(1); + } + memcpy(n->buf, m->buf, n->size); } - memcpy(n->buf, m->buf, n->size); - n->tags = (unsigned char *)malloc(n->size); - if (n->tags == NULL) { - fprintf(stderr, - "avr_dup_mem(): out of memory (memsize=%d)\n", - n->size); - exit(1); + if (m->tags != NULL) { + n->tags = (unsigned char *)malloc(n->size); + if (n->tags == NULL) { + fprintf(stderr, + "avr_dup_mem(): out of memory (memsize=%d)\n", + n->size); + exit(1); + } + memcpy(n->tags, m->tags, n->size); + } + + for (i = 0; i < AVR_OP_MAX; i++) { + n->op[i] = avr_dup_opcode(n->op[i]); } - memcpy(n->tags, m->tags, n->size); return n; } @@ -398,6 +427,7 @@ AVRPART * avr_dup_part(AVRPART * d) AVRPART * p; LISTID save; LNODEID ln; + int i; p = avr_new_part(); save = p->mem; @@ -410,6 +440,10 @@ AVRPART * avr_dup_part(AVRPART * d) ladd(p->mem, avr_dup_mem(ldata(ln))); } + for (i = 0; i < AVR_OP_MAX; i++) { + p->op[i] = avr_dup_opcode(p->op[i]); + } + return p; } diff --git a/config_gram.y b/config_gram.y index df6619c8..d25fe3bf 100644 --- a/config_gram.y +++ b/config_gram.y @@ -128,6 +128,7 @@ static int pin_name; %token K_PAGEL %token K_PAR %token K_PARALLEL +%token K_PARENT %token K_PART %token K_PGMLED %token K_PROGRAMMER @@ -316,13 +317,7 @@ prog_decl : part_def : - K_PART - { - current_part = avr_new_part(); - strcpy(current_part->config_file, infile); - current_part->lineno = lineno; - } - part_parms + part_decl part_parms { LNODEID ln; AVRMEM * m; @@ -376,6 +371,30 @@ part_def : } ; +part_decl : + K_PART + { + current_part = avr_new_part(); + strcpy(current_part->config_file, infile); + current_part->lineno = lineno; + } | + K_PART K_PARENT TKN_STRING + { + AVRPART * parent_part = locate_part(part_list, $3->value.string); + if (parent_part == NULL) { + fprintf(stderr, + "%s: error at %s:%d: can't find parent part", + progname, infile, lineno); + exit(1); + } + + current_part = avr_dup_part(parent_part); + strcpy(current_part->config_file, infile); + current_part->lineno = lineno; + + free_token($3); + } +; string_list : TKN_STRING { ladd(string_list, $1); } | @@ -632,19 +651,11 @@ part_parm : unsigned nbytes; int ok; - if (current_part->ctl_stack_type != CTL_STACK_NONE) - { - fprintf(stderr, - "%s: error at line %d of %s: " - "control stack already defined\n", - progname, lineno, infile); - exit(1); - } - current_part->ctl_stack_type = CTL_STACK_PP; nbytes = 0; ok = 1; + memset(current_part->controlstack, 0, CTL_STACK_SIZE); while (lsize(number_list)) { t = lrmv_n(number_list, 1); if (nbytes < CTL_STACK_SIZE) @@ -674,19 +685,11 @@ part_parm : unsigned nbytes; int ok; - if (current_part->ctl_stack_type != CTL_STACK_NONE) - { - fprintf(stderr, - "%s: error at line %d of %s: " - "control stack already defined\n", - progname, lineno, infile); - exit(1); - } - current_part->ctl_stack_type = CTL_STACK_HVSP; nbytes = 0; ok = 1; + memset(current_part->controlstack, 0, CTL_STACK_SIZE); while (lsize(number_list)) { t = lrmv_n(number_list, 1); if (nbytes < CTL_STACK_SIZE) @@ -719,6 +722,7 @@ part_parm : nbytes = 0; ok = 1; + memset(current_part->flash_instr, 0, FLASH_INSTR_SIZE); while (lsize(number_list)) { t = lrmv_n(number_list, 1); if (nbytes < FLASH_INSTR_SIZE) @@ -751,6 +755,7 @@ part_parm : nbytes = 0; ok = 1; + memset(current_part->eeprom_instr, 0, EEPROM_INSTR_SIZE); while (lsize(number_list)) { t = lrmv_n(number_list, 1); if (nbytes < EEPROM_INSTR_SIZE) @@ -1154,9 +1159,9 @@ part_parm : op = avr_new_opcode(); parse_cmdbits(op); if (current_part->op[opnum] != NULL) { - fprintf(stderr, + /*fprintf(stderr, "%s: warning at %s:%d: operation redefined\n", - progname, infile, lineno); + progname, infile, lineno);*/ free(current_part->op[opnum]); } current_part->op[opnum] = op; @@ -1281,9 +1286,9 @@ mem_spec : op = avr_new_opcode(); parse_cmdbits(op); if (current_mem->op[opnum] != NULL) { - fprintf(stderr, + /*fprintf(stderr, "%s: warning at %s:%d: operation redefined\n", - progname, infile, lineno); + progname, infile, lineno);*/ free(current_mem->op[opnum]); } current_mem->op[opnum] = op; diff --git a/doc/avrdude.texi b/doc/avrdude.texi index d822d372..da9a3bbd 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -1529,13 +1529,34 @@ part @end smallexample @menu +* Parent Part:: * Instruction Format:: @end menu @c @c Node @c -@node Instruction Format, , Part Definitions, Part Definitions +@node Parent Part, Instruction Format, Part Definitions, Part Definitions +@subsection Parent Part + +@noindent +Parts can also inherit parameters from previously defined parts +using the following syntax. In this case specified integer and +string values override parameter values from the parent part. New +memory definitions are added to the definitions inherited from the +parent. + +@smallexample + part parent # quoted string + id = ; # quoted string + + ; +@end smallexample + +@c +@c Node +@c +@node Instruction Format, , Parent Part, Part Definitions @subsection Instruction Format @noindent diff --git a/lexer.l b/lexer.l index 9870e7c6..a57ac237 100644 --- a/lexer.l +++ b/lexer.l @@ -177,6 +177,7 @@ paged { yylval=NULL; return K_PAGED; } pagel { yylval=NULL; return K_PAGEL; } par { yylval=NULL; return K_PAR; } parallel { yylval=NULL; return K_PARALLEL; } +parent { yylval=NULL; return K_PARENT; } part { yylval=NULL; return K_PART; } pgmled { yylval=NULL; return K_PGMLED; } programmer { yylval=NULL; return K_PROGRAMMER; }