Prepare for new components in avrdude.conf incl prog_modes

- Add prog_modes to part and programmer definitions; prog_mode is a bitwise
   or of programming modes
     + PM_SPM: Bootloaders, self-programming with SPM/NVM Controllers
     + PM_TPI: t4, t5, t9, t10, t20, t40, t102, t104
     + PM_ISP: SPI programming for In-System Programming (typ classic parts)
     + PM_PDI: Program and Debug Interface (xmega parts)
     + PM_UPDI: Unified Program and Debug Interface
     + PM_HVSP: High Voltage Serial Programming (some classic parts)
     + PM_HVPP: High Voltage Parallel Programming (most non-HVSP classic parts)
     + PM_debugWIRE: Simpler alternative to JTAG (a subset of HVPP/HVSP parts)
     + PM_JTAG: some classic parts, some xmega
     + PM_aWire: AVR32 parts
 - Add mcuid, a unique id in 0..2039, to part definition for urclock programmer
 - Add n_interrupts, the number of interrupts, to part definition
 - Add n_page_erase to part definition (# of pages erased during NVM erase)

 - Implement a simple calculator in config_gram.y so numeric values can be
   expressed as simple expressions such as PM_SPM | PM_UPDI

 - Introduce a new method of assigning simple components to the grammar without
   touching config_gram.y via an eligible-component list in config.c; numeric
   expressions on the rhs of an assignment resolve to integer values

 - Update documentation in avrdude.conf.in and avrdude.texi
This commit is contained in:
Stefan Rueger 2022-08-30 02:08:15 +01:00
parent cddf2943eb
commit ed2b8342df
No known key found for this signature in database
GPG Key ID: B0B4F1FD86B1EC55
8 changed files with 542 additions and 142 deletions

View File

@ -21,39 +21,56 @@
# id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings # id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
# desc = <description> ; # quoted string # desc = <description> ; # quoted string
# type = <type>; # programmer type, quoted string # type = <type>; # programmer type, quoted string
# # supported programmer types can be listed by "-c ?type" # # supported types can be listed by "-c ?type"
# prog_modes = PM_<i/f> {| PM_<i/f>} # interfaces, eg, PM_SPM|PM_PDI (1)
# connection_type = parallel | serial | usb | spi # connection_type = parallel | serial | usb | spi
# baudrate = <num> ; # baudrate for avr910-programmer # baudrate = <num> ; # baudrate for avr910-programmer
# vcc = <num1> [, <num2> ... ] ; # pin number(s) # vcc = <pin1> [, <pin2> ... ] ; # pin number(s)
# buff = <num1> [, <num2> ... ] ; # pin number(s) # buff = <pin1> [, <pin2> ... ] ; # pin number(s)
# reset = <num> ; # pin number # reset = <pin> ; # pin number
# sck = <num> ; # pin number # sck = <pin> ; # pin number
# mosi = <num> ; # pin number # mosi = <pin> ; # pin number
# miso = <num> ; # pin number # miso = <pin> ; # pin number
# errled = <num> ; # pin number # errled = <pin> ; # pin number
# rdyled = <num> ; # pin number # rdyled = <pin> ; # pin number
# pgmled = <num> ; # pin number # pgmled = <pin> ; # pin number
# vfyled = <num> ; # pin number # vfyled = <pin> ; # pin number
# usbvid = <hexnum> ; # USB VID (Vendor ID) # usbvid = <hexnum> ; # USB VID (Vendor ID)
# usbpid = <hexnum> [, <hexnum> ...] ; # USB PID (Product ID) (1) # usbpid = <hexnum> [, <hexnum> ...] ; # USB PID (Product ID) (2)
# usbdev = <interface> ; # USB interface or other device info # usbdev = <interface> ; # USB interface or other device info
# usbvendor = <vendorname> ; # USB Vendor Name # usbvendor = <vendorname> ; # USB Vendor Name
# usbproduct = <productname> ; # USB Product Name # usbproduct = <productname> ; # USB Product Name
# usbsn = <serialno> ; # USB Serial Number # usbsn = <serialno> ; # USB Serial Number
# hvupdi_support = <num> [, <num>, ... ] ; # UPDI HV Variants Support # hvupdi_support = <num> [, <num>, ... ] ; # UPDI HV Variants Support
#
# To invert a bit, use = ~ <num>, the spaces are important.
# For a pin list all pins must be inverted.
# A single pin can be specified as usual = ~ <num>, for lists
# specify it as follows = ~ ( <num> [, <num2> ... ] ) .
#
# (1) Not all programmer types can process a list of PIDs.
# ; # ;
# #
# # To invert a bit, use = ~ <num>, the spaces are important.
# # For a pin list all pins must be inverted.
# # A single pin can be specified as usual = ~ <num>, for lists
# # specify it as follows = ~ ( <num> [, <num2> ... ] ).
# #
# # (1) The following program modes are known:
# # - PM_SPM: Bootloaders, self-programming with SPM opcodes or NVM Controllers
# # - PM_TPI: Tiny Programming Interface (t4, t5, t9, t10, t20, t40, t102, t104)
# # - PM_ISP: SPI programming for In-System Programming (almost all classic parts)
# # - PM_PDI: Program and Debug Interface (xmega parts)
# # - PM_UPDI: Unified Program and Debug Interface
# # - PM_HVSP: High Voltage Serial Programming (some classic parts)
# # - PM_HVPP: High Voltage Parallel Programming (most non-HVSP classic parts)
# # - PM_debugWIRE: Simpler alternative to JTAG (a subset of HVPP/HVSP parts)
# # - PM_JTAG: Joint Test Action Group standard (some classic parts, some xmega)
# # - PM_aWire: AVR32 parts
# #
# # (2) Not all programmer types can process a list of PIDs
#
# part # part
# desc = <description> ; # quoted string # desc = <description> ; # quoted string
# id = <id> ; # quoted string # id = <id> ; # quoted string
# family_id = <id> ; # quoted string, eg, "megaAVR" or "tinyAVR" # family_id = <id> ; # quoted string, eg, "megaAVR" or "tinyAVR"
# prog_modes = PM_<i/f> {| PM_<i/f>} # interfaces, eg, PM_SPM|PM_ISP|PM_HVPP|PM_debugWIRE
# mcuid = <num>; # unique id in 0..2039 for urclock programmer
# n_interrupts = <num>; # number of interrupts, used for vector bootloaders
# n_page_erase = <num>; # if set, number of pages erased during NVM erase
# hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2 # hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2
# devicecode = <num> ; # deprecated, use stk500_devcode # devicecode = <num> ; # deprecated, use stk500_devcode
# stk500_devcode = <num> ; # numeric # stk500_devcode = <num> ; # numeric
@ -63,8 +80,9 @@
# has_pdi = <yes/no> ; # part has PDI i/f # has_pdi = <yes/no> ; # part has PDI i/f
# has_updi = <yes/no> ; # part has UPDI i/f # has_updi = <yes/no> ; # part has UPDI i/f
# has_tpi = <yes/no> ; # part has TPI i/f # has_tpi = <yes/no> ; # part has TPI i/f
# is_at90s1200 = <yes/no> ; # AT90S1200 part
# is_avr32 = <yes/no> ; # AVR32 part # is_avr32 = <yes/no> ; # AVR32 part
#
# is_at90s1200 = <yes/no> ; # AT90S1200 part
# signature = <num> <num> <num> ; # signature bytes # signature = <num> <num> <num> ; # signature bytes
# usbpid = <num> ; # DFU USB PID # usbpid = <num> ; # DFU USB PID
# chip_erase_delay = <num> ; # micro-seconds # chip_erase_delay = <num> ; # micro-seconds
@ -247,7 +265,7 @@
# section avr061.zip which accompanies the application note # section avr061.zip which accompanies the application note
# AVR061 available from: # AVR061 available from:
# #
# http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf # https://ww1.microchip.com/downloads/en/Appnotes/doc2525.pdf
# #
#define ATTINY10 0x10 /* the _old_ one that never existed! */ #define ATTINY10 0x10 /* the _old_ one that never existed! */

View File

@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -44,6 +45,7 @@ LISTID number_list;
PROGRAMMER * current_prog; PROGRAMMER * current_prog;
AVRPART * current_part; AVRPART * current_part;
AVRMEM * current_mem; AVRMEM * current_mem;
int current_strct;
LISTID part_list; LISTID part_list;
LISTID programmers; LISTID programmers;
bool is_alias; bool is_alias;
@ -53,6 +55,22 @@ char * cfg_infile;
extern char * yytext; extern char * yytext;
#define pgm_comp_desc(x, type) { #x, COMP_PROGRAMMER, offsetof(PROGRAMMER, x), sizeof(((PROGRAMMER *) NULL)->x), type }
#define part_comp_desc(x, type) { #x, COMP_AVRPART, offsetof(AVRPART, x), sizeof(((AVRPART *) NULL)->x), type }
#define mem_comp_desc(x, type) { #x, COMP_AVRMEM, offsetof(AVRMEM, x), sizeof(((AVRMEM *) NULL)->x), type }
// Component description for config_gram.y, will be sorted appropriately on first use
Component_t avr_comp[] = {
// PROGRAMMER
pgm_comp_desc(prog_modes, COMP_INT),
// AVRPART
part_comp_desc(prog_modes, COMP_INT),
part_comp_desc(mcuid, COMP_INT),
part_comp_desc(n_interrupts, COMP_INT),
part_comp_desc(n_page_erase, COMP_INT),
};
#define DEBUG 0 #define DEBUG 0
void cleanup_config(void) void cleanup_config(void)
@ -190,7 +208,7 @@ void free_tokens(int n, ...)
TOKEN *number(const char *text) { TOKEN *new_number(const char *text) {
struct token_t *tkn = new_token(TKN_NUMBER); struct token_t *tkn = new_token(TKN_NUMBER);
tkn->value.type = V_NUM; tkn->value.type = V_NUM;
tkn->value.number = atoi(text); tkn->value.number = atoi(text);
@ -202,7 +220,7 @@ TOKEN *number(const char *text) {
return tkn; return tkn;
} }
TOKEN *number_real(const char *text) { TOKEN *new_number_real(const char *text) {
struct token_t * tkn = new_token(TKN_NUMBER); struct token_t * tkn = new_token(TKN_NUMBER);
tkn->value.type = V_NUM_REAL; tkn->value.type = V_NUM_REAL;
tkn->value.number_real = atof(text); tkn->value.number_real = atof(text);
@ -214,7 +232,7 @@ TOKEN *number_real(const char *text) {
return tkn; return tkn;
} }
TOKEN *hexnumber(const char *text) { TOKEN *new_hexnumber(const char *text) {
struct token_t *tkn = new_token(TKN_NUMBER); struct token_t *tkn = new_token(TKN_NUMBER);
char * e; char * e;
@ -233,11 +251,41 @@ TOKEN *hexnumber(const char *text) {
return tkn; return tkn;
} }
TOKEN *new_constant(const char *con) {
struct token_t *tkn = new_token(TKN_NUMBER);
int assigned = 1;
TOKEN *string(const char *text) { tkn->value.type = V_NUM;
tkn->value.number =
!strcmp("PM_SPM", con)? PM_SPM:
!strcmp("PM_TPI", con)? PM_TPI:
!strcmp("PM_ISP", con)? PM_ISP:
!strcmp("PM_PDI", con)? PM_PDI:
!strcmp("PM_UPDI", con)? PM_UPDI:
!strcmp("PM_HVSP", con)? PM_HVSP:
!strcmp("PM_HVPP", con)? PM_HVPP:
!strcmp("PM_debugWIRE", con)? PM_debugWIRE:
!strcmp("PM_JTAG", con)? PM_JTAG:
!strcmp("PM_aWire", con)? PM_aWire:
(assigned = 0);
if(!assigned) {
yyerror("can't identify constant %s", con);
free_token(tkn);
return NULL;
}
#if DEBUG
avrdude_message(MSG_INFO, "CONSTANT(%s=%d)\n", con, tkn->value.number);
#endif
return tkn;
}
TOKEN *new_string(const char *text) {
struct token_t *tkn = new_token(TKN_STRING); struct token_t *tkn = new_token(TKN_STRING);
tkn->value.type = V_STR; tkn->value.type = V_STR;
tkn->value.string = cfg_strdup("string()", text); tkn->value.string = cfg_strdup("new_string()", text);
#if DEBUG #if DEBUG
avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string); avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string);
@ -247,7 +295,7 @@ TOKEN *string(const char *text) {
} }
TOKEN * keyword(int primary) { TOKEN *new_keyword(int primary) {
return new_token(primary); return new_token(primary);
} }
@ -692,3 +740,97 @@ char *cfg_escape(const char *s) {
return cfg_strdup("cfg_escape()", buf); return cfg_strdup("cfg_escape()", buf);
} }
static int cmp_comp(const void *v1, const void *v2) {
const Component_t *c1 = v1, *c2 = v2;
int ret = strcmp(c1->name, c2->name);
return ret? ret: c1->strct - c2->strct;
}
Component_t *cfg_comp_search(const char *name, int strct) {
static int init;
Component_t key;
if(!init++)
qsort(avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component_t), cmp_comp);
key.name = name;
key.strct = strct;
return bsearch(&key, avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component_t), cmp_comp);
}
const char *cfg_strct_name(int strct) {
switch(strct) {
case COMP_CONFIG_MAIN: return "avrdude.conf main";
case COMP_AVRPART: return "AVRPART";
case COMP_AVRMEM: return "AVRMEM";
case COMP_PROGRAMMER: return "PROGRAMMER";
}
return "unknown struct";
}
const char *cfg_v_type(int type) {
switch(type) {
case V_NONE: return "void";
case V_NUM: return "number";
case V_NUM_REAL: return "real";
case V_STR: return "string";
case V_COMPONENT: return "component";
}
return "unknown v type";
}
const char *cfg_comp_type(int type) {
switch(type) {
case COMP_INT: return "number";
case COMP_SHORT: return "short";
case COMP_CHAR: return "char";
case COMP_STRING: return "string";
case COMP_CHAR_ARRAY: return "byte array";
case COMP_INT_LISTID: return "number list";
case COMP_STRING_LISTID: return "string list";
case COMP_OPCODE: return "opcode";
case COMP_PIN: return "pin";
case COMP_PIN_LIST: return "pin list";
}
return "unknown comp type";
}
// Used by config_gram.y to assign a component in one of the relevant structures with a value
void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v) {
const char *str;
int num;
switch(cp->type) {
case COMP_CHAR:
case COMP_SHORT:
case COMP_INT:
if(v->type != V_NUM) {
yywarning("%s in %s expects a %s but is assigned a %s",
cp->name, cfg_strct_name(strct), cfg_comp_type(cp->type), cfg_v_type(v->type));
return;
}
// TODO: consider endianess (code currently assumes little endian)
num = v->number;
memcpy(sp+cp->offset, &num, cp->size);
break;
case COMP_STRING:
if(v->type != V_STR) {
yywarning("%s in %s expects a string but is assigned a %s",
cp->name, cfg_strct_name(strct), cfg_v_type(v->type));
return;
}
str = cache_string(v->string);
memcpy(sp+cp->offset, &str, cp->size);
break;
// TODO: implement COMP_CHAR_ARRAY, COMP_INT_LISTID, COMP_STRING_LISTID, ...
default:
yywarning("%s in %s expects a %s but that is not implemented",
cp->name, cfg_strct_name(strct), cfg_comp_type(cp->type));
}
}

View File

@ -37,13 +37,48 @@ typedef struct {
} COMMENT; } COMMENT;
enum { V_NONE, V_NUM, V_NUM_REAL, V_STR }; enum { // Which structures a component can occur in
COMP_CONFIG_MAIN,
COMP_PROGRAMMER,
COMP_AVRPART,
COMP_AVRMEM,
};
enum { // Component types in structure
COMP_INT,
COMP_SHORT,
COMP_CHAR,
COMP_STRING,
COMP_CHAR_ARRAY, // This and below are not yet implemented
COMP_INT_LISTID,
COMP_STRING_LISTID,
COMP_OPCODE,
COMP_PIN, // Pins may never be implemented
COMP_PIN_LIST
};
typedef struct { // Description of a component in a structure
const char *name; // Component name
int strct; // Structure, eg, COMP_AVRPART
int offset, size, type; // Location, size and type within structure
} Component_t;
enum { // Value types for VALUE struct
V_NONE,
V_NUM,
V_NUM_REAL,
V_STR,
V_COMPONENT,
};
typedef struct value_t { typedef struct value_t {
int type; int type;
union { union {
int number; int number;
double number_real; double number_real;
char * string; char * string;
Component_t *comp;
}; };
} VALUE; } VALUE;
@ -59,6 +94,7 @@ extern FILE * yyin;
extern PROGRAMMER * current_prog; extern PROGRAMMER * current_prog;
extern AVRPART * current_part; extern AVRPART * current_part;
extern AVRMEM * current_mem; extern AVRMEM * current_mem;
int current_strct;
extern int cfg_lineno; extern int cfg_lineno;
extern char * cfg_infile; extern char * cfg_infile;
extern LISTID string_list; extern LISTID string_list;
@ -87,15 +123,17 @@ void free_token(TOKEN *tkn);
void free_tokens(int n, ...); void free_tokens(int n, ...);
TOKEN *number(const char *text); TOKEN *new_number(const char *text);
TOKEN *number_real(const char *text); TOKEN *new_number_real(const char *text);
TOKEN *hexnumber(const char *text); TOKEN *new_hexnumber(const char *text);
TOKEN *string(const char *text); TOKEN *new_constant(const char *text);
TOKEN *keyword(int primary); TOKEN *new_string(const char *text);
TOKEN *new_keyword(int primary);
void print_token(TOKEN *tkn); void print_token(TOKEN *tkn);
@ -115,6 +153,15 @@ LISTID cfg_move_comments(void);
void cfg_pop_comms(void); void cfg_pop_comms(void);
Component_t *cfg_comp_search(const char *name, int strct);
const char *cfg_v_type(int type);
const char *cfg_strct_name(int strct);
void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -208,12 +208,19 @@ static int pin_name;
%token TKN_COMMA %token TKN_COMMA
%token TKN_EQUAL %token TKN_EQUAL
%token TKN_SEMI %token TKN_SEMI
%token TKN_TILDE
%token TKN_LEFT_PAREN %token TKN_LEFT_PAREN
%token TKN_RIGHT_PAREN %token TKN_RIGHT_PAREN
%token TKN_NUMBER %token TKN_NUMBER
%token TKN_NUMBER_REAL %token TKN_NUMBER_REAL
%token TKN_STRING %token TKN_STRING
%token TKN_COMPONENT
%left OP_OR /* calculator operations */
%left OP_XOR
%left OP_AND
%left OP_PLUS OP_MINUS
%left OP_TIMES OP_DIVIDE OP_MODULO
%right OP_TILDE UNARY
%start configuration %start configuration
@ -229,6 +236,27 @@ number_real :
TKN_NUMBER_REAL { TKN_NUMBER_REAL {
$$ = $1; $$ = $1;
} }
;
expr: numexpr | TKN_STRING;
numexpr:
TKN_NUMBER |
numexpr OP_OR numexpr { $$ = $1; $$->value.number |= $3->value.number; } |
numexpr OP_XOR numexpr { $$ = $1; $$->value.number ^= $3->value.number; } |
numexpr OP_AND numexpr { $$ = $1; $$->value.number &= $3->value.number; } |
numexpr OP_PLUS numexpr { $$ = $1; $$->value.number += $3->value.number; } |
numexpr OP_MINUS numexpr { $$ = $1; $$->value.number -= $3->value.number; } |
numexpr OP_TIMES numexpr { $$ = $1; $$->value.number *= $3->value.number; } |
numexpr OP_DIVIDE numexpr { $$ = $1; $$->value.number /= $3->value.number; } |
numexpr OP_MODULO numexpr { $$ = $1; $$->value.number %= $3->value.number; } |
OP_PLUS numexpr %prec UNARY { $$ = $2; } |
OP_MINUS numexpr %prec UNARY { $$ = $2; $$->value.number = -$$->value.number; } |
OP_TILDE numexpr %prec UNARY { $$ = $2; $$->value.number = ~$$->value.number; } |
TKN_LEFT_PAREN numexpr TKN_RIGHT_PAREN { $$ = $2; }
;
configuration : configuration :
/* empty */ | config /* empty */ | config
@ -302,6 +330,7 @@ prog_def :
// pgm_fill_old_pins(current_prog); // TODO to be removed if old pin data no longer needed // pgm_fill_old_pins(current_prog); // TODO to be removed if old pin data no longer needed
// pgm_display_generic(current_prog, id); // pgm_display_generic(current_prog, id);
current_prog = NULL; current_prog = NULL;
current_strct = COMP_CONFIG_MAIN;
} }
; ;
@ -309,6 +338,7 @@ prog_def :
prog_decl : prog_decl :
K_PROGRAMMER K_PROGRAMMER
{ current_prog = pgm_new(); { current_prog = pgm_new();
current_strct = COMP_PROGRAMMER;
current_prog->config_file = cache_string(cfg_infile); current_prog->config_file = cache_string(cfg_infile);
current_prog->lineno = cfg_lineno; current_prog->lineno = cfg_lineno;
} }
@ -322,6 +352,7 @@ prog_decl :
YYABORT; YYABORT;
} }
current_prog = pgm_dup(pgm); current_prog = pgm_dup(pgm);
current_strct = COMP_PROGRAMMER;
current_prog->parent_id = cache_string($3->value.string); current_prog->parent_id = cache_string($3->value.string);
current_prog->comments = NULL; current_prog->comments = NULL;
current_prog->config_file = cache_string(cfg_infile); current_prog->config_file = cache_string(cfg_infile);
@ -389,6 +420,7 @@ part_def :
current_part->comments = cfg_move_comments(); current_part->comments = cfg_move_comments();
LISTADD(part_list, current_part); LISTADD(part_list, current_part);
current_part = NULL; current_part = NULL;
current_strct = COMP_CONFIG_MAIN;
} }
; ;
@ -396,6 +428,7 @@ part_decl :
K_PART K_PART
{ {
current_part = avr_new_part(); current_part = avr_new_part();
current_strct = COMP_AVRPART;
current_part->config_file = cache_string(cfg_infile); current_part->config_file = cache_string(cfg_infile);
current_part->lineno = cfg_lineno; current_part->lineno = cfg_lineno;
} | } |
@ -409,6 +442,7 @@ part_decl :
} }
current_part = avr_dup_part(parent_part); current_part = avr_dup_part(parent_part);
current_strct = COMP_AVRPART;
current_part->parent_id = cache_string($3->value.string); current_part->parent_id = cache_string($3->value.string);
current_part->comments = NULL; current_part->comments = NULL;
current_part->config_file = cache_string(cfg_infile); current_part->config_file = cache_string(cfg_infile);
@ -435,6 +469,10 @@ prog_parms :
; ;
prog_parm : prog_parm :
TKN_COMPONENT TKN_EQUAL expr {
cfg_assign((char *) current_prog, COMP_PROGRAMMER, $1->value.comp, &$3->value);
free_token($1);
} |
K_ID TKN_EQUAL string_list { K_ID TKN_EQUAL string_list {
{ {
while (lsize(string_list)) { while (lsize(string_list)) {
@ -589,7 +627,7 @@ hvupdi_support_list:
pin_number_non_empty: pin_number_non_empty:
TKN_NUMBER { if(0 != assign_pin(pin_name, $1, 0)) YYABORT; } TKN_NUMBER { if(0 != assign_pin(pin_name, $1, 0)) YYABORT; }
| |
TKN_TILDE TKN_NUMBER { if(0 != assign_pin(pin_name, $2, 1)) YYABORT; } OP_TILDE TKN_NUMBER { if(0 != assign_pin(pin_name, $2, 1)) YYABORT; }
; ;
pin_number: pin_number:
@ -601,7 +639,7 @@ pin_number:
pin_list_element: pin_list_element:
pin_number_non_empty pin_number_non_empty
| |
TKN_TILDE TKN_LEFT_PAREN num_list TKN_RIGHT_PAREN { if(0 != assign_pin_list(1)) YYABORT; } OP_TILDE TKN_LEFT_PAREN num_list TKN_RIGHT_PAREN { if(0 != assign_pin_list(1)) YYABORT; }
; ;
pin_list_non_empty: pin_list_non_empty:
@ -665,6 +703,10 @@ retry_lines :
; ;
part_parm : part_parm :
TKN_COMPONENT TKN_EQUAL expr {
cfg_assign((char *) current_part, COMP_AVRPART, $1->value.comp, &$3->value);
free_token($1);
} |
K_ID TKN_EQUAL TKN_STRING K_ID TKN_EQUAL TKN_STRING
{ {
current_part->id = cache_string($3->value.string); current_part->id = cache_string($3->value.string);
@ -1075,51 +1117,61 @@ part_parm :
K_HAS_JTAG TKN_EQUAL yesno K_HAS_JTAG TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES) {
current_part->flags |= AVRPART_HAS_JTAG; current_part->flags |= AVRPART_HAS_JTAG;
else if ($3->primary == K_NO) current_part->prog_modes |= PM_JTAG;
} else if ($3->primary == K_NO) {
current_part->flags &= ~AVRPART_HAS_JTAG; current_part->flags &= ~AVRPART_HAS_JTAG;
current_part->prog_modes &= ~PM_JTAG;
}
free_token($3); free_token($3);
} | } |
K_HAS_DW TKN_EQUAL yesno K_HAS_DW TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES) {
current_part->flags |= AVRPART_HAS_DW; current_part->flags |= AVRPART_HAS_DW;
else if ($3->primary == K_NO) current_part->prog_modes |= PM_debugWIRE;
} else if ($3->primary == K_NO) {
current_part->flags &= ~AVRPART_HAS_DW; current_part->flags &= ~AVRPART_HAS_DW;
current_part->prog_modes &= ~PM_debugWIRE;
}
free_token($3); free_token($3);
} | } |
K_HAS_PDI TKN_EQUAL yesno K_HAS_PDI TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES) {
current_part->flags |= AVRPART_HAS_PDI; current_part->flags |= AVRPART_HAS_PDI;
else if ($3->primary == K_NO) current_part->prog_modes |= PM_PDI;
} else if ($3->primary == K_NO) {
current_part->flags &= ~AVRPART_HAS_PDI; current_part->flags &= ~AVRPART_HAS_PDI;
current_part->prog_modes &= ~PM_PDI;
}
free_token($3); free_token($3);
} | } |
K_HAS_UPDI TKN_EQUAL yesno K_HAS_UPDI TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES) {
current_part->flags |= AVRPART_HAS_UPDI; current_part->flags |= AVRPART_HAS_UPDI;
else if ($3->primary == K_NO) current_part->prog_modes |= PM_UPDI;
} else if ($3->primary == K_NO) {
current_part->flags &= ~AVRPART_HAS_UPDI; current_part->flags &= ~AVRPART_HAS_UPDI;
current_part->prog_modes &= ~PM_UPDI;
}
free_token($3); free_token($3);
} | } |
K_HAS_TPI TKN_EQUAL yesno K_HAS_TPI TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES) {
current_part->flags |= AVRPART_HAS_TPI; current_part->flags |= AVRPART_HAS_TPI;
else if ($3->primary == K_NO) current_part->prog_modes |= PM_TPI;
} else if ($3->primary == K_NO) {
current_part->flags &= ~AVRPART_HAS_TPI; current_part->flags &= ~AVRPART_HAS_TPI;
current_part->prog_modes &= ~PM_TPI;
}
free_token($3); free_token($3);
} | } |
@ -1135,11 +1187,13 @@ part_parm :
K_IS_AVR32 TKN_EQUAL yesno K_IS_AVR32 TKN_EQUAL yesno
{ {
if ($3->primary == K_YES) if ($3->primary == K_YES) {
current_part->flags |= AVRPART_AVR32; current_part->flags |= AVRPART_AVR32;
else if ($3->primary == K_NO) current_part->prog_modes |= PM_aWire;
} else if ($3->primary == K_NO) {
current_part->flags &= ~AVRPART_AVR32; current_part->flags &= ~AVRPART_AVR32;
current_part->prog_modes &= ~PM_aWire;
}
free_token($3); free_token($3);
} | } |
@ -1255,14 +1309,6 @@ part_parm :
} | } |
/*
K_EEPROM { current_mem = AVR_M_EEPROM; }
mem_specs |
K_FLASH { current_mem = AVR_M_FLASH; }
mem_specs |
*/
K_MEMORY TKN_STRING K_MEMORY TKN_STRING
{ /* select memory for extension or create if not there */ { /* select memory for extension or create if not there */
AVRMEM *mem = avr_locate_mem_noalias(current_part, $2->value.string); AVRMEM *mem = avr_locate_mem_noalias(current_part, $2->value.string);
@ -1273,6 +1319,7 @@ part_parm :
} }
avr_add_mem_order($2->value.string); avr_add_mem_order($2->value.string);
current_mem = mem; current_mem = mem;
current_strct = COMP_AVRMEM;
free_token($2); free_token($2);
} }
mem_specs mem_specs
@ -1295,6 +1342,7 @@ part_parm :
} }
cfg_pop_comms(); cfg_pop_comms();
current_mem = NULL; current_mem = NULL;
current_strct = COMP_AVRPART;
} | } |
K_MEMORY TKN_STRING TKN_EQUAL K_NULL K_MEMORY TKN_STRING TKN_EQUAL K_NULL
{ {
@ -1306,6 +1354,7 @@ part_parm :
free_token($2); free_token($2);
cfg_pop_comms(); cfg_pop_comms();
current_mem = NULL; current_mem = NULL;
current_strct = COMP_AVRPART;
} | } |
opcode TKN_EQUAL string_list { opcode TKN_EQUAL string_list {
{ {
@ -1355,6 +1404,11 @@ mem_specs :
mem_spec : mem_spec :
TKN_COMPONENT TKN_EQUAL expr {
cfg_assign((char *) current_mem, COMP_AVRMEM, $1->value.comp, &$3->value);
free_token($1);
} |
K_PAGED TKN_EQUAL yesno K_PAGED TKN_EQUAL yesno
{ {
current_mem->paged = $3->primary == K_YES ? 1 : 0; current_mem->paged = $3->primary == K_YES ? 1 : 0;

View File

@ -63,7 +63,7 @@ static struct {
const char *mcu, *var, *value; const char *mcu, *var, *value;
} ptinj[] = { } ptinj[] = {
// Add triples here, eg, {"ATmega328P", "mcuid", "999"}, // Add triples here, eg, {"ATmega328P", "mcuid", "999"},
{NULL, NULL, NULL}, {NULL, NULL, NULL},
}; };
static struct { static struct {
@ -134,7 +134,7 @@ static void printallopcodes(const AVRPART *p, const char *d, OPCODE * const *opa
// Programming modes // Programming modes
static char *prog_modes(const AVRPART *p) { static char *prog_modes_str_flags(const AVRPART *p) {
static char type[1024]; static char type[1024];
*type = 0; *type = 0;
@ -194,6 +194,34 @@ static char *prog_modes(const AVRPART *p) {
return type + (*type == '|'); return type + (*type == '|');
} }
static char *prog_modes_str(int pm) {
static char type[1024];
strcpy(type, "0");
if(pm & PM_SPM)
strcat(type, " | PM_SPM");
if(pm & PM_TPI)
strcat(type, " | PM_TPI");
if(pm & PM_ISP)
strcat(type, " | PM_ISP");
if(pm & PM_PDI)
strcat(type, " | PM_PDI");
if(pm & PM_UPDI)
strcat(type, " | PM_UPDI");
if(pm & PM_HVSP)
strcat(type, " | PM_HVSP");
if(pm & PM_HVPP)
strcat(type, " | PM_HVPP");
if(pm & PM_debugWIRE)
strcat(type, " | PM_debugWIRE");
if(pm & PM_JTAG)
strcat(type, " | PM_JTAG");
if(pm & PM_aWire)
strcat(type, " | PM_aWire");
return type + (type[1] == 0? 0: 4);
}
// Check whether address bits are where they should be in ISP commands // Check whether address bits are where they should be in ISP commands
static void checkaddr(int memsize, int pagesize, int opnum, const OPCODE *op, const AVRPART *p, const AVRMEM *m) { static void checkaddr(int memsize, int pagesize, int opnum, const OPCODE *op, const AVRPART *p, const AVRMEM *m) {
@ -573,6 +601,10 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool
_if_partout_str(strcmp, descstr, desc); _if_partout_str(strcmp, descstr, desc);
_if_partout_str(strcmp, cfg_escape(p->id), id); _if_partout_str(strcmp, cfg_escape(p->id), id);
_if_partout_str(strcmp, cfg_escape(p->family_id), family_id); _if_partout_str(strcmp, cfg_escape(p->family_id), family_id);
_if_partout_str(intcmp, cfg_strdup("dev_part_strct()", prog_modes_str(p->prog_modes)), prog_modes);
_if_partout(intcmp, "%d", mcuid);
_if_partout(intcmp, "%d", n_interrupts);
_if_partout(intcmp, "%d", n_page_erase);
_if_partout(intcmp, "%d", hvupdi_variant); _if_partout(intcmp, "%d", hvupdi_variant);
_if_partout(intcmp, "0x%02x", stk500_devcode); _if_partout(intcmp, "0x%02x", stk500_devcode);
_if_partout(intcmp, "0x%02x", avr910_devcode); _if_partout(intcmp, "0x%02x", avr910_devcode);
@ -1032,7 +1064,7 @@ void dev_output_part_defs(char *partdesc) {
nfuses, nfuses,
ok, ok,
p->flags, p->flags,
prog_modes(p), prog_modes_str_flags(p),
p->config_file, p->lineno p->config_file, p->lineno
); );
} }
@ -1189,6 +1221,7 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
_if_pgmout_str(strcmp, cfg_escape(pgm->desc), desc); _if_pgmout_str(strcmp, cfg_escape(pgm->desc), desc);
if(!base || base->initpgm != pgm->initpgm) if(!base || base->initpgm != pgm->initpgm)
_pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm)); _pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm));
_if_pgmout_str(intcmp, cfg_strdup("dev_pgm_strct()", prog_modes_str(pgm->prog_modes)), prog_modes);
if(!base || base->conntype != pgm->conntype) if(!base || base->conntype != pgm->conntype)
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype)); _pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));
_if_pgmout(intcmp, "%d", baudrate); _if_pgmout(intcmp, "%d", baudrate);

View File

@ -1694,34 +1694,53 @@ The format of the programmer definition is as follows:
@smallexample @smallexample
programmer programmer
parent <id> # <id> is a quoted string parent <id> # optional parent
id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
desc = <description> ; # quoted string desc = <description> ; # quoted string
type = "par" | "stk500" | ... ; # programmer type (see below for a list) type = <type>; # programmer type, quoted string
baudrate = <num> ; # baudrate for serial ports # supported types can be listed by "-c ?type"
vcc = <num1> [, <num2> ... ] ; # pin number(s) prog_modes = PM_<i/f> @{ | PM_<i/f> @} # interfaces, eg, PM_SPM|PM_PDI
buff = <num1> [, <num2> ... ] ; # pin number(s) connection_type = parallel | serial | usb | spi
reset = <num> ; # pin number baudrate = <num> ; # baudrate for avr910-programmer
sck = <num> ; # pin number vcc = <pin1> [, <pin2> ... ] ; # pin number(s)
mosi = <num> ; # pin number buff = <pin1> [, <pin2> ... ] ; # pin number(s)
miso = <num> ; # pin number reset = <pin> ; # pin number
errled = <num> ; # pin number sck = <pin> ; # pin number
rdyled = <num> ; # pin number mosi = <pin> ; # pin number
pgmled = <num> ; # pin number miso = <pin> ; # pin number
vfyled = <num> ; # pin number errled = <pin> ; # pin number
usbvid = <hexnum>; # USB VID (Vendor ID) rdyled = <pin> ; # pin number
usbpid = <hexnum> [, <hexnum> ...]; # USB PID (Product ID) pgmled = <pin> ; # pin number
usbdev = <interface>; # USB interface or other device info vfyled = <pin> ; # pin number
usbvendor = <vendorname>; # USB Vendor Name usbvid = <hexnum> ; # USB VID (Vendor ID)
usbproduct = <productname>; # USB Product Name usbpid = <hexnum> [, <hexnum> ...] ; # USB PID (Product ID)
usbsn = <serialno>; # USB Serial Number usbdev = <interface> ; # USB interface or other device info
; usbvendor = <vendorname> ; # USB Vendor Name
usbproduct = <productname> ; # USB Product Name
usbsn = <serialno> ; # USB Serial Number
hvupdi_support = <num> [, <num>, ... ] ; # UPDI HV Variants Support
;
@end smallexample @end smallexample
@noindent @noindent
If a parent is specified, all settings of it (except its ids) are used for the new If a parent is specified, all settings of it (except its ids) are used for the new
programmer. These values can be changed by new setting them for the new programmer. programmer. These values can be changed by new setting them for the new programmer.
@noindent
Known programming modes are
@itemize @bullet
@item @code{PM_SPM}: Bootloaders, self-programming with SPM opcodes or NVM Controllers
@item @code{PM_TPI}: Tiny Programming Interface (t4, t5, t9, t10, t20, t40, t102, t104)
@item @code{PM_ISP}: SPI programming for In-System Programming (almost all classic parts)
@item @code{PM_PDI}: Program and Debug Interface (xmega parts)
@item @code{PM_UPDI}: Unified Program and Debug Interface
@item @code{PM_HVSP}: High Voltage Serial Programming (some classic parts)
@item @code{PM_HVPP}: High Voltage Parallel Programming (most non-HVSP classic parts)
@item @code{PM_debugWIRE}: Simpler alternative to JTAG (a subset of HVPP/HVSP parts)
@item @code{PM_JTAG}: Joint Test Action Group standard (some classic parts, some xmega)
@item @code{PM_aWire}: AVR32 parts
@end itemize
@noindent @noindent
To invert a bit in the pin definitions, use @code{= ~ <num>}. To invert a bit in the pin definitions, use @code{= ~ <num>}.
@ -1729,7 +1748,7 @@ To invert a bit in the pin definitions, use @code{= ~ <num>}.
Not all programmer types can handle a list of USB PIDs. Not all programmer types can handle a list of USB PIDs.
@noindent @noindent
Following programmer types are currently implemented: The following programmer types are currently implemented:
@multitable @columnfractions .25 .6 @multitable @columnfractions .25 .6
@include programmer_types.texi @include programmer_types.texi
@ -1743,29 +1762,35 @@ Following programmer types are currently implemented:
@smallexample @smallexample
part part
id = <id> ; # quoted string
desc = <description> ; # quoted string desc = <description> ; # quoted string
family_id = <description> ; # quoted string id = <id> ; # quoted string
family_id = <id> ; # quoted string, eg, "megaAVR" or "tinyAVR"
prog_modes = PM_<i/f> @{ | PM_<i/f> @} # interfaces, eg, PM_SPM|PM_ISP|PM_HVPP|PM_debugWIRE
mcuid = <num>; # unique id in 0..2039 for urclock programmer
n_interrupts = <num>; # number of interrupts, used for vector bootloaders
n_page_erase = <num>; # if set, number of pages erased during NVM erase
hvupdi_variant = <num> ; # numeric -1 (n/a) or 0..2
devicecode = <num> ; # deprecated, use stk500_devcode
stk500_devcode = <num> ; # numeric
avr910_devcode = <num> ; # numeric
has_jtag = <yes/no> ; # part has JTAG i/f has_jtag = <yes/no> ; # part has JTAG i/f
has_debugwire = <yes/no> ; # part has debugWire i/f has_debugwire = <yes/no> ; # part has debugWire i/f
has_pdi = <yes/no> ; # part has PDI i/f has_pdi = <yes/no> ; # part has PDI i/f
has_updi = <yes/no> ; # part has UPDI i/f has_updi = <yes/no> ; # part has UPDI i/f
has_tpi = <yes/no> ; # part has TPI i/f has_tpi = <yes/no> ; # part has TPI i/f
devicecode = <num> ; # numeric is_avr32 = <yes/no> ; # AVR32 part
stk500_devcode = <num> ; # numeric is_at90s1200 = <yes/no> ; # AT90S1200 part
avr910_devcode = <num> ; # numeric
signature = <num> <num> <num> ; # signature bytes signature = <num> <num> <num> ; # signature bytes
usbpid = <num> ; # DFU USB PID usbpid = <num> ; # DFU USB PID
reset = dedicated | io;
retry_pulse = reset | sck;
pgm_enable = <instruction format> ;
chip_erase = <instruction format> ;
chip_erase_delay = <num> ; # micro-seconds chip_erase_delay = <num> ; # micro-seconds
reset = dedicated | io ;
retry_pulse = reset | sck ;
chip_erase_delay = <num> ; # chip erase delay (us)
# STK500 parameters (parallel programming IO lines) # STK500 parameters (parallel programming IO lines)
pagel = <num> ; # pin name in hex, i.e., 0xD7 pagel = <num> ; # pin name in hex, i.e., 0xD7
bs2 = <num> ; # pin name in hex, i.e., 0xA0 bs2 = <num> ; # pin name in hex, i.e., 0xA0
serial = <yes/no> ; # can use serial downloading serial = <yes/no> ; # can use serial downloading
parallel = <yes/no/pseudo>; # can use par. programming parallel = <yes/no/pseudo> ; # can use par. programming
# STK500v2 parameters, to be taken from Atmel's XML files # STK500v2 parameters, to be taken from Atmel's XML files
timeout = <num> ; timeout = <num> ;
stabdelay = <num> ; stabdelay = <num> ;
@ -1777,52 +1802,59 @@ part
predelay = <num> ; predelay = <num> ;
postdelay = <num> ; postdelay = <num> ;
pollmethod = <num> ; pollmethod = <num> ;
mode = <num> ;
delay = <num> ;
blocksize = <num> ;
readsize = <num> ;
hvspcmdexedelay = <num> ; hvspcmdexedelay = <num> ;
# STK500v2 HV programming parameters, from XML # STK500v2 HV programming parameters, from XML
pp_controlstack = <num>, <num>, ...; # PP only pp_controlstack = <num>, <num>, ... ; # PP only
hvsp_controlstack = <num>, <num>, ...; # HVSP only hvsp_controlstack = <num>, <num>, ... ; # HVSP only
hventerstabdelay = <num>; flash_instr = <num>, <num>, <num> ;
progmodedelay = <num>; # PP only eeprom_instr = <num>, <num>, ... ;
latchcycles = <num>; hventerstabdelay = <num> ;
togglevtg = <num>; progmodedelay = <num> ; # PP only
poweroffdelay = <num>; latchcycles = <num> ;
resetdelayms = <num>; togglevtg = <num> ;
resetdelayus = <num>; poweroffdelay = <num> ;
hvleavestabdelay = <num>; resetdelayms = <num> ;
resetdelay = <num>; resetdelayus = <num> ;
synchcycles = <num>; # HVSP only hvleavestabdelay = <num> ;
chiperasepulsewidth = <num>; # PP only resetdelay = <num> ;
chiperasepolltimeout = <num>; synchcycles = <num> ; # HVSP only
chiperasetime = <num>; # HVSP only chiperasepulsewidth = <num> ; # PP only
programfusepulsewidth = <num>; # PP only chiperasepolltimeout = <num> ;
programfusepolltimeout = <num>; chiperasetime = <num> ; # HVSP only
programlockpulsewidth = <num>; # PP only programfusepulsewidth = <num> ; # PP only
programlockpolltimeout = <num>; programfusepolltimeout = <num> ;
programlockpulsewidth = <num> ; # PP only
programlockpolltimeout = <num> ;
# JTAG ICE mkII parameters, also from XML files # JTAG ICE mkII parameters, also from XML files
allowfullpagebitstream = <yes/no> ; allowfullpagebitstream = <yes/no> ;
enablepageprogramming = <yes/no> ; enablepageprogramming = <yes/no> ;
idr = <num> ; # IO addr of IDR (OCD) reg. idr = <num> ; # IO addr of IDR (OCD) reg
rampz = <num> ; # IO addr of RAMPZ reg. rampz = <num> ; # IO addr of RAMPZ reg
spmcr = <num> ; # mem addr of SPMC[S]R reg. spmcr = <num> ; # mem addr of SPMC[S]R reg
eecr = <num> ; # mem addr of EECR reg. eecr = <num> ; # mem addr of EECR reg only when != 0x3f
# (only when != 0x3F) mcu_base = <num> ;
is_at90s1200 = <yes/no> ; # AT90S1200 part nvm_base = <num> ;
is_avr32 = <yes/no> ; # AVR32 part ocd_base = <num> ;
ocdrev = <num> ;
pgm_enable = <instruction format> ;
chip_erase = <instruction format> ;
memory <memtype> memory <memtype>
paged = <yes/no> ; # yes / no paged = <yes/no> ; # yes/no (flash only, do not use for EEPROM)
offset = <num> ; # memory offset
size = <num> ; # bytes size = <num> ; # bytes
page_size = <num> ; # bytes page_size = <num> ; # bytes
num_pages = <num> ; # numeric num_pages = <num> ; # numeric
min_write_delay = <num> ; # micro-seconds min_write_delay = <num> ; # micro-seconds
max_write_delay = <num> ; # micro-seconds max_write_delay = <num> ; # micro-seconds
readback_p1 = <num> ; # byte value readback = <num> <num> ; # pair of byte values
readback_p2 = <num> ; # byte value readback_p1 = <num> ; # byte value (first component)
pwroff_after_write = <yes/no> ; # yes / no readback_p2 = <num> ; # byte value (second component)
pwroff_after_write = <yes/no> ; # yes/no
mode = <num> ; # STK500 v2 file parameter from Atmel's XML files
delay = <num> ; # "
blocksize = <num> ; # "
readsize = <num> ; # "
read = <instruction format> ; read = <instruction format> ;
write = <instruction format> ; write = <instruction format> ;
read_lo = <instruction format> ; read_lo = <instruction format> ;
@ -1832,8 +1864,8 @@ part
loadpage_lo = <instruction format> ; loadpage_lo = <instruction format> ;
loadpage_hi = <instruction format> ; loadpage_hi = <instruction format> ;
writepage = <instruction format> ; writepage = <instruction format> ;
; ;
; ;
@end smallexample @end smallexample
@menu @menu
@ -1914,7 +1946,22 @@ write = "1 1 0 0 0 0 0 0 x x x x x x x x",
@end smallexample @end smallexample
As the address bit numbers in the SPI opcodes are highly systematic, they
don't really need to be specified. A compact version of the format
specification neither uses bit-numbers for address lines nor spaces. If such
a string is longer than 7 characters, then the characters @code{0}, @code{1},
@code{x}, @code{a}, @code{i} and @code{o} will be recognised as the
corresponding bit, whilst any of the characters @code{.}, @code{-}, @code{_}
or @code{/} can act as arbitrary visual separators, which are ignored.
Examples:
@smallexample
loadpage_lo = "0100.0000--000x.xxxx--xxaa.aaaa--iiii.iiii";
loadpage_lo = "0100.0000", "000x.xxxx", "xxaa.aaaa", "iiii.iiii";
@end smallexample
@c @c
@c Node @c Node

View File

@ -63,9 +63,9 @@ SIGN [+-]
%% %%
{SIGN}?{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; } {SIGN}?{DIGIT}+ { yylval = new_number(yytext); return TKN_NUMBER; }
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; } {SIGN}?{DIGIT}+"."{DIGIT}* { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
{SIGN}?"."{DIGIT}+ { yylval = number_real(yytext); return TKN_NUMBER_REAL; } {SIGN}?"."{DIGIT}+ { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
["]([^"\\\n]|\\.|\\\n)*["] { ["]([^"\\\n]|\\.|\\\n)*["] {
char *str= cfg_strdup("lexer.l", yytext); char *str= cfg_strdup("lexer.l", yytext);
@ -73,12 +73,12 @@ SIGN [+-]
size_t len = strlen(str); size_t len = strlen(str);
if(len) if(len)
str[len-1] = 0; str[len-1] = 0;
yylval = string(str); yylval = new_string(str);
free(str); free(str);
return TKN_STRING; return TKN_STRING;
} }
0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; } 0x{HEXDIGIT}+ { yylval = new_hexnumber(yytext); return TKN_NUMBER; }
#\n#\ PROGRAMMER\ DEFINITIONS\n#\n+ { /* Record comments so far as prologue and skip */ #\n#\ PROGRAMMER\ DEFINITIONS\n#\n+ { /* Record comments so far as prologue and skip */
cfg_capture_prologue(); cfg_capture_prologue();
@ -121,6 +121,23 @@ SIGN [+-]
} }
prog_modes|mcuid|n_interrupts|n_page_erase { /* Components for assignment */
Component_t *cp = cfg_comp_search(yytext, current_strct);
if(!cp) {
yyerror("Unknown component %s in %s", yytext, cfg_strct_name(current_strct));
return YYERRCODE;
}
yylval = new_token(TKN_COMPONENT);
yylval->value.comp = cp;
ccap();
return TKN_COMPONENT;
}
PM_SPM|PM_TPI|PM_ISP|PM_PDI|PM_UPDI|PM_HVSP|PM_HVPP|PM_debugWIRE|PM_JTAG|PM_aWire { /* Constants */
yylval = new_constant(yytext);
return TKN_NUMBER;
}
alias { yylval=NULL; return K_ALIAS; } alias { yylval=NULL; return K_ALIAS; }
allowfullpagebitstream { yylval=NULL; ccap(); return K_ALLOWFULLPAGEBITSTREAM; } allowfullpagebitstream { yylval=NULL; ccap(); return K_ALLOWFULLPAGEBITSTREAM; }
avr910_devcode { yylval=NULL; ccap(); return K_AVR910_DEVCODE; } avr910_devcode { yylval=NULL; ccap(); return K_AVR910_DEVCODE; }
@ -258,7 +275,17 @@ yes { yylval=new_token(K_YES); return K_YES; }
"," { yylval = NULL; pyytext(); return TKN_COMMA; } "," { yylval = NULL; pyytext(); return TKN_COMMA; }
"=" { yylval = NULL; pyytext(); return TKN_EQUAL; } "=" { yylval = NULL; pyytext(); return TKN_EQUAL; }
";" { yylval = NULL; pyytext(); return TKN_SEMI; } ";" { yylval = NULL; pyytext(); return TKN_SEMI; }
"~" { yylval = NULL; pyytext(); return TKN_TILDE; }
"|" { yylval = NULL; pyytext(); return OP_OR; }
"^" { yylval = NULL; pyytext(); return OP_XOR; }
"&" { yylval = NULL; pyytext(); return OP_AND; }
"+" { yylval = NULL; pyytext(); return OP_PLUS; }
"-" { yylval = NULL; pyytext(); return OP_MINUS; }
"*" { yylval = NULL; pyytext(); return OP_TIMES; }
"/" { yylval = NULL; pyytext(); return OP_DIVIDE; }
"%" { yylval = NULL; pyytext(); return OP_MODULO; }
"~" { yylval = NULL; pyytext(); return OP_TILDE; }
"(" { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; } "(" { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; }
")" { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; } ")" { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; }

View File

@ -169,6 +169,7 @@ enum ctl_stack_t {
CTL_STACK_HVSP /* high voltage serial programming control stack */ CTL_STACK_HVSP /* high voltage serial programming control stack */
}; };
/* /*
* serial programming instruction bit specifications * serial programming instruction bit specifications
*/ */
@ -197,6 +198,18 @@ typedef struct opcode {
#define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */ #define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */
#define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */ #define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */
// Programming modes for parts and programmers: reflect changes in lexer.l, developer_opts.c and config.c
#define PM_SPM 1 // Bootloaders, self-programming with SPM opcodes or NVM Controllers
#define PM_TPI 2 // Tiny Programming Interface (t4, t5, t9, t10, t20, t40, t102, t104)
#define PM_ISP 4 // SPI programming for In-System Programming (almost all classic parts)
#define PM_PDI 8 // Program and Debug Interface (xmega parts)
#define PM_UPDI 16 // Unified Program and Debug Interface
#define PM_HVSP 32 // High Voltage Serial Programming (some classic parts)
#define PM_HVPP 64 // High Voltage Parallel Programming (most non-HVSP classic parts)
#define PM_debugWIRE 128 // Simpler alternative to JTAG (a subset of HVPP/HVSP parts)
#define PM_JTAG 256 // Joint Test Action Group standard (some classic parts, some xmega)
#define PM_aWire 512 // AVR32 parts
#define HV_UPDI_VARIANT_0 0 /* Shared UPDI/GPIO/RESET pin, HV on UPDI pin (tinyAVR0/1/2)*/ #define HV_UPDI_VARIANT_0 0 /* Shared UPDI/GPIO/RESET pin, HV on UPDI pin (tinyAVR0/1/2)*/
#define HV_UPDI_VARIANT_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */ #define HV_UPDI_VARIANT_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */
#define HV_UPDI_VARIANT_2 2 /* Shared UPDI pin, HV on _RESET (AVR-Ex) */ #define HV_UPDI_VARIANT_2 2 /* Shared UPDI pin, HV on _RESET (AVR-Ex) */
@ -209,13 +222,24 @@ typedef struct opcode {
#define TAG_ALLOCATED 1 /* memory byte is allocated */ #define TAG_ALLOCATED 1 /* memory byte is allocated */
/* Any changes here, please also reflect in dev_part_strct() of developer_opts.c */ /*
* Any changes in AVRPART or AVRMEM, please also ensure changes are made in
* - lexer.l
* - Either Component_t avr_comp[] of config.c or in config_gram.y
* - dev_part_strct() in developer_opts.c
* - avr_new_part() and/or avr_new_memtype() in avrpart.c for
* initialisation; note that all const char * must be initialised with ""
*/
typedef struct avrpart { typedef struct avrpart {
const char * desc; /* long part name */ const char * desc; /* long part name */
const char * id; /* short part name */ const char * id; /* short part name */
LISTID comments; // Used by developer options -p*/[ASsr...] LISTID comments; // Used by developer options -p*/[ASsr...]
const char * parent_id; /* Used by developer options */ const char * parent_id; /* Used by developer options */
const char * family_id; /* family id in the SIB (avr8x) */ const char * family_id; /* family id in the SIB (avr8x) */
int prog_modes; /* Programming interfaces, see #define PM_... */
int mcuid; /* Unique id in 0..2039 for urclock programmer */
int n_interrupts; /* Number of interrupts, used for vector bootloaders */
int n_page_erase; /* If set, number of pages erased during NVM erase */
int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */ int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */
int stk500_devcode; /* stk500 device code */ int stk500_devcode; /* stk500 device code */
int avr910_devcode; /* avr910 device code */ int avr910_devcode; /* avr910 device code */
@ -262,7 +286,7 @@ typedef struct avrpart {
int programlockpulsewidth; /* stk500 v2 hv mode parameter */ int programlockpulsewidth; /* stk500 v2 hv mode parameter */
int programlockpolltimeout; /* stk500 v2 hv mode parameter */ int programlockpolltimeout; /* stk500 v2 hv mode parameter */
int synchcycles; /* stk500 v2 hv mode parameter */ int synchcycles; /* stk500 v2 hv mode parameter */
int hvspcmdexedelay; /* stk500 v2 xml file parameter */ int hvspcmdexedelay; /* stk500 v2 hv mode file parameter */
unsigned char idr; /* JTAG ICE mkII XML file parameter */ unsigned char idr; /* JTAG ICE mkII XML file parameter */
unsigned char rampz; /* JTAG ICE mkII XML file parameter */ unsigned char rampz; /* JTAG ICE mkII XML file parameter */
@ -677,13 +701,21 @@ typedef enum {
CONNTYPE_SPI CONNTYPE_SPI
} conntype_t; } conntype_t;
/* Any changes here, please also reflect in dev_pgm_strct() of developer_opts.c */ /*
* Any changes in PROGRAMMER, please also ensure changes are made in
* - lexer.l
* - Either Component_t avr_comp[] of config.c or config_gram.y
* - dev_pgm_strct() in developer_opts.c
* - pgm_new() in pgm.c for initialisation; note that all const char * must
* be initialised with ""
*/
typedef struct programmer_t { typedef struct programmer_t {
LISTID id; LISTID id;
const char *desc; const char *desc;
void (*initpgm)(struct programmer_t *pgm); // Sets up the AVRDUDE programmer void (*initpgm)(struct programmer_t *pgm); // Sets up the AVRDUDE programmer
LISTID comments; // Used by developer options -c*/[ASsr...] LISTID comments; // Used by developer options -c*/[ASsr...]
const char *parent_id; // Used by developer options const char *parent_id; // Used by developer options
int prog_modes; // Programming interfaces, see #define PM_...
struct pindef_t pin[N_PINS]; struct pindef_t pin[N_PINS];
conntype_t conntype; conntype_t conntype;
int baudrate; int baudrate;
@ -695,7 +727,7 @@ typedef struct programmer_t {
const char *usbproduct; const char *usbproduct;
LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x
// Values below are not set by config_gram.y; make sure fd is first for dev_pgm_raw() // Values below are not set by config_gram.y; ensure fd is first for dev_pgm_raw()
union filedescriptor fd; union filedescriptor fd;
char type[PGM_TYPELEN]; char type[PGM_TYPELEN];
char port[PGM_PORTLEN]; char port[PGM_PORTLEN];