From 81c2f05fa92a2127ee6fe6775c6be6584c8eb9ed Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 15 Aug 2022 16:18:16 +0200 Subject: [PATCH 1/3] doc: Add high level documentation on flashing This is mostly intended as a place to add available configuration options for each `` in `PROGRAMMER=`. --- doc/doxygen/riot.doxyfile | 1 + doc/doxygen/src/flashing.md | 136 ++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 doc/doxygen/src/flashing.md diff --git a/doc/doxygen/riot.doxyfile b/doc/doxygen/riot.doxyfile index d8d0308aac..cb56850175 100644 --- a/doc/doxygen/riot.doxyfile +++ b/doc/doxygen/riot.doxyfile @@ -764,6 +764,7 @@ INPUT = ../../doc.txt \ src/porting-boards.md \ src/driver-guide.md \ src/getting-started.md \ + src/flashing.md \ src/build-in-docker.md \ ../../tests/README.md \ src/build-system-basics.md \ diff --git a/doc/doxygen/src/flashing.md b/doc/doxygen/src/flashing.md new file mode 100644 index 0000000000..b01d6c6f74 --- /dev/null +++ b/doc/doxygen/src/flashing.md @@ -0,0 +1,136 @@ +Flashing via RIOT's Build System {#flashing} +================================ + +[TOC] + +General Approach {#flashing-general} +================ + +In general, flashing a board from RIOT is as straight forward as typing in a +shell (with the application directory as current working directory): + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +make BOARD= flash +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This will **rebuild** ***AND*** **flash** the application in the current working +directory for board ``, using its default programming tool. If +you want to use an alternative programming tool, say `stm32flash`, use: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +make BOARD= PROGRAMMER=stm32flash flash +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To flash without rebuilding use `flash-only` as target instead of `flash`. + + + + +Compatibility Matrix {#flashing-compatibility} +==================== + +Note that some programmers require additional configuration on a per board +level or rely on features only available on some boards. Hence, a board `FOO` of +MCU family `BAR` may not be supported by programmer `BAZ`, even though `BAZ` is +listed as supported for MCU family `BAR`. + +This table will use the value to pass to `PROGRAMMER=` as title, rather +than the official spelling of the programmer. + +MCU Family | `adafruit-nrfutil` | `avrdude` | `bmp` | `bossa` | `cc2538-bsl`| `cpy2remed` | `dfu-util` | `edbg` | `elf2uf2` | `esptool` | `goodfet` | `jlink` | `lpc2k_pgm` | `mspdebug` | `nrfutil` | `openocd` | `pic32prog` | `pyocd` | `robotis-loader` | `stm32flash` | `stm32loader` | `uf2conv` | `uniflash` +---------------|--------------------|-----------|-------|---------|-------------|-------------|------------|--------|-----------|-----------|-----------|---------|-------------|------------|-----------|-----------|-------------|---------|------------------|--------------|---------------|-----------|----------- +ATmega | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ATXmega | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +CC2538 | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +CC13xx / C26xx | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ (3) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ +EFM32 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ESP8266 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ESP32 (Xtensa) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +ESP32 (RISC-V) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +FE310 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +GD32V | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ (3) | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +Kinetis | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +LPC1768 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +LPC23xx | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +MIPS32r2 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +MSP430 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +nRF51 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ +nRF52 | ✓ (1) | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ (1) | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ +RP2040 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +SAM | ✗ | ✗ | ✗ | ✓ (1) | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +Stellaris | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ +STM32 | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ (1) | ✓ | ✓ | ✗ | ✗ + + +Remarks: + +1. Requires a bootloader to be flashed (rather than a bootloader in ROM) +2. Requires specific hardware, e.g. an embedded programmer +3. Requires a patched version of the programmer tool + +Programmer Configuration {#flashing-configuration} +======================== + +This section will list additional configuration options to control the behavior +of a programming tool, such as selecting the hardware adapter used for +programming. + +OpenOCD Configuration {#flashing-configuration-openocd} +--------------------- + +### `OPENOCD_DEBUG_ADAPTER` + +`OPENOCD_DEBUG_ADAPTER` can be set via command line or as environment variable +to use non-default flashing hardware. + +### `OPENOCD_RESET_USE_CONNECT_ASSERT_SRST` + +`OPENOCD_RESET_USE_CONNECT_ASSERT_SRST` can be set via command line or as +environment variable to `0` to disable resetting the board via the `SRST` line. +This is useful when the `SRST` signal is not connected to the debug adapter or +when using cheap ST-Link V2 clones with broken `SRST` output. Note that it may +not be possible to attach the debugger while the MCU is in deep sleeping mode. +If this is set to `0` by the user, the user may need a carefully timed reset +button press to be able to flash the board. + +### `OPENOCD_PRE_FLASH_CMDS` + +`OPENOCD_PRE_FLASH_CMDS` can be set as environment variable to pass additional +commands to OpenOCD prior to flashing, e.g. to disable flash write protection. + +### `OPENOCD_PRE_VERIFY_CMDS` + +`OPENOCD_PRE_VERIFY_CMDS` can be set as environment variable to pass additional +flags to OpenOCD prior to verifying the flashed firmware. E.g. this is used +in the `pba-d-01-kw2x` to disable the watchdog to prevent it from disrupting +the verification process. + +### `OPENOCD_PRE_FLASH_CHECK_SCRIPT` + +`OPENOCD_PRE_FLASH_CHECK_SCRIPT` can be set via command line or as +environment variable to execute a script before OpenOCD starts flashing. It is +used for Kinetis boards to prevent bricking a board by locking the flash via +magic value in the flash configuration field protection bits. + +The script is expected to exit with code `0` if flashing should resume, or with +exit code `1` if flashing should be aborted. + +### `OPENOCD_CONFIG` + +`OPENOCD_DEBUG_ADAPTER` can be set via command line or as environment variable +to use non-default OpenOCD configuration file. + +### `OPENOCD_TRANSPORT` + +`OPENOCD_TRANSPORT` can be set via command line or as environment variable to +select a non-default transport protocol. E.g. to use JTAG rather than SWD for a +board that defaults to SWD use: + +``` +make PROGRAMMER=openocd OPENOCD_TRANSPORT=jtag +``` + +Note that OpenOCD configuration file of a given board may only support SWD or +JTAG. Also JTAG requires more signal lines to be connected compared to SWD and +some internal programmers only have the SWD signal lines connected, so that +JTAG will not be possible. From 1fd908bd70d044e8520a137734d1942e55f35565 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 15 Aug 2022 16:27:19 +0200 Subject: [PATCH 2/3] doc: Move flashing tips to flashing.md --- .../src/advanced-build-system-tricks.md | 209 ------------------ doc/doxygen/src/flashing.md | 208 +++++++++++++++++ 2 files changed, 208 insertions(+), 209 deletions(-) diff --git a/doc/doxygen/src/advanced-build-system-tricks.md b/doc/doxygen/src/advanced-build-system-tricks.md index 748709af6a..1a8c68a278 100644 --- a/doc/doxygen/src/advanced-build-system-tricks.md +++ b/doc/doxygen/src/advanced-build-system-tricks.md @@ -39,215 +39,6 @@ You can configure your own files that will be parsed by the build system main * Define your custom targets * Override default targets - -Handling multiple boards with udev-rules {#multiple-boards-udev} -======================================== - -When developing and working with multiple boards the default `PORT` configuration -for a particular board might not apply anymore so `PORT` will need to be specified -whenever calling `make term/test`. This can also happen if multiple `DEBUGGERS/PROGRAMMERS` -are present so `DEBUG_ADAPTER_ID` will also need to be passed. Keeping track of -this will become annoying. - -One way of handling this is to use `udev` rules to define `SYMLINKS` between the -boards serial port (`riot/tty-`) and the actual serial port -(dev/ttyACM* or other). With this we can query the rest of the boards serial -`dev` information (`DEBUG_ADAPTER_ID`, `PORT`, etc.) to always flash and open a -terminal on the correct port. - -Procedure: - -- use `udevadm info /dev/ttyACM0` to query the udev database for information on - device on port `/dev/ttyACM0`. - - or use `udevadm info --attribute-walk --name /dev/ttyACM0` for more detailed - output when the first level of information isn't enough - -- create a udev rule with information of the device and one parent to create a - matching rule in `/etc/udev/rules.d/70-riotboards.rules`. - -~~~~~~~~~~~~~~~~~~~ - # samr21-xpro - SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ - ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ - ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro" -~~~~~~~~~~~~~~~~~~~ - -- reload rules: `udevadm control --reload-rules` - -- Boards `PORT` are symlinked to /dev/riot/tty-`board-name`. - -- Create a `makefile.pre` that will query the real `PORT` and the `DEBUG_ADAPTER_ID` - from the `SYMLINK` info - -~~~~~~~~~~~~~~~~~~~ - PORT = /dev/riot/tty-$(BOARD) - DEBUG_ADAPTER_ID = $(\ - shell udevadm info -q property $(PORT) |\ - sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) -~~~~~~~~~~~~~~~~~~~ - -- You can now add `makefile.pre` to `RIOT_MAKEFILES_GLOBAL_PRE` as an environment - variable or on each `make` call: - -~~~~~~~~~~~~~~~~~~~ - $ RIOT_MAKEFILES_GLOBAL_PRE=/path/to/makefile.pre make -C examples/hello-world flash term -~~~~~~~~~~~~~~~~~~~ - -_note_: if set as an environment variable it would be a good idea to add a variable -to enable/disable it, e.g: - -~~~~~~~~~~~~~~~~~~~ -ifeq (1,$(ENABLE_LOCAL_BOARDS)) - PORT = /dev/riot/tty-$(BOARD) - DEBUG_ADAPTER_ID = $(\ - shell udevadm info -q property $(PORT) |\ - sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) -endif -~~~~~~~~~~~~~~~~~~~ - -Handling multiple versions of the same BOARD -------------------------------------------- - -The above procedure works fine when handling different boards, but not -multiple times the same board, e.g: multiple `samr21-xpro`. - -An option for this would be to add an identifier of that board to the mapped -`riot/tty-*`, there are multiple ways of handling this but in the end it means -having a way to identify every copy. - -Another way would be to map the `DEBUG_ADAPTER_ID` in the name: - -~~~~~~~~~~~~~~~~~~~ -SYMLINK+="riot/node-$attr{serial} -~~~~~~~~~~~~~~~~~~~ - -But it will require to know in advance the serial number of each board you want -to use. Another option would be to add some kind of numbering and defining -multiple symlinks for each board. e.g. for `samr21-xpro` number `n`: - -~~~~~~~~~~~~~~~~~~~ - # samr21-xpro - SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ - ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ - ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro", \ - SYMLINK+="riot/tty-samr21-xpro-n" -~~~~~~~~~~~~~~~~~~~ - -Then, when flashing, the number can be specified and the parsing adapted: - -~~~~~~~~~~~~~~~~~~~ - ifneq(,$(BOARD_NUM)) - PORT = /dev/riot/tty-$(BOARD)-$(BOARD_NUM) - else - PORT = /dev/riot/tty-$(BOARD) - endif - DEBUG_ADAPTER_ID = $(\ - shell udevadm info -q property $(PORT) |\ - sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) -~~~~~~~~~~~~~~~~~~~ - -~~~~~~~~~~~~~~~~~~~ - BOARD=samr21-xpro BOARD_NUM=n make flash term -~~~~~~~~~~~~~~~~~~~ - -In the end, this would be the same as using the serial, but a simple number might -be easier to handle. - -Notes ------ -Udev only parses SUBSYSTEM and one parent. For others, we will rely on ENV -variables defined by 60-serial.rules - -So the current filename should be higher than 60-serial.rules - -If for some reason re-writing the serial is needed there is a windows tool: - https://remoteqth.com/wiki/index.php?page=How+to+set+usb+device+SerialNumber - - -Documentation: --------------- -* The whole documentation - http://reactivated.net/writing_udev_rules.html#udevinfo -* Udev manpage - http://manpages.ubuntu.com/manpages/eoan/en/man7/udev.7.html - -Handling multiple boards without udev-rules {#multiple-boards-no-udev} -=========================================== - -This is a simpler approach to the above mentioned issue. The solution here only -uses a makefile script for selecting the debugger and serial port. No -administrative privileges (e.g. to configure Udev) are required. - -One of the limitations of the solution described here is that it currently -doesn't work with multiple boards of the same type. This limitation is a -limitation of the script and not of the mechanism used, it is possible to adapt -the script to support multiple boards of the same type. This modification is -left as an exercise to the reader. - -The following Make snippet is used: - -~~~~~~~~~~~~~~~~~~~ - LOCAL_BOARD_MAP ?= 1 - - # Adapt this list to your board collection - SERIAL_nucleo-f103rb ?= 066BFF343633464257254156 - SERIAL_same54-xpro ?= ATML2748051800005053 - SERIAL_samr21-xpro ?= ATML2127031800008360 - SERIAL_nrf52dk ?= 000682223007 - - ifeq (1,$(LOCAL_BOARD_MAP)) - - # Retrieve the serial of the selected board - BOARD_SERIAL = $(SERIAL_$(BOARD)) - - # Check if there is a serial for the board - ifneq (,$(BOARD_SERIAL)) - - # Set the variables used by various debug tools to the selected serial - SERIAL ?= $(BOARD_SERIAL) - DEBUG_ADAPTER_ID ?= $(BOARD_SERIAL) - JLINK_SERIAL ?= $(BOARD_SERIAL) - - # Use the existing script to grab the matching /dev/ttyACM* device - PORT ?= $(shell $(RIOTTOOLS)/usb-serial/ttys.py --most-recent --format path --serial $(SERIAL)) - endif - endif -~~~~~~~~~~~~~~~~~~~ - -The array of board serial numbers has to be edited to match your local boards. -The serial numbers used here is the USB device serial number as reported by -the debugger hardware. With the `make list-ttys` it is reported as the 'serial': - -~~~~~~~~~~~~~~~~~~~ -$ make list-ttys -path | driver | vendor | model | model_db | serial | ctime --------------|---------|--------------------------|--------------------------------------|-----------------------|--------------------------|--------- -/dev/ttyUSB0 | cp210x | Silicon Labs | CP2102 USB to UART Bridge Controller | CP210x UART Bridge | 0001 | 15:58:13 -/dev/ttyACM1 | cdc_acm | STMicroelectronics | STM32 STLink | ST-LINK/V2.1 | 0671FF535155878281151932 | 15:58:04 -/dev/ttyACM3 | cdc_acm | Arduino (www.arduino.cc) | EOS High Power | Mega ADK R3 (CDC ACM) | 75230313733351110120 | 15:59:57 -/dev/ttyACM2 | cdc_acm | SEGGER | J-Link | J-Link | 000683475134 | 12:41:36 -~~~~~~~~~~~~~~~~~~~ - -When the above make snippet is included as `RIOT_MAKEFILES_GLOBAL_PRE`, the -serial number of the USB device is automatically set if the used board is -included in the script. This will then ensure that the board debugger is used -for flashing and the board serial device is used when starting the serial -console. - -It supports command line parameters to filter by vendor name, model name, serial -number, or driver. In addition, the `--most-recent` argument will only print the -most recently added interface (out of those matching the filtering by vendor, -model, etc.). The `--format path` argument will result in only the device path -being printed for convenient use in scripts. - -Handling multiple boards: Simplest approach {#multiple-boards-simple} -=========================================== - -Passing `MOST_RECENT_PORT=1` as environment variable or as parameter to -make will result in the most recently connected board being preferred over the -default PORT for the selected board. - Analyze dependency resolution {#analyze-depedency-resolution} ============================= diff --git a/doc/doxygen/src/flashing.md b/doc/doxygen/src/flashing.md index b01d6c6f74..927c479375 100644 --- a/doc/doxygen/src/flashing.md +++ b/doc/doxygen/src/flashing.md @@ -134,3 +134,211 @@ Note that OpenOCD configuration file of a given board may only support SWD or JTAG. Also JTAG requires more signal lines to be connected compared to SWD and some internal programmers only have the SWD signal lines connected, so that JTAG will not be possible. + +Handling Multiple Boards With UDEV-Rules {#multiple-boards-udev} +======================================== + +When developing and working with multiple boards the default `PORT` +configuration for a particular board might not apply anymore so `PORT` will need +to be specified whenever calling `make term/test`. This can also happen if +multiple `DEBUGGERS/PROGRAMMERS` are present so `DEBUG_ADAPTER_ID` will also +need to be passed. Keeping track of this will become annoying. + +One way of handling this is to use `udev` rules to define `SYMLINKS` between the +boards serial port (`riot/tty-`) and the actual serial port +(dev/ttyACM* or other). With this we can query the rest of the boards serial +`dev` information (`DEBUG_ADAPTER_ID`, `PORT`, etc.) to always flash and open a +terminal on the correct port. + +Procedure: + +- use `udevadm info /dev/ttyACM0` to query the udev database for information on + device on port `/dev/ttyACM0`. + + or use `udevadm info --attribute-walk --name /dev/ttyACM0` for more detailed + output when the first level of information isn't enough + +- create a udev rule with information of the device and one parent to create a + matching rule in `/etc/udev/rules.d/70-riotboards.rules`. + +~~~~~~~~~~~~~~~~~~~ + # samr21-xpro + SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ + ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ + ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro" +~~~~~~~~~~~~~~~~~~~ + +- reload rules: `udevadm control --reload-rules` + +- Boards `PORT` are symlinked to /dev/riot/tty-`board-name`. + +- Create a `makefile.pre` that will query the real `PORT` and the + `DEBUG_ADAPTER_ID` from the `SYMLINK` info + +~~~~~~~~~~~~~~~~~~~ + PORT = /dev/riot/tty-$(BOARD) + DEBUG_ADAPTER_ID = $(\ + shell udevadm info -q property $(PORT) |\ + sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) +~~~~~~~~~~~~~~~~~~~ + +- You can now add `makefile.pre` to `RIOT_MAKEFILES_GLOBAL_PRE` as an environment + variable or on each `make` call: + +~~~~~~~~~~~~~~~~~~~ + $ RIOT_MAKEFILES_GLOBAL_PRE=/path/to/makefile.pre make -C examples/hello-world flash term +~~~~~~~~~~~~~~~~~~~ + +@note if set as an environment variable it would be a good idea to add a + variable to enable/disable it, e.g: + +~~~~~~~~~~~~~~~~~~~ +ifeq (1,$(ENABLE_LOCAL_BOARDS)) + PORT = /dev/riot/tty-$(BOARD) + DEBUG_ADAPTER_ID = $(\ + shell udevadm info -q property $(PORT) |\ + sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) +endif +~~~~~~~~~~~~~~~~~~~ + +Handling Multiple Versions of the Same BOARD +-------------------------------------------- + +The above procedure works fine when handling different boards, but not +multiple times the same board, e.g: multiple `samr21-xpro`. + +An option for this would be to add an identifier of that board to the mapped +`riot/tty-*`, there are multiple ways of handling this but in the end it means +having a way to identify every copy. + +Another way would be to map the `DEBUG_ADAPTER_ID` in the name: + +~~~~~~~~~~~~~~~~~~~ +SYMLINK+="riot/node-$attr{serial} +~~~~~~~~~~~~~~~~~~~ + +But it will require to know in advance the serial number of each board you want +to use. Another option would be to add some kind of numbering and defining +multiple symlinks for each board. e.g. for `samr21-xpro` number `n`: + +~~~~~~~~~~~~~~~~~~~ + # samr21-xpro + SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", \ + ATTRS{idProduct}=="2111", ATTRS{manufacturer}=="Atmel Corp.", \ + ATTRS{serial}=="ATML2127031800004957", SYMLINK+="riot/tty-samr21-xpro", \ + SYMLINK+="riot/tty-samr21-xpro-n" +~~~~~~~~~~~~~~~~~~~ + +Then, when flashing, the number can be specified and the parsing adapted: + +~~~~~~~~~~~~~~~~~~~ + ifneq(,$(BOARD_NUM)) + PORT = /dev/riot/tty-$(BOARD)-$(BOARD_NUM) + else + PORT = /dev/riot/tty-$(BOARD) + endif + DEBUG_ADAPTER_ID = $(\ + shell udevadm info -q property $(PORT) |\ + sed -n ’/ID_SERIAL_SHORT/ {s/ID_SERIAL_SHORT=//p}’) +~~~~~~~~~~~~~~~~~~~ + +~~~~~~~~~~~~~~~~~~~ + BOARD=samr21-xpro BOARD_NUM=n make flash term +~~~~~~~~~~~~~~~~~~~ + +In the end, this would be the same as using the serial, but a simple number might +be easier to handle. + +Notes +----- +Udev only parses SUBSYSTEM and one parent. For others, we will rely on ENV +variables defined by 60-serial.rules + +So the current filename should be higher than 60-serial.rules + +If for some reason re-writing the serial is needed there is a windows tool: + https://remoteqth.com/wiki/index.php?page=How+to+set+usb+device+SerialNumber + + +Documentation: +-------------- +* The whole documentation + http://reactivated.net/writing_udev_rules.html#udevinfo +* Udev manpage + http://manpages.ubuntu.com/manpages/eoan/en/man7/udev.7.html + +Handling Multiple Boards Without UDEV-Rules {#multiple-boards-no-udev} +=========================================== + +This is a simpler approach to the above mentioned issue. The solution here only +uses a makefile script for selecting the debugger and serial port. No +administrative privileges (e.g. to configure Udev) are required. + +One of the limitations of the solution described here is that it currently +doesn't work with multiple boards of the same type. This limitation is a +limitation of the script and not of the mechanism used, it is possible to adapt +the script to support multiple boards of the same type. This modification is +left as an exercise to the reader. + +The following Make snippet is used: + +~~~~~~~~~~~~~~~~~~~ + LOCAL_BOARD_MAP ?= 1 + + # Adapt this list to your board collection + SERIAL_nucleo-f103rb ?= 066BFF343633464257254156 + SERIAL_same54-xpro ?= ATML2748051800005053 + SERIAL_samr21-xpro ?= ATML2127031800008360 + SERIAL_nrf52dk ?= 000682223007 + + ifeq (1,$(LOCAL_BOARD_MAP)) + + # Retrieve the serial of the selected board + BOARD_SERIAL = $(SERIAL_$(BOARD)) + + # Check if there is a serial for the board + ifneq (,$(BOARD_SERIAL)) + + # Set the variables used by various debug tools to the selected serial + SERIAL ?= $(BOARD_SERIAL) + DEBUG_ADAPTER_ID ?= $(BOARD_SERIAL) + JLINK_SERIAL ?= $(BOARD_SERIAL) + + # Use the existing script to grab the matching /dev/ttyACM* device + PORT ?= $(shell $(RIOTTOOLS)/usb-serial/ttys.py --most-recent --format path --serial $(SERIAL)) + endif + endif +~~~~~~~~~~~~~~~~~~~ + +The array of board serial numbers has to be edited to match your local boards. +The serial numbers used here is the USB device serial number as reported by +the debugger hardware. With the `make list-ttys` it is reported as the 'serial': + +~~~~~~~~~~~~~~~~~~~ +$ make list-ttys +path | driver | vendor | model | model_db | serial | ctime +-------------|---------|--------------------------|--------------------------------------|-----------------------|--------------------------|--------- +/dev/ttyUSB0 | cp210x | Silicon Labs | CP2102 USB to UART Bridge Controller | CP210x UART Bridge | 0001 | 15:58:13 +/dev/ttyACM1 | cdc_acm | STMicroelectronics | STM32 STLink | ST-LINK/V2.1 | 0671FF535155878281151932 | 15:58:04 +/dev/ttyACM3 | cdc_acm | Arduino (www.arduino.cc) | EOS High Power | Mega ADK R3 (CDC ACM) | 75230313733351110120 | 15:59:57 +/dev/ttyACM2 | cdc_acm | SEGGER | J-Link | J-Link | 000683475134 | 12:41:36 +~~~~~~~~~~~~~~~~~~~ + +When the above make snippet is included as `RIOT_MAKEFILES_GLOBAL_PRE`, the +serial number of the USB device is automatically set if the used board is +included in the script. This will then ensure that the board debugger is used +for flashing and the board serial device is used when starting the serial +console. + +It supports command line parameters to filter by vendor name, model name, serial +number, or driver. In addition, the `--most-recent` argument will only print the +most recently added interface (out of those matching the filtering by vendor, +model, etc.). The `--format path` argument will result in only the device path +being printed for convenient use in scripts. + +Handling Multiple Boards: Simplest Approach {#multiple-boards-simple} +=========================================== + +Passing `MOST_RECENT_PORT=1` as environment variable or as parameter to +make will result in the most recently connected board being preferred over the +default PORT for the selected board. From cc451a553148335f6cd4514d674e89a0916634f0 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 15 Aug 2022 16:30:36 +0200 Subject: [PATCH 3/3] doc: Add documentation for TTY_BOARD_FILTER --- doc/doxygen/src/flashing.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/doxygen/src/flashing.md b/doc/doxygen/src/flashing.md index 927c479375..bdc94ce01e 100644 --- a/doc/doxygen/src/flashing.md +++ b/doc/doxygen/src/flashing.md @@ -342,3 +342,10 @@ Handling Multiple Boards: Simplest Approach {#multiple-boards-simple} Passing `MOST_RECENT_PORT=1` as environment variable or as parameter to make will result in the most recently connected board being preferred over the default PORT for the selected board. + +For some boards `TTY_BOARD_FILTER` is provided, which filters TTYs e.g. by +vendor or model to only considered TTYs that actually may belong to the selected +board. E.g. for Nucleo boards this is `--model 'STM32 STLink'`, as they all use +an integrated STLink as programmer. As long as only one TTY is provided from an +STLink, this will reliably select the correct TTY for an Nucleo regardless of +which TTY was most recently connected.