Provide serialadapter entity in avrdude.conf

This commit is contained in:
Stefan Rueger
2023-08-29 00:07:57 +01:00
parent b8c47f3999
commit 91ffab5fc6
10 changed files with 69 additions and 9 deletions

View File

@@ -214,6 +214,7 @@ add_library(libavrdude
ser_avrdoper.c
ser_posix.c
ser_win32.c
serialadapter.c
serialupdi.c
serialupdi.h
solaris_ecpp.h
@@ -286,6 +287,7 @@ target_link_libraries(libavrdude
${LIB_LIBFTDI}
${LIB_LIBFTDI1}
${LIB_LIBREADLINE}
${LIB_LIBSERIALPORT}
${LIB_NCURSES}
${LIB_LIBGPIOD}
${EXTRA_WINDOWS_LIBRARIES}

View File

@@ -163,6 +163,7 @@ libavrdude_a_SOURCES = \
ser_avrdoper.c \
ser_posix.c \
ser_win32.c \
serialadapter.c \
solaris_ecpp.h \
stk500.c \
stk500.h \

View File

@@ -83,6 +83,16 @@
# #
# # (3) Not all programmer types can process a list of PIDs
#
# serialadapter # same as programmer albeit only for usb parameters
# parent <id> # optional serialadapter or programmer parent
# id = <id1> [, <id2> ... ] ; # <idN> are quoted strings
# desc = <description> ; # quoted string
# baudrate = <num> ; # optional default baudrate
# usbvid = <hexnum> ; # USB vendor ID
# usbpid = <hexnum> [, <hexnum> ...] ; # list of USB product IDs
# usbsn = <serialno> ; # USB Serial Number in private .avrduderc files
# ;
#
# part
# desc = <description> ; # quoted string, the long part name, eg, "ATmega328p"
# id = <id> ; # quoted string, normally an abbreviated part name
@@ -924,7 +934,7 @@ programmer
# The drivers will look for a specific device and use the first one
# found. If you have mulitple devices, and they give out serial
# numbers, a different entry for each of them can be created in a
# persnonal ~/.avrduderc or avrdude.rc entry and the usbsn = "...";
# personal ~/.avrduderc or avrdude.rc entry and the usbsn = "...";
# field added to distinguish between them.
#
# Note that the pin numbers for the main ISP signals (reset, sck,
@@ -1583,6 +1593,9 @@ programmer
type = "ftdi_syncbb";
prog_modes = PM_TPI | PM_ISP;
connection_type = usb;
baudrate = 250000; # For use as serial adapter
usbvid = 0x0403; # "
usbpid = 0x6001; # "
reset = 4; # DTR
sck = 0; # TxD
sdo = 2; # RTS
@@ -1740,7 +1753,6 @@ programmer
usbpid = 0x05dc; # Obdev's free shared PID
usbvendor = "www.fischl.de";
usbproduct = "USBasp";
# Old usbasp from fischl.de:
# usbvid = 0x03EB; # ATMEL
# usbpid = 0xC7B4; # (unoffical) USBasp
@@ -2896,6 +2908,29 @@ programmer
hvupdi_support = 1;
;
#------------------------------------------------------------
# ch340
#------------------------------------------------------------
# A serialadapter is a programmer that has only USB parameters defined;
# they can be used for a -P <serialadapter|programmer>[:<serial number>]
# port specification instead of the serial port that the serial adapter
# creates, eg, instead of /dev/ttyUSB3. Personal serialadapter definitions
# in the ~/.avrduderc or avrdude.rc files can add a serial number using
# the definition usbsn = "012345679"; to give a particular board a
# specific unique name (id). This is particularly useful when uploading
# directly to a board with a bootloader as it allows to assign boards
# unique names rather than having to figure out which a varying serial
# port name the Operating System has assigned at runtime.
serialadapter
id = "ch340";
desc = "WCH CH340 USB to serial adapter";
baudrate = 250000;
usbvid = 0x1a86;
usbpid = 0x7523;
;
#
# PART DEFINITIONS
#

View File

@@ -570,7 +570,7 @@ void capture_lvalue_kw(const char *kw, int lineno) {
}
}
if(str_eq(kw, "programmer") || str_eq(kw, "part") || str_eq(kw, "memory"))
if(str_eq(kw, "programmer") || str_eq(kw, "serialadapter") || str_eq(kw, "part") || str_eq(kw, "memory"))
kw = "*"; // Show comment before programmer/part/memory
if(lkw)

View File

@@ -258,7 +258,7 @@ prog_def :
yyerror("required parameter id not specified");
YYABORT;
}
if (current_prog->initpgm == NULL) {
if (current_prog->initpgm == NULL && current_prog->prog_modes) {
yyerror("programmer type not specified");
YYABORT;
}

View File

@@ -1359,10 +1359,11 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
if(cp)
dev_print_comment(cp->comms);
const char *prog_sea = is_programmer(pgm)? "programmer": is_serialadapter(pgm)? "serialadapter": "programmer";
if(pgm->parent_id && *pgm->parent_id)
dev_info("programmer parent \"%s\"\n", pgm->parent_id);
dev_info("%s parent \"%s\"\n", prog_sea, pgm->parent_id);
else
dev_info("programmer\n");
dev_info("%s\n", prog_sea);
}
if(tsv)

View File

@@ -224,7 +224,7 @@ part { yylval=NULL; ccap(); current_strct = COMP_AVRPART; return K_P
pgm_enable { yylval=new_token(K_PGM_ENABLE); ccap(); return K_PGM_ENABLE; }
pgmled { yylval=NULL; ccap(); return K_PGMLED; }
pp_controlstack { yylval=NULL; ccap(); return K_PP_CONTROLSTACK; }
programmer { yylval=NULL; ccap(); current_strct = COMP_PROGRAMMER; return K_PROGRAMMER; }
(programmer|serialadapter) { yylval=NULL; ccap(); current_strct = COMP_PROGRAMMER; return K_PROGRAMMER; }
rdyled { yylval=NULL; ccap(); return K_RDYLED; }
read { yylval=new_token(K_READ); ccap(); return K_READ; }
read_hi { yylval=new_token(K_READ_HI); ccap(); return K_READ_HI; }

View File

@@ -851,6 +851,12 @@ typedef struct programmer_t {
char flag; // For use by pgm->initpgm()
} PROGRAMMER;
typedef PROGRAMMER SERIALADAPTER; // Only a subset is needed for serial adapters
int is_programmer(const PROGRAMMER *p);
int is_serialadapter(const SERIALADAPTER *p);
void list_serialadapters(FILE *f, const char *prefix, LISTID programmers);
void serialadapter_not_found(const char *sea_id);
#define NO_PIN (PIN_MAX + 1U) // Magic pinno[] value for unused pins
#ifdef __cplusplus

View File

@@ -298,6 +298,8 @@ static void list_programmers(FILE *f, const char *prefix, LISTID programmers, in
// Compute max length of programmer names
for(ln1 = lfirst(programmers); ln1; ln1 = lnext(ln1)) {
pgm = ldata(ln1);
if(!is_programmer(pgm))
continue;
for(ln2=lfirst(pgm->id); ln2; ln2=lnext(ln2))
if(!pm || !pgm->prog_modes || (pm & pgm->prog_modes)) {
const char *id = ldata(ln2);
@@ -310,6 +312,8 @@ static void list_programmers(FILE *f, const char *prefix, LISTID programmers, in
for(ln1 = lfirst(programmers); ln1; ln1 = lnext(ln1)) {
pgm = ldata(ln1);
if(!is_programmer(pgm))
continue;
for(ln2=lfirst(pgm->id); ln2; ln2=lnext(ln2)) {
// List programmer if pm or prog_modes uninitialised or if they are compatible otherwise
if(!pm || !pgm->prog_modes || (pm & pgm->prog_modes)) {
@@ -1018,6 +1022,8 @@ int main(int argc, char * argv [])
AVRPART *p = ldata(ln1);
for(LNODEID ln2 = lfirst(programmers); ln2; ln2 = lnext(ln2)) {
PROGRAMMER *pgm = ldata(ln2);
if(!is_programmer(pgm))
continue;
const char *pnam = pgm->id? ldata(lfirst(pgm->id)): "???";
int pm = pgm->prog_modes & p->prog_modes;
if((pm & (pm-1)) && !str_eq(pnam, "dryrun"))
@@ -1029,7 +1035,7 @@ int main(int argc, char * argv [])
if(str_eq(partdesc, "?")) {
if(pgmid && *pgmid && explicit_c) {
PROGRAMMER *pgm = locate_programmer_set(programmers, pgmid, &pgmid);
if(!pgm) {
if(!pgm || !is_programmer(pgm)) {
programmer_not_found(pgmid);
exit(1);
}
@@ -1078,7 +1084,7 @@ int main(int argc, char * argv [])
}
pgm = locate_programmer_set(programmers, pgmid, &pgmid);
if (pgm == NULL) {
if (pgm == NULL || !is_programmer(pgm)) {
programmer_not_found(pgmid);
exit(1);
}

View File

@@ -364,3 +364,12 @@ void sort_programmers(LISTID programmers)
lsort(programmers,(int (*)(void*, void*)) sort_programmer_compare);
}
// Soft assignment: some struct programmer_t entries can be both programmers and serial adapters
int is_programmer(const PROGRAMMER *p) {
return p->id && lsize(p->id) && p->prog_modes && p->initpgm;
}
int is_serialadapter(const SERIALADAPTER *p) {
return p->id && lsize(p->id) && p->usbpid && lsize(p->usbpid);
}