From 91ffab5fc6f22087e29e30d2a2ec64beaccb3858 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 29 Aug 2023 00:07:57 +0100 Subject: [PATCH] Provide serialadapter entity in avrdude.conf --- src/CMakeLists.txt | 2 ++ src/Makefile.am | 1 + src/avrdude.conf.in | 39 +++++++++++++++++++++++++++++++++++++-- src/config.c | 2 +- src/config_gram.y | 2 +- src/developer_opts.c | 5 +++-- src/lexer.l | 2 +- src/libavrdude.h | 6 ++++++ src/main.c | 10 ++++++++-- src/pgm.c | 9 +++++++++ 10 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c10a77eb..5577d955 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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} diff --git a/src/Makefile.am b/src/Makefile.am index 9ac585a5..5a994fb4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 3dd99558..eede3e4c 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -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 # optional serialadapter or programmer parent +# id = [, ... ] ; # are quoted strings +# desc = ; # quoted string +# baudrate = ; # optional default baudrate +# usbvid = ; # USB vendor ID +# usbpid = [, ...] ; # list of USB product IDs +# usbsn = ; # USB Serial Number in private .avrduderc files +# ; +# # part # desc = ; # quoted string, the long part name, eg, "ATmega328p" # 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 [:] +# 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 # diff --git a/src/config.c b/src/config.c index 9d2c790e..6a62519e 100644 --- a/src/config.c +++ b/src/config.c @@ -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) diff --git a/src/config_gram.y b/src/config_gram.y index 0b62c216..441fa863 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -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; } diff --git a/src/developer_opts.c b/src/developer_opts.c index ea067111..b390fc87 100644 --- a/src/developer_opts.c +++ b/src/developer_opts.c @@ -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) diff --git a/src/lexer.l b/src/lexer.l index e064e3cd..0bd229c7 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -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; } diff --git a/src/libavrdude.h b/src/libavrdude.h index cabd276c..49fb89af 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -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 diff --git a/src/main.c b/src/main.c index 06e7b034..98586147 100644 --- a/src/main.c +++ b/src/main.c @@ -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); } diff --git a/src/pgm.c b/src/pgm.c index 8e4ab69b..28aa37f2 100644 --- a/src/pgm.c +++ b/src/pgm.c @@ -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); +}