platformio / platform-ststm32

ST STM32: development platform for PlatformIO
https://registry.platformio.org/platforms/platformio/ststm32
Apache License 2.0
400 stars 311 forks source link

Add support for multiple ST-Link adapters #564

Open jcw opened 3 years ago

jcw commented 3 years ago

I've set up a Raspberry Pi as build farm for STM32 µC boards. The problem is that the ST-Link interfaces on these boards all look the same, apart from the serial number, exposed in the USB descriptors. For OpenOCD, which is the default upload tool, an extra parameter needs to be specified (hla_serial <serialnum>).

Attached is a platformio.ini file which properly uploads and connect to the matching serial port. It works, but it's messy, and I need to specify the board type again, even though PIO already has that info in its board definition file. Also included is a main.cpp, to test the builds / uploads (which will obviously fail at some point, without these exact same boards present).

blink.zip

It would be useful to streamline this all a bit more, perhaps with a new upload_serial config parameter. For the serial connection, a second simplification would be to use this same serial number to match the proper port (in minicom?) when monitor_port is not set. That way, all you'd need to pick a specific ST-Link would be to add upload serial = ....

(see also my forum post on this topic)

ivankravets commented 3 years ago

Yep, a known issue. We still have not found the best solution for it. hla_* has multiple options -> https://openocd.org/doc/html/Debug-Adapter-Configuration.html The same story with other on-chip debuggers, J-Link, etc.

Nevertheless, PlatformIO allows you to override variables in runtime. So, let use dynamic variables and post script:

platformio.ini

[env]
platform = ststm32
framework = cmsis
monitor_speed = 115200
lib_deps = jeeh
extra_scripts = post:extra_script.py

[env:f103]
board = nucleo_f103rb
build_flags = -Wno-format -DSTM32F1
custom_hla_serial = 066DFF525257775087154313
monitor_port = /dev/serial/by-id/usb-STMicroelectronics_STM32_STLink_${env:f103.custom_hla_serial}-if02

extra_script.py

Import("env")

f_index = env.get("UPLOADERFLAGS", []).index("-f")
hla_serial = env.GetProjectOption("custom_hla_serial", None)
if f_index > 0 and hla_serial:
    env["UPLOADERFLAGS"].insert(f_index, ["-c", f"hla_serial {hla_serial}"])

Should we add an example to https://docs.platformio.org/en/latest/projectconf/advanced_scripting.html?

maxgerhardt commented 3 years ago

Should we add an example to https://docs.platformio.org/en/latest/projectconf/advanced_scripting.html?

Would it make sense to integrate this into the core? E.g., if upload_protocol = stlink and upload_port is set explicitly and matches the serial number format, automatically inject the -c hla_serial <serial> command. Or instead of upload_port, support a hla_serial = .. option by standard.

ivankravets commented 3 years ago

Yes, I think we can parse upload_protocol. Need to discuss possible formats https://openocd.org/doc/html/Debug-Adapter-Configuration.html

jcw commented 2 years ago

Been a while, I'm going to investigate the extra_script.py approach. But there is still one issue with this - the names for ST-Link v2.1 and v3 differ:

monitor_port = /dev/serial/by-id/usb-STMicroelectronics_STM32_STLink_0670FF504955857567192657-if02
monitor_port = /dev/serial/by-id/usb-STMicroelectronics_STLINK-V3_004200283137510739383538-if02

One option would be to look at the devices which are currently present, and look for a match on their path names, perhaps something like this - untested:

p = os.listdir(f'/dev/serial/by-id/usb-STM*_${sernum}-if02')[0]

... with as added benefit that you wouldn't have to specify the full serial number, just enough to disambiguate.

jcw commented 2 years ago

The following works (note the findex+2):

Import("env")
try:
    findex = env.get("UPLOADERFLAGS").index("-f")
    sernum = env.GetProjectOption("custom_sernum")
    env["UPLOADERFLAGS"].insert(findex+2, ["-c", f"hla_serial {sernum}"])
except:
    pass

I'm trying to also auto-generate the proper monitor port setting for Linux, given that all the info is present when custom_sernum has been specified, but I can't quite figure out how/where to set this. I imported projenv and looked at its Dump(), but there's no mention of a monitor_port.

What I'm after, is to make everything upload and connect with just these settings for each attached ST-Link board:

[env:l412]
board = nucleo_l412kb
build_flags = ${env.build_flags} -DSTM32L4
custom_sernum = 0668FF575051717867043125

I can figure out how to scan the /dev/serial/by_id/ area in extra_script.py to find the exact path, but is there a way to generate the monitor port choice in the post:extra_script.py ?

Another approach would be for PIO to allow specifying a wildcard in its monitor_port setting:

custom_sernum = 0668FF575051717867043125
monitor_port = /dev/serial/by_id/usb-STM*${this.custom_sernum}-if02

Although that's slightly less convenient, because you then still have to specify that extra line for each board.

jcw commented 1 year ago

(re-opened, as this is actually still an issue)

As described here, there's a simplication possible:

monitor_port = hwgrep://0668FF575051717867043125

Which in the above context can then be written as follows (and moved to the [env] section):

monitor_port = hwgrep://${this.custom_sernum}

That also addresses the ST-Link v2 vs v3 issue, as either of them will now match.

ivankravets commented 1 year ago

There is a related feature request https://github.com/platformio/platformio-core/issues/4460

Please vote ( 👍 ) for it.

jcw commented 1 year ago

Okay, vote added. Not sure it's the same thing, but I suppose a filter for vid/pid is similar to a filter for a serial number. The key issue for me is specifying the serial number once, and using it for both uploads & serial monitor connections.