Merge pull request #1497 from stefanrueger/add-serialadapter

Provide serialadapter entity in avrdude.conf
This commit is contained in:
Stefan Rueger
2023-08-31 17:52:55 +01:00
committed by GitHub
12 changed files with 300 additions and 124 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

@@ -4,11 +4,11 @@
#
# This file contains configuration data used by AVRDUDE which describes
# the programming hardware pinouts and also provides part definitions.
# AVRDUDE's "-C" command line option specifies the location of the
# configuration file. The "-c" option names the programmer configuration
# which must match one of the entry's "id" parameter. The "-p" option
# AVRDUDE's -C command line option specifies the location of the
# configuration file. The -c option names the programmer configuration
# which must match one of the entry's id parameter. The -p option
# identifies which part AVRDUDE is going to be programming and must match
# one of the parts' "id" parameter.
# one of the parts' id parameters.
#
# DO NOT MODIFY THIS FILE. Modifications will be overwritten the next
# time a "make install" is run. For user-specific additions, use the
@@ -21,12 +21,13 @@
# id = <id1> [, <id2> ... ] ; # <idN> are quoted strings
# desc = <description> ; # quoted string
# type = <type>; # programmer type, quoted string
# # supported types can be listed by "-c ?type"
# # list known types with -c ?type
# prog_modes = PM_<i/f> {| PM_<i/f>} # interfaces, eg, PM_SPM|PM_PDI (1)
# extra_features = HAS_<fea> {| HAS_<fea>} # extra features, eg, HAS_SUFFER|HAS_VTARG_ADJ (2)
# is_serialadapter = <yes|no> # programmer is also a serialadapter
# extra_features = HAS_<fea> {| HAS_<fea>} # extra features, eg, HAS_SUFFER (2)
# connection_type = parallel | serial | usb | spi
# baudrate = <num> ; # baudrate for avr910-programmer
# vcc = <pin1> [, <pin2> ... ] ; # pin number(s)
# vcc = <pin1> [, <pin2> ... ] ; # pin number(s) (3)
# buff = <pin1> [, <pin2> ... ] ; # pin number(s)
# reset = <pin> ; # pin number
# sck = <pin> ; # pin number
@@ -40,8 +41,8 @@
# 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) (3)
# usbvid = <hexnum> ; # USB vendor ID
# usbpid = <hexnum> [, <hexnum> ...] ; # USB product ID (4)
# usbdev = <interface> ; # USB interface or other device info
# usbvendor = <vendorname> ; # USB Vendor Name
# usbproduct = <productname> ; # USB Product Name
@@ -49,8 +50,7 @@
# hvupdi_support = <num> [, <num>, ... ] ; # UPDI HV Variants Support
# ;
#
# # To invert a pin use = ~ <num>
# # To invert a pin list (all pins get inverted) use ~ ( <num1> [, <num2> ... ] )
# # Notes
# #
# # (1) The following program modes are known:
# # - PM_SPM: Bootloaders, self-programming with SPM opcodes or NVM Controllers
@@ -81,7 +81,20 @@
# # - HAS_VAREF_ADJ: Programmer has an adjustable analog reference voltage that
# # can be controlled with Avrdude
# #
# # (3) Not all programmer types can process a list of PIDs
# # (3) To invert the polarity of a pin use a tilde: ~<num>
# # To invert the polarity of all pins in a list use ~(<num1> [, <num2> ... ])
# #
# # (4) 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, eg, in .avrduderc
# usbvid = <hexnum> ; # USB vendor ID
# usbpid = <hexnum> [, <hexnum> ...] ; # list of USB product IDs
# usbsn = <serialno> ; # USB Serial Number in per-user .avrduderc
# ;
#
# part
# desc = <description> ; # quoted string, the long part name, eg, "ATmega328p"
@@ -924,7 +937,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 = "...";
# per-user ~/.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,
@@ -935,7 +948,7 @@ programmer
# See also https://ftdichip.com/wp-content/uploads/2020/07/DS_FT2232H.pdf
programmer
id = "ft2232h", "avrftdi", "2232h";
id = "avrftdi", "2232h";
desc = "FT2232H/D based generic programmer";
type = "avrftdi";
prog_modes = PM_TPI | PM_ISP;
@@ -950,6 +963,15 @@ programmer
sdi = 2; # AD2 (TDO)
;
#------------------------------------------------------------
# ft2232h
#------------------------------------------------------------
programmer parent "2232h"
id = "ft2232h";
is_serialadapter = yes;
;
#------------------------------------------------------------
# 2232HIO
#------------------------------------------------------------
@@ -957,7 +979,7 @@ programmer
# This is an implementation of the above with a buffer IC (74AC244) and
# 4 LEDs directly attached, all active low.
programmer parent "ft2232h"
programmer parent "2232h"
id = "2232hio";
desc = "2232hio based on FT2232H with buffer and LEDs";
buff = ~4;
@@ -975,7 +997,7 @@ programmer parent "ft2232h"
# Tigard - FT2232H based multi-protocol tool for hardware hacking
# https://github.com/tigard-tools/tigard
programmer parent "ft2232h"
programmer parent "2232h"
id = "tigard";
desc = "Tigard interface board";
usbdev = "B";
@@ -991,7 +1013,7 @@ programmer parent "ft2232h"
# Adds a buffer and a LED indicating that the programming is in progress.
# https://www.kanda.com/products/Kanda/AVRISP-U.html
programmer parent "ft2232h"
programmer parent "2232h"
id = "avrisp-u";
desc = "Kanda AVRISP-U";
usbsn = "AVR";
@@ -1028,7 +1050,17 @@ programmer
# device ID of 0x6011
programmer parent "ft2232h"
id = "ft4232h", "4232h";
id = "ft4232h";
desc = "FT4232H based generic programmer";
usbpid = 0x6011;
;
#------------------------------------------------------------
# 4232h
#------------------------------------------------------------
programmer parent "2232h"
id = "4232h";
desc = "FT4232H based generic programmer";
usbpid = 0x6011;
;
@@ -1067,6 +1099,7 @@ programmer
desc = "FT232H based generic programmer";
type = "avrftdi";
prog_modes = PM_TPI | PM_ISP;
is_serialadapter = yes;
connection_type = usb;
usbvid = 0x0403;
usbpid = 0x6014;
@@ -1113,6 +1146,7 @@ programmer
programmer parent "ft232h"
id = "um232h";
desc = "UM232H module from FTDI";
is_serialadapter = no;
;
#------------------------------------------------------------
@@ -1127,7 +1161,7 @@ programmer parent "ft232h"
# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get
# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant.
programmer parent "ft232h"
programmer parent "um232h"
id = "c232hm";
desc = "C232HM cable from FTDI";
;
@@ -1205,7 +1239,7 @@ programmer
# First SPI connector
# User manual: https://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User%27s_Manual
programmer parent "ft2232h"
programmer parent "2232h"
id = "tumpa";
desc = "TIAO USB Multi-Protocol Adapter";
usbpid = 0x8a98;
@@ -1582,7 +1616,10 @@ programmer
desc = "FT232R based generic programmer";
type = "ftdi_syncbb";
prog_modes = PM_TPI | PM_ISP;
is_serialadapter = yes;
connection_type = usb;
usbvid = 0x0403; # For use as serial adapter
usbpid = 0x6001; # "
reset = 4; # DTR
sck = 0; # TxD
sdo = 2; # RTS
@@ -1740,7 +1777,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
@@ -1949,6 +1985,7 @@ programmer
desc = "ch341a programmer (AVR must have minimum F_CPU of 6.8 MHz)";
type = "ch341a";
prog_modes = PM_ISP;
is_serialadapter = yes;
connection_type = usb;
usbvid = 0x1a86;
usbpid = 0x5512;
@@ -2896,6 +2933,40 @@ programmer
hvupdi_support = 1;
;
#
# SERIAL ADAPTER DEFINITIONS
#
# A serialadapter is a programmer that has only USB parameters defined; it
# can be used for a -P <serialadapter>[:<serial number>] port
# specification instead of the created serial port. Per-user serialadapter
# definitions in ~/.avrduderc or avrdude.rc files can add a serial number
# to assign a particular board a specific id and default upload baud rate:
#
# serialadapter parent "ft232r"
# id = "bike-shed-door";
# usbsn = "0123456789";
# baudrate = 250000;
# ;
#
# This is particularly useful for uploading to a bootloader as it allows
# specifying the port as -P bike-shed-door rather than having to figure
# out which serial port name the operating system has assigned to the
# plugged in bike-shed-door board at runtime. Note that each programmer
# that defines usbpid and sets is_serialadapter = yes can also be utilised
# as a serialadapter.
#------------------------------------------------------------
# ch340
#------------------------------------------------------------
serialadapter
id = "ch340";
desc = "WCH CH340 USB to serial adapter";
usbvid = 0x1a86;
usbpid = 0x7523;
;
#
# PART DEFINITIONS
#

View File

@@ -68,6 +68,7 @@ Component_t avr_comp[] = {
// PROGRAMMER
pgm_comp_desc(desc, COMP_STRING),
pgm_comp_desc(prog_modes, COMP_INT),
pgm_comp_desc(is_serialadapter, COMP_INT),
pgm_comp_desc(extra_features, COMP_INT),
pgm_comp_desc(baudrate, COMP_INT),
pgm_comp_desc(usbvid, COMP_INT),
@@ -570,7 +571,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

@@ -140,76 +140,6 @@ static void printallopcodes(const AVRPART *p, const char *d, OPCODE * const *opa
// Programming modes
/*
* p->flags no longer used for programming modes, use p->prog_modes
*
remove this comment in 2023
static char *prog_modes_str_flags(const AVRPART *p) {
static char type[1024];
*type = 0;
if(!(p->flags & AVRPART_HAS_TPI) // TPI devices don't have the SPM opcode
&& !str_eq(p->id, "t4") // Nor have these early ones
&& !str_eq(p->id, "t5")
&& !str_eq(p->id, "t9")
&& !str_eq(p->id, "t10")
&& !str_eq(p->id, "t11")
&& !str_eq(p->id, "t12")
&& !str_eq(p->id, "t15")
&& !str_eq(p->id, "t20")
&& !str_eq(p->id, "t26")
&& !str_eq(p->id, "t28")
&& !str_eq(p->id, "t40"))
strcpy(type, "PM_SPM");
switch(p->flags & (AVRPART_HAS_PDI | AVRPART_AVR32 | AVRPART_HAS_TPI | AVRPART_HAS_UPDI)) {
case AVRPART_HAS_TPI: // AVR8L family
strcat(type, "|PM_TPI");
break;
case 0: // AVR8 family, "classic" parts
if(p->flags & AVRPART_SERIALOK) // ATmega406 has no ISP
strcat(type, "|PM_ISP");
break;
case AVRPART_HAS_PDI: // AVR8_XMEGA family
strcat(type, "|PM_PDI");
break;
case AVRPART_HAS_UPDI: // AVR8X family
strcat(type, "|PM_UPDI");
break;
case AVRPART_AVR32: // AVR32 family
strcat(type, "|PM_aWire");
break;
default:
strcat(type, "|PM_UNKNOWN");
}
switch(p->ctl_stack_type) {
case CTL_STACK_PP:
strcat(type, "|PM_HVPP");
break;
case CTL_STACK_HVSP:
strcat(type, "|PM_HVSP");
break;
default:
break;
}
if(p->flags & AVRPART_HAS_DW)
strcat(type, "|PM_debugWIRE");
if(p->flags & AVRPART_HAS_JTAG)
strcat(type, "|PM_JTAG");
return type + (*type == '|');
}
*
*/
static char *prog_modes_str(int pm) {
static char type[1024];
@@ -450,6 +380,10 @@ static int intcmp(int a, int b) {
return a-b;
}
static int boolcmp(int a, int b) {
return !!a-!!b;
}
// Deep copies for comparison and raw output
@@ -1359,10 +1293,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)
@@ -1390,6 +1325,7 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
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_pgmout_str(boolcmp, cfg_strdup("dev_pgm_strct()", pgm->is_serialadapter? "yes": "no"), is_serialadapter);
_if_pgmout_str(intcmp, cfg_strdup("dev_pgm_strct()", extra_features_str(pgm->extra_features)), extra_features);
if(!base || base->conntype != pgm->conntype)
_pgmout_fmt("connection_type", "%s", connstr(pgm->conntype));

View File

@@ -2736,6 +2736,7 @@ the executable.
@menu
* AVRDUDE Defaults::
* Programmer Definitions::
* Serial Adapter Definitions::
* Part Definitions::
* Other Notes::
@end menu
@@ -2775,7 +2776,7 @@ Whether or not AVRDUDE's interactive terminal is allowed to use subshell
rare case @code{avrdude -t} is set up with attached hardware to provide a
web service, remote ssh or a login on a PC instead of a shell, say, for
demo or training purposes. In almost all other cases this can be
overridden in the personal @code{avrddude.rc} or @code{.avrduderc}
overridden in the per-user @code{avrddude.rc} or @code{.avrduderc}
configuration file with @var{yes}.
@end table
@@ -2784,7 +2785,8 @@ configuration file with @var{yes}.
@c
@c Node
@c
@node Programmer Definitions, Part Definitions, AVRDUDE Defaults, Configuration File
@node Programmer Definitions, Serial Adapter Definitions, AVRDUDE Defaults, Configuration File
@cindex @code{programmer}
@section Programmer Definitions
@noindent
@@ -2796,22 +2798,27 @@ programmer
id = <id1> [, <id2> ... ] ; # <idN> are quoted strings
desc = <description> ; # quoted string
type = <type>; # programmer type, quoted string
# supported types can be listed by "-c ?type"
prog_modes = PM_<i/f> @{ | PM_<i/f> @} # interfaces, e.g., PM_SPM|PM_PDI
# list known types with -c ?type
prog_modes = PM_<i/f> @{| PM_<i/f>@} # interfaces, e.g., PM_SPM|PM_PDI (1)
extra_features = HAS_<fea> @{| HAS_<fea>@} # extra features, e.g., HAS_SUFFER (2)
connection_type = parallel | serial | usb | spi
baudrate = <num> ; # baudrate for avr910-programmer
vcc = <pin1> [, <pin2> ... ] ; # pin number(s)
vcc = <pin1> [, <pin2> ... ] ; # pin number(s) (3)
buff = <pin1> [, <pin2> ... ] ; # pin number(s)
reset = <pin> ; # pin number
sck = <pin> ; # pin number
sdo = <pin> ; # pin number
sdi = <pin> ; # pin number
tck = <pin> ; # pin number
tdi = <pin> ; # pin number
tdo = <pin> ; # pin number
tms = <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)
usbvid = <hexnum> ; # USB vendor ID
usbpid = <hexnum> [, <hexnum> ...] ; # USB product ID (4)
usbdev = <interface> ; # USB interface or other device info
usbvendor = <vendorname> ; # USB Vendor Name
usbproduct = <productname> ; # USB Product Name
@@ -2825,7 +2832,12 @@ If a parent is specified, all settings of it (except its ids) are used for the n
programmer. These values can be changed by new setting them for the new programmer.
@noindent
Known programming modes are
@strong{Notes}
@enumerate
@item 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)
@@ -2842,12 +2854,29 @@ Known programming modes are
@item @code{PM_aWire}: AVR32 parts
@end itemize
@noindent
To invert a bit in the pin definitions, use @code{= ~ <num>}. To invert a pin list
(all pins get inverted) use @code{~ ( <num1> [, <num2> ... ] )}.
@item The following extra programmer features are known
@noindent
Not all programmer types can handle a list of USB PIDs.
@itemize @bullet
@item @code{HAS_SUFFER}: Only present on Xplained Mini/Nano programmers;
the Super User Fantastic Feature Enable Register allows the user to modify
the behavior of the mEDBG programmer/debugger chip, see the Xplained Mini/Nano
documentation for more information
@item @code{HAS_VTARG_SWITCH}: Programer has a programmable target power switch
@item @code{HAS_VTARG_READ}: Programmer can read the target voltage
@item @code{HAS_VTARG_ADJ}: Programmer has an adjustable target power source that can
be controlled with Avrdude
@item @code{HAS_FOSC_ADJ}: Programmer has a programable frequency generator that
can clock an AVR directly through its XTAL1 pin
@item @code{HAS_VAREF_ADJ}: Programmer has an adjustable analog reference voltage that
can be controlled with Avrdude
@end itemize
@item To invert the polarity of a pin, use a tilde @code{~<num>}; to invert
the polarity of all pins in a list use @code{~(<num1> [, <num2> ... ])}
@item Not all programmer types can handle a list of USB PIDs
@end enumerate
@noindent
The following programmer types are currently implemented:
@@ -2859,7 +2888,53 @@ The following programmer types are currently implemented:
@c
@c Node
@c
@node Part Definitions, Other Notes, Programmer Definitions, Configuration File
@node Serial Adapter Definitions, Part Definitions, Programmer Definitions, Configuration File
@cindex @code{serialadapter}
@section Serial Adapter Definitions
@noindent
The format of a serial adapter definition is as follows:
@smallexample
serialadapter
parent <id> # optional serialadapter or programmer parent
id = <id1> [, <id2> ... ] ; # <idN> are quoted strings
desc = <description> ; # quoted string
baudrate = <num> ; # optional default baudrate, eg, in .avrduderc
usbvid = <hexnum> ; # USB vendor ID
usbpid = <hexnum> [, <hexnum> ...] ; # list of USB product IDs
usbsn = <serialno> ; # USB Serial Number in per-user .avrduderc
;
@end smallexample
Technically, a @code{serialadapter} is implemented as @code{programmer}
that has only USB parameters defined. It can be used for a @code{-P
<serialadapter>[:<serial number>]} port specification instead of the
created serial port. Per-user serialadapter definitions in
@code{~/.avrduderc} or @code{avrdude.rc} files can add a serial number to
assign a particular board a specific id and default upload baud rate:
@smallexample
serialadapter parent "ft232r"
id = "bike-shed-door";
usbsn = "0123456789";
baudrate = 250000;
;
@end smallexample
@noindent
This is particularly useful for uploading to a bootloader as it allows
specifying the port as @code{-P bike-shed-door} rather than having to
figure out which serial port name the operating system has assigned to the
plugged in bike-shed-door board at runtime. Note that each programmer that
defines @code{usbpid} and sets @code{is_serialadapter = yes} can also be
utilised as a serialadapter.
@c
@c Node
@c
@node Part Definitions, Other Notes, Serial Adapter Definitions, Configuration File
@cindex @code{part}
@section Part Definitions
@smallexample
@@ -3003,7 +3078,7 @@ arithemtic and bitwise operators.
@noindent
Parts can also inherit parameters from previously defined parts using
the following syntax. In this case specified integer and string values
the following syntax. In this case specified integer and string values
override parameter values from the parent part. New memory definitions
are added to the definitions inherited from the parent. If, however, a
new memory definition refers to an existing one of the same name for
@@ -3023,7 +3098,7 @@ Example format for part inheritance:
part parent <id> # String identifying parent
id = <id> ; # Id string for new part
<any set of other parameters from the list above>
;
;
@end smallexample
@c
@@ -3827,17 +3902,10 @@ Problem: I'm not using Linux and my AVR910 programmer is really slow.
Solutions: The reasons for this are the same as above.
If you know how to work around this on your OS, please let us know.
@item
Problem: Updating the flash ROM from terminal mode does not work with the
JTAG ICEs.
Solution: None at this time. Currently, the JTAG ICE code cannot
write to the flash ROM one byte at a time.
@item
Problem: Page-mode programming the EEPROM (using the -U option) does
not erase EEPROM cells before writing, and thus cannot overwrite any
previous value != 0xff.
not erase EEPROM cells before writing, and thus cannot necessarily overwrite
previous values that are different to 0xff.
Solution: None. This is an inherent feature of the way JTAG EEPROM
programming works, and is documented that way in the Atmel AVR

View File

@@ -148,7 +148,7 @@ INF [Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])?
}
(?x: desc | prog_modes | extra_features | baudrate | usbvid | usbdev | usbsn | usbvendor | usbproduct |
(?x: desc | prog_modes | is_serialadapter | extra_features | baudrate | usbvid | usbdev | usbsn | usbvendor | usbproduct |
family_id | mcuid | n_interrupts | n_page_erase | n_boot_sections | boot_section_size |
hvupdi_variant | stk500_devcode | avr910_devcode | chip_erase_delay | pagel | bs2 |
timeout | stabdelay | cmdexedelay | synchloops | bytedelay | pollindex | pollvalue | predelay | postdelay | pollmethod |
@@ -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

@@ -753,6 +753,7 @@ typedef struct programmer_t {
LISTID comments; // Used by developer options -c*/[ASsr...]
const char *parent_id; // Used by developer options
int prog_modes; // Programming interfaces, see #define PM_...
int is_serialadapter; // Programmer is also a serialadapter
int extra_features;
struct pindef_t pin[N_PINS];
conntype_t conntype;
@@ -851,6 +852,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 *fp, 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 && p->id && lsize(p->id) && p->prog_modes && p->initpgm;
}
int is_serialadapter(const SERIALADAPTER *p) {
return p && p->id && lsize(p->id) && p->usbpid && lsize(p->usbpid) && (!p->prog_modes || p->is_serialadapter);
}

75
src/serialadapter.c Normal file
View File

@@ -0,0 +1,75 @@
/*
* AVRDUDE - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2023 Stefan Rueger <stefan.rueger@urclocks.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ac_cfg.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "avrdude.h"
#include "libavrdude.h"
void list_serialadapters(FILE *fp, const char *prefix, LISTID programmers) {
LNODEID ln1, ln2, ln3;
SERIALADAPTER *sea;
int maxlen=0, len;
sort_programmers(programmers);
// Compute max length of serial adapter names
for(ln1 = lfirst(programmers); ln1; ln1 = lnext(ln1)) {
sea = ldata(ln1);
if(!is_serialadapter(sea))
continue;
for(ln2=lfirst(sea->id); ln2; ln2=lnext(ln2)) {
const char *id = ldata(ln2);
if(*id == 0 || *id == '.')
continue;
if((len = strlen(id)) > maxlen)
maxlen = len;
}
}
for(ln1 = lfirst(programmers); ln1; ln1 = lnext(ln1)) {
sea = ldata(ln1);
if(!is_serialadapter(sea))
continue;
for(ln2=lfirst(sea->id); ln2; ln2=lnext(ln2)) {
const char *id = ldata(ln2);
if(*id == 0 || *id == '.')
continue;
fprintf(fp, "%s%-*s = [usbvid 0x%04x, usbpid", prefix, maxlen, id, sea->usbvid);
for(ln3=lfirst(sea->usbpid); ln3; ln3=lnext(ln3))
fprintf(fp, " 0x%04x", *(int *) ldata(ln3));
if(sea->usbsn && *sea->usbsn)
fprintf(fp, ", usbsn %s", sea->usbsn);
fprintf(fp, "]\n");
}
}
}
void serialadapter_not_found(const char *sea_id) {
msg_error("\v");
if(sea_id && *sea_id)
pmsg_error("cannot find serial adapter id %s\n", sea_id);
msg_error("\nValid serial adapters are:\n");
list_serialadapters(stderr, " ", programmers);
msg_error("\n");
}