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:
parent
cddf2943eb
commit
ed2b8342df
|
@ -21,39 +21,56 @@
|
|||
# id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
|
||||
# desc = <description> ; # 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
|
||||
# baudrate = <num> ; # baudrate for avr910-programmer
|
||||
# vcc = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
# buff = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
# reset = <num> ; # pin number
|
||||
# sck = <num> ; # pin number
|
||||
# mosi = <num> ; # pin number
|
||||
# miso = <num> ; # pin number
|
||||
# errled = <num> ; # pin number
|
||||
# rdyled = <num> ; # pin number
|
||||
# pgmled = <num> ; # pin number
|
||||
# vfyled = <num> ; # pin number
|
||||
# vcc = <pin1> [, <pin2> ... ] ; # pin number(s)
|
||||
# buff = <pin1> [, <pin2> ... ] ; # pin number(s)
|
||||
# reset = <pin> ; # pin number
|
||||
# sck = <pin> ; # pin number
|
||||
# mosi = <pin> ; # pin number
|
||||
# miso = <pin> ; # pin number
|
||||
# errled = <pin> ; # pin number
|
||||
# rdyled = <pin> ; # pin number
|
||||
# pgmled = <pin> ; # pin number
|
||||
# vfyled = <pin> ; # pin number
|
||||
# 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
|
||||
# usbvendor = <vendorname> ; # USB Vendor Name
|
||||
# usbproduct = <productname> ; # USB Product Name
|
||||
# usbsn = <serialno> ; # USB Serial Number
|
||||
# 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
|
||||
# desc = <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
|
||||
|
@ -63,8 +80,9 @@
|
|||
# has_pdi = <yes/no> ; # part has PDI i/f
|
||||
# has_updi = <yes/no> ; # part has UPDI i/f
|
||||
# has_tpi = <yes/no> ; # part has TPI i/f
|
||||
# is_at90s1200 = <yes/no> ; # AT90S1200 part
|
||||
# is_avr32 = <yes/no> ; # AVR32 part
|
||||
#
|
||||
# is_at90s1200 = <yes/no> ; # AT90S1200 part
|
||||
# signature = <num> <num> <num> ; # signature bytes
|
||||
# usbpid = <num> ; # DFU USB PID
|
||||
# chip_erase_delay = <num> ; # micro-seconds
|
||||
|
@ -247,7 +265,7 @@
|
|||
# section avr061.zip which accompanies the application note
|
||||
# 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! */
|
||||
|
|
154
src/config.c
154
src/config.c
|
@ -24,6 +24,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -44,6 +45,7 @@ LISTID number_list;
|
|||
PROGRAMMER * current_prog;
|
||||
AVRPART * current_part;
|
||||
AVRMEM * current_mem;
|
||||
int current_strct;
|
||||
LISTID part_list;
|
||||
LISTID programmers;
|
||||
bool is_alias;
|
||||
|
@ -53,6 +55,22 @@ char * cfg_infile;
|
|||
|
||||
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
|
||||
|
||||
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);
|
||||
tkn->value.type = V_NUM;
|
||||
tkn->value.number = atoi(text);
|
||||
|
@ -202,7 +220,7 @@ TOKEN *number(const char *text) {
|
|||
return tkn;
|
||||
}
|
||||
|
||||
TOKEN *number_real(const char *text) {
|
||||
TOKEN *new_number_real(const char *text) {
|
||||
struct token_t * tkn = new_token(TKN_NUMBER);
|
||||
tkn->value.type = V_NUM_REAL;
|
||||
tkn->value.number_real = atof(text);
|
||||
|
@ -214,7 +232,7 @@ TOKEN *number_real(const char *text) {
|
|||
return tkn;
|
||||
}
|
||||
|
||||
TOKEN *hexnumber(const char *text) {
|
||||
TOKEN *new_hexnumber(const char *text) {
|
||||
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||
char * e;
|
||||
|
||||
|
@ -233,11 +251,41 @@ TOKEN *hexnumber(const char *text) {
|
|||
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);
|
||||
tkn->value.type = V_STR;
|
||||
tkn->value.string = cfg_strdup("string()", text);
|
||||
tkn->value.string = cfg_strdup("new_string()", text);
|
||||
|
||||
#if DEBUG
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -692,3 +740,97 @@ char *cfg_escape(const char *s) {
|
|||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
59
src/config.h
59
src/config.h
|
@ -37,13 +37,48 @@ typedef struct {
|
|||
} 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 {
|
||||
int type;
|
||||
union {
|
||||
int number;
|
||||
double number_real;
|
||||
char * string;
|
||||
Component_t *comp;
|
||||
};
|
||||
} VALUE;
|
||||
|
||||
|
@ -59,6 +94,7 @@ extern FILE * yyin;
|
|||
extern PROGRAMMER * current_prog;
|
||||
extern AVRPART * current_part;
|
||||
extern AVRMEM * current_mem;
|
||||
int current_strct;
|
||||
extern int cfg_lineno;
|
||||
extern char * cfg_infile;
|
||||
extern LISTID string_list;
|
||||
|
@ -87,15 +123,17 @@ void free_token(TOKEN *tkn);
|
|||
|
||||
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);
|
||||
|
||||
|
@ -115,6 +153,15 @@ LISTID cfg_move_comments(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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -208,12 +208,19 @@ static int pin_name;
|
|||
%token TKN_COMMA
|
||||
%token TKN_EQUAL
|
||||
%token TKN_SEMI
|
||||
%token TKN_TILDE
|
||||
%token TKN_LEFT_PAREN
|
||||
%token TKN_RIGHT_PAREN
|
||||
%token TKN_NUMBER
|
||||
%token TKN_NUMBER_REAL
|
||||
%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
|
||||
|
||||
|
@ -229,6 +236,27 @@ number_real :
|
|||
TKN_NUMBER_REAL {
|
||||
$$ = $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 :
|
||||
/* 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_display_generic(current_prog, id);
|
||||
current_prog = NULL;
|
||||
current_strct = COMP_CONFIG_MAIN;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -309,6 +338,7 @@ prog_def :
|
|||
prog_decl :
|
||||
K_PROGRAMMER
|
||||
{ current_prog = pgm_new();
|
||||
current_strct = COMP_PROGRAMMER;
|
||||
current_prog->config_file = cache_string(cfg_infile);
|
||||
current_prog->lineno = cfg_lineno;
|
||||
}
|
||||
|
@ -322,6 +352,7 @@ prog_decl :
|
|||
YYABORT;
|
||||
}
|
||||
current_prog = pgm_dup(pgm);
|
||||
current_strct = COMP_PROGRAMMER;
|
||||
current_prog->parent_id = cache_string($3->value.string);
|
||||
current_prog->comments = NULL;
|
||||
current_prog->config_file = cache_string(cfg_infile);
|
||||
|
@ -389,6 +420,7 @@ part_def :
|
|||
current_part->comments = cfg_move_comments();
|
||||
LISTADD(part_list, current_part);
|
||||
current_part = NULL;
|
||||
current_strct = COMP_CONFIG_MAIN;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -396,6 +428,7 @@ part_decl :
|
|||
K_PART
|
||||
{
|
||||
current_part = avr_new_part();
|
||||
current_strct = COMP_AVRPART;
|
||||
current_part->config_file = cache_string(cfg_infile);
|
||||
current_part->lineno = cfg_lineno;
|
||||
} |
|
||||
|
@ -409,6 +442,7 @@ part_decl :
|
|||
}
|
||||
|
||||
current_part = avr_dup_part(parent_part);
|
||||
current_strct = COMP_AVRPART;
|
||||
current_part->parent_id = cache_string($3->value.string);
|
||||
current_part->comments = NULL;
|
||||
current_part->config_file = cache_string(cfg_infile);
|
||||
|
@ -435,6 +469,10 @@ prog_parms :
|
|||
;
|
||||
|
||||
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 {
|
||||
{
|
||||
while (lsize(string_list)) {
|
||||
|
@ -589,7 +627,7 @@ hvupdi_support_list:
|
|||
pin_number_non_empty:
|
||||
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:
|
||||
|
@ -601,7 +639,7 @@ pin_number:
|
|||
pin_list_element:
|
||||
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:
|
||||
|
@ -665,6 +703,10 @@ retry_lines :
|
|||
;
|
||||
|
||||
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
|
||||
{
|
||||
current_part->id = cache_string($3->value.string);
|
||||
|
@ -1075,51 +1117,61 @@ part_parm :
|
|||
|
||||
K_HAS_JTAG TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
if ($3->primary == K_YES) {
|
||||
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->prog_modes &= ~PM_JTAG;
|
||||
}
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_DW TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
if ($3->primary == K_YES) {
|
||||
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->prog_modes &= ~PM_debugWIRE;
|
||||
}
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_PDI TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
if ($3->primary == K_YES) {
|
||||
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->prog_modes &= ~PM_PDI;
|
||||
}
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_UPDI TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
if ($3->primary == K_YES) {
|
||||
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->prog_modes &= ~PM_UPDI;
|
||||
}
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_HAS_TPI TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
if ($3->primary == K_YES) {
|
||||
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->prog_modes &= ~PM_TPI;
|
||||
}
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
|
@ -1135,11 +1187,13 @@ part_parm :
|
|||
|
||||
K_IS_AVR32 TKN_EQUAL yesno
|
||||
{
|
||||
if ($3->primary == K_YES)
|
||||
if ($3->primary == K_YES) {
|
||||
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->prog_modes &= ~PM_aWire;
|
||||
}
|
||||
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
|
||||
{ /* select memory for extension or create if not there */
|
||||
AVRMEM *mem = avr_locate_mem_noalias(current_part, $2->value.string);
|
||||
|
@ -1273,6 +1319,7 @@ part_parm :
|
|||
}
|
||||
avr_add_mem_order($2->value.string);
|
||||
current_mem = mem;
|
||||
current_strct = COMP_AVRMEM;
|
||||
free_token($2);
|
||||
}
|
||||
mem_specs
|
||||
|
@ -1295,6 +1342,7 @@ part_parm :
|
|||
}
|
||||
cfg_pop_comms();
|
||||
current_mem = NULL;
|
||||
current_strct = COMP_AVRPART;
|
||||
} |
|
||||
K_MEMORY TKN_STRING TKN_EQUAL K_NULL
|
||||
{
|
||||
|
@ -1306,6 +1354,7 @@ part_parm :
|
|||
free_token($2);
|
||||
cfg_pop_comms();
|
||||
current_mem = NULL;
|
||||
current_strct = COMP_AVRPART;
|
||||
} |
|
||||
opcode TKN_EQUAL string_list {
|
||||
{
|
||||
|
@ -1355,6 +1404,11 @@ mem_specs :
|
|||
|
||||
|
||||
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
|
||||
{
|
||||
current_mem->paged = $3->primary == K_YES ? 1 : 0;
|
||||
|
|
|
@ -63,7 +63,7 @@ static struct {
|
|||
const char *mcu, *var, *value;
|
||||
} ptinj[] = {
|
||||
// Add triples here, eg, {"ATmega328P", "mcuid", "999"},
|
||||
{NULL, NULL, NULL},
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
static struct {
|
||||
|
@ -134,7 +134,7 @@ static void printallopcodes(const AVRPART *p, const char *d, OPCODE * const *opa
|
|||
|
||||
|
||||
// Programming modes
|
||||
static char *prog_modes(const AVRPART *p) {
|
||||
static char *prog_modes_str_flags(const AVRPART *p) {
|
||||
static char type[1024];
|
||||
|
||||
*type = 0;
|
||||
|
@ -194,6 +194,34 @@ static char *prog_modes(const AVRPART *p) {
|
|||
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
|
||||
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, cfg_escape(p->id), 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, "0x%02x", stk500_devcode);
|
||||
_if_partout(intcmp, "0x%02x", avr910_devcode);
|
||||
|
@ -1032,7 +1064,7 @@ void dev_output_part_defs(char *partdesc) {
|
|||
nfuses,
|
||||
ok,
|
||||
p->flags,
|
||||
prog_modes(p),
|
||||
prog_modes_str_flags(p),
|
||||
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(!base || base->initpgm != 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)
|
||||
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));
|
||||
_if_pgmout(intcmp, "%d", baudrate);
|
||||
|
|
|
@ -1694,34 +1694,53 @@ The format of the programmer definition is as follows:
|
|||
|
||||
@smallexample
|
||||
programmer
|
||||
parent <id> # <id> is a quoted string
|
||||
parent <id> # optional parent
|
||||
id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
|
||||
desc = <description> ; # quoted string
|
||||
type = "par" | "stk500" | ... ; # programmer type (see below for a list)
|
||||
baudrate = <num> ; # baudrate for serial ports
|
||||
vcc = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
buff = <num1> [, <num2> ... ] ; # pin number(s)
|
||||
reset = <num> ; # pin number
|
||||
sck = <num> ; # pin number
|
||||
mosi = <num> ; # pin number
|
||||
miso = <num> ; # pin number
|
||||
errled = <num> ; # pin number
|
||||
rdyled = <num> ; # pin number
|
||||
pgmled = <num> ; # pin number
|
||||
vfyled = <num> ; # pin number
|
||||
usbvid = <hexnum>; # USB VID (Vendor ID)
|
||||
usbpid = <hexnum> [, <hexnum> ...]; # USB PID (Product ID)
|
||||
usbdev = <interface>; # USB interface or other device info
|
||||
usbvendor = <vendorname>; # USB Vendor Name
|
||||
usbproduct = <productname>; # USB Product Name
|
||||
usbsn = <serialno>; # USB Serial Number
|
||||
;
|
||||
type = <type>; # programmer type, quoted string
|
||||
# supported types can be listed by "-c ?type"
|
||||
prog_modes = PM_<i/f> @{ | PM_<i/f> @} # interfaces, eg, PM_SPM|PM_PDI
|
||||
connection_type = parallel | serial | usb | spi
|
||||
baudrate = <num> ; # baudrate for avr910-programmer
|
||||
vcc = <pin1> [, <pin2> ... ] ; # pin number(s)
|
||||
buff = <pin1> [, <pin2> ... ] ; # pin number(s)
|
||||
reset = <pin> ; # pin number
|
||||
sck = <pin> ; # pin number
|
||||
mosi = <pin> ; # pin number
|
||||
miso = <pin> ; # pin number
|
||||
errled = <pin> ; # pin number
|
||||
rdyled = <pin> ; # pin number
|
||||
pgmled = <pin> ; # pin number
|
||||
vfyled = <pin> ; # pin number
|
||||
usbvid = <hexnum> ; # USB VID (Vendor ID)
|
||||
usbpid = <hexnum> [, <hexnum> ...] ; # USB PID (Product ID)
|
||||
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
|
||||
|
||||
@noindent
|
||||
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.
|
||||
|
||||
@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
|
||||
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.
|
||||
|
||||
@noindent
|
||||
Following programmer types are currently implemented:
|
||||
The following programmer types are currently implemented:
|
||||
|
||||
@multitable @columnfractions .25 .6
|
||||
@include programmer_types.texi
|
||||
|
@ -1743,29 +1762,35 @@ Following programmer types are currently implemented:
|
|||
|
||||
@smallexample
|
||||
part
|
||||
id = <id> ; # 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_debugwire = <yes/no> ; # part has debugWire i/f
|
||||
has_pdi = <yes/no> ; # part has PDI i/f
|
||||
has_updi = <yes/no> ; # part has UPDI i/f
|
||||
has_tpi = <yes/no> ; # part has TPI i/f
|
||||
devicecode = <num> ; # numeric
|
||||
stk500_devcode = <num> ; # numeric
|
||||
avr910_devcode = <num> ; # numeric
|
||||
is_avr32 = <yes/no> ; # AVR32 part
|
||||
is_at90s1200 = <yes/no> ; # AT90S1200 part
|
||||
signature = <num> <num> <num> ; # signature bytes
|
||||
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
|
||||
reset = dedicated | io ;
|
||||
retry_pulse = reset | sck ;
|
||||
chip_erase_delay = <num> ; # chip erase delay (us)
|
||||
# STK500 parameters (parallel programming IO lines)
|
||||
pagel = <num> ; # pin name in hex, i.e., 0xD7
|
||||
bs2 = <num> ; # pin name in hex, i.e., 0xA0
|
||||
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
|
||||
timeout = <num> ;
|
||||
stabdelay = <num> ;
|
||||
|
@ -1777,52 +1802,59 @@ part
|
|||
predelay = <num> ;
|
||||
postdelay = <num> ;
|
||||
pollmethod = <num> ;
|
||||
mode = <num> ;
|
||||
delay = <num> ;
|
||||
blocksize = <num> ;
|
||||
readsize = <num> ;
|
||||
hvspcmdexedelay = <num> ;
|
||||
# STK500v2 HV programming parameters, from XML
|
||||
pp_controlstack = <num>, <num>, ...; # PP only
|
||||
hvsp_controlstack = <num>, <num>, ...; # HVSP only
|
||||
hventerstabdelay = <num>;
|
||||
progmodedelay = <num>; # PP only
|
||||
latchcycles = <num>;
|
||||
togglevtg = <num>;
|
||||
poweroffdelay = <num>;
|
||||
resetdelayms = <num>;
|
||||
resetdelayus = <num>;
|
||||
hvleavestabdelay = <num>;
|
||||
resetdelay = <num>;
|
||||
synchcycles = <num>; # HVSP only
|
||||
chiperasepulsewidth = <num>; # PP only
|
||||
chiperasepolltimeout = <num>;
|
||||
chiperasetime = <num>; # HVSP only
|
||||
programfusepulsewidth = <num>; # PP only
|
||||
programfusepolltimeout = <num>;
|
||||
programlockpulsewidth = <num>; # PP only
|
||||
programlockpolltimeout = <num>;
|
||||
pp_controlstack = <num>, <num>, ... ; # PP only
|
||||
hvsp_controlstack = <num>, <num>, ... ; # HVSP only
|
||||
flash_instr = <num>, <num>, <num> ;
|
||||
eeprom_instr = <num>, <num>, ... ;
|
||||
hventerstabdelay = <num> ;
|
||||
progmodedelay = <num> ; # PP only
|
||||
latchcycles = <num> ;
|
||||
togglevtg = <num> ;
|
||||
poweroffdelay = <num> ;
|
||||
resetdelayms = <num> ;
|
||||
resetdelayus = <num> ;
|
||||
hvleavestabdelay = <num> ;
|
||||
resetdelay = <num> ;
|
||||
synchcycles = <num> ; # HVSP only
|
||||
chiperasepulsewidth = <num> ; # PP only
|
||||
chiperasepolltimeout = <num> ;
|
||||
chiperasetime = <num> ; # HVSP only
|
||||
programfusepulsewidth = <num> ; # PP only
|
||||
programfusepolltimeout = <num> ;
|
||||
programlockpulsewidth = <num> ; # PP only
|
||||
programlockpolltimeout = <num> ;
|
||||
# JTAG ICE mkII parameters, also from XML files
|
||||
allowfullpagebitstream = <yes/no> ;
|
||||
enablepageprogramming = <yes/no> ;
|
||||
idr = <num> ; # IO addr of IDR (OCD) reg.
|
||||
rampz = <num> ; # IO addr of RAMPZ reg.
|
||||
spmcr = <num> ; # mem addr of SPMC[S]R reg.
|
||||
eecr = <num> ; # mem addr of EECR reg.
|
||||
# (only when != 0x3F)
|
||||
is_at90s1200 = <yes/no> ; # AT90S1200 part
|
||||
is_avr32 = <yes/no> ; # AVR32 part
|
||||
idr = <num> ; # IO addr of IDR (OCD) reg
|
||||
rampz = <num> ; # IO addr of RAMPZ reg
|
||||
spmcr = <num> ; # mem addr of SPMC[S]R reg
|
||||
eecr = <num> ; # mem addr of EECR reg only when != 0x3f
|
||||
mcu_base = <num> ;
|
||||
nvm_base = <num> ;
|
||||
ocd_base = <num> ;
|
||||
ocdrev = <num> ;
|
||||
pgm_enable = <instruction format> ;
|
||||
chip_erase = <instruction format> ;
|
||||
|
||||
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
|
||||
page_size = <num> ; # bytes
|
||||
num_pages = <num> ; # numeric
|
||||
min_write_delay = <num> ; # micro-seconds
|
||||
max_write_delay = <num> ; # micro-seconds
|
||||
readback_p1 = <num> ; # byte value
|
||||
readback_p2 = <num> ; # byte value
|
||||
pwroff_after_write = <yes/no> ; # yes / no
|
||||
readback = <num> <num> ; # pair of byte values
|
||||
readback_p1 = <num> ; # byte value (first component)
|
||||
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> ;
|
||||
write = <instruction format> ;
|
||||
read_lo = <instruction format> ;
|
||||
|
@ -1832,8 +1864,8 @@ part
|
|||
loadpage_lo = <instruction format> ;
|
||||
loadpage_hi = <instruction format> ;
|
||||
writepage = <instruction format> ;
|
||||
;
|
||||
;
|
||||
;
|
||||
;
|
||||
@end smallexample
|
||||
|
||||
@menu
|
||||
|
@ -1914,7 +1946,22 @@ write = "1 1 0 0 0 0 0 0 x x x x x x x x",
|
|||
|
||||
@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 Node
|
||||
|
|
39
src/lexer.l
39
src/lexer.l
|
@ -63,9 +63,9 @@ SIGN [+-]
|
|||
|
||||
%%
|
||||
|
||||
{SIGN}?{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; }
|
||||
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
||||
{SIGN}?"."{DIGIT}+ { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
||||
{SIGN}?{DIGIT}+ { yylval = new_number(yytext); return TKN_NUMBER; }
|
||||
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
|
||||
{SIGN}?"."{DIGIT}+ { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
|
||||
|
||||
["]([^"\\\n]|\\.|\\\n)*["] {
|
||||
char *str= cfg_strdup("lexer.l", yytext);
|
||||
|
@ -73,12 +73,12 @@ SIGN [+-]
|
|||
size_t len = strlen(str);
|
||||
if(len)
|
||||
str[len-1] = 0;
|
||||
yylval = string(str);
|
||||
yylval = new_string(str);
|
||||
free(str);
|
||||
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 */
|
||||
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; }
|
||||
allowfullpagebitstream { yylval=NULL; ccap(); return K_ALLOWFULLPAGEBITSTREAM; }
|
||||
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_EQUAL; }
|
||||
";" { 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_RIGHT_PAREN; }
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ enum ctl_stack_t {
|
|||
CTL_STACK_HVSP /* high voltage serial programming control stack */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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_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_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */
|
||||
#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 */
|
||||
|
||||
/* 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 {
|
||||
const char * desc; /* long part name */
|
||||
const char * id; /* short part name */
|
||||
LISTID comments; // Used by developer options -p*/[ASsr...]
|
||||
const char * parent_id; /* Used by developer options */
|
||||
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 stk500_devcode; /* stk500 device code */
|
||||
int avr910_devcode; /* avr910 device code */
|
||||
|
@ -262,7 +286,7 @@ typedef struct avrpart {
|
|||
int programlockpulsewidth; /* stk500 v2 hv mode parameter */
|
||||
int programlockpolltimeout; /* 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 rampz; /* JTAG ICE mkII XML file parameter */
|
||||
|
@ -677,13 +701,21 @@ typedef enum {
|
|||
CONNTYPE_SPI
|
||||
} 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 {
|
||||
LISTID id;
|
||||
const char *desc;
|
||||
void (*initpgm)(struct programmer_t *pgm); // Sets up the AVRDUDE programmer
|
||||
LISTID comments; // Used by developer options -c*/[ASsr...]
|
||||
const char *parent_id; // Used by developer options
|
||||
int prog_modes; // Programming interfaces, see #define PM_...
|
||||
struct pindef_t pin[N_PINS];
|
||||
conntype_t conntype;
|
||||
int baudrate;
|
||||
|
@ -695,7 +727,7 @@ typedef struct programmer_t {
|
|||
const char *usbproduct;
|
||||
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;
|
||||
char type[PGM_TYPELEN];
|
||||
char port[PGM_PORTLEN];
|
||||
|
|
Loading…
Reference in New Issue