2023-11-06 01:46 AM - edited 2023-11-06 06:00 AM
Hello,
I got a radio MCU which connects to cloud and can receive binaries from database. And I got a STM32 that controls some stuff, including other MCUs. In production this means a lot of headers and programming time for all of them, no way to update remotely, and even if the code is thoroughly tested - glitches are still possible.
So I want to connect things in a chain, so that if something apart from the radio crashes - radio MCU could re-flash the whole system. This of course could be done with UART when using bootloaders, but this again means you have to pre-program bootloaders on MCUs, and there's still a very slim chance it might fail.
So I need an example of how one MCU can flash another via JTAG or SWD (preferably), and then verify the result. From there I could get it to work on Arduino / STM / AVR / radio ARM. What I really want is a proof of concept simple test example to show it works with the peripheral (bit banging is always possible, but surely there is a smarter way to do it using existing MCU resources), before I go ahead and order prototype boards.
In general this should not be black magic, we've all got some Nucleo boards, which are a great example that programming STM32 with STM32 is possible. On my NucleoF722ZE, the STM32F103CBT6 does the programming. It should receive packets via USB, then program the main MCU via either JTAG or SWD. It has a pair of jumpers - CN4, when closed - the jumper connects T_JTCK with SWCLK, and T_JTMS with SWDIO, and programs the big MCU via SWD interface.
When I look at how these signals are wired, I see this:
PB14 (SPI2_MISO) - T_JTMS - SWDIO
PB13 (SPI2_SCK) - T_JTCK - SWCLK
PB12 (SPI2_NSS) via resistor - T_JTMS - SWDIO
It leads me to think that SWD is done somehow with SPI2 in half-duplex master mode. I've seen people mentioning SPI for JTAG more than once, but I haven't found a good example.
If STM has the code for Nucleo STM32F103CBT6 programmer freely available - that would be everything I need to proceed with my project. But I can't find it.
What I have found so far:
JTAG bit-banging example: https://github.com/openwch/usb-jtag-spi/tree/main/src/OpenOCD/USB20JTAG
Free DAP, also bit-banging: https://github.com/ataradov/free-dap/blob/master/dap.c
Arduino SWD programmer, bit-banging: https://github.com/dimitar-kunchev/arduino-swd-programmer-samd/tree/master
LibSWD, opensource project to make SWD more available: https://github.com/cederom/LibSWD/tree/master
There are Black Magic probe source codes: https://github.com/blackmagic-debug/blackmagic
Wiki page on ST-link with some links to firmware reverse-engineering: https://stm32world.com/wiki/ST-Link
There's a lot of references to OpenOCD, but it's a ton of information, and at this point I don't even see if it's useful for me:
https://openocd.org/doc/html/index.html
There is a topic on Hackaday, which is about the hardware and firmware of STlink: https://hackaday.io/project/179054-custom-st-link-v20-v21-v30/details
At this point I'm just shocked that programmer firmware is something that people need to hack, instead of ST just providing a source code so people can use it with their ICs.
SWD tutorial page: https://robo.fish/wiki/index.php?title=SWD
ST-link open source project: https://github.com/stlink-org/stlink
There is also an adaptation of libSWD for ESP32 which in fact uses SPI, and this might be the most relevant resource: https://github.com/PaulFreund/libSWD-esp32
So it's not like there is no information on the topic. Almost all the code I found seems to bit-bang the data. I find it hard to believe that both JTAG and SWD on all STM32-based programmers are wired to SPI peripheral by pure coincidence :D Especially after that last repo for ESP32, which reads it via SPI.
Or maybe I'm just blind and don't see something right in front of me, and someone will be able to point it out :D
It looks like the best approach is to adopt Paul Freund's project to some Arduino board and check out if it works fine. In the meantime, if anyone knows of original STM32 STlink source, or SWD example, or Arduino/STM32/AVR source that uses SPI to do SWD, to upload the flash to STM32 and check if it uploaded correctly - please drop a comment.
I hope if this does not get resolved, at least the stuff I collected here might be of use.
UPD. 1
Another project, using SWD over SPI with Raspberry PI: https://github.com/lupyuen/pi-swd-spi
And it has a cool spreadsheet with commands and bits: https://docs.google.com/spreadsheets/d/12oXe1MTTEZVIbdmFXsOgOXVFHCQnYVvIw6fRpIQZybg/edit#gid=0
UPD. 2
A very interesting blog post explaining how to do SWD over SPI: https://www.pcbway.com/blog/technology/OpenOCD_on_Raspberry_Pi__Better_with_SWD_on_SPI.html
An Arduino example for monitoring SWD line (might be useful to test or verify something): https://levelup.gitconnected.com/listen-up-how-to-monitor-uart-i2c-swd-and-spi-with-arduino-9d8ef25da308
2023-11-06 04:17 AM
JTAG / SWD control is non-trivial and documented by ARM. You'd need to push in code specific to the STM32 to write FLASH, via the normal registers and interaction.
Less complex would be to initiate the ROM loader and use UART (AN3155) or other supported peripherals and protocols (AN2606) to communicate with code provided to do that.
2023-11-06 05:05 AM
Hi. Yes I know it would be less complex, but you're missing the point. Every ST-LINK does it, and there's a bunch of projects where people have done it. So non-triviality doesn't matter - it's done. In most cases it's done with bit-banging which is usable and portable, but not the best way to do it IMHO. So I did a bit of research and found out it has also been implemented over SPI by few awesome people.
I can try to adapt the code from PaulFreund or lupyuen, and I will do so if I need to. But it will take days to rewrite and test, and I don't want to reinvent the wheel if it's already been done by smart people, or ST have since published their sources, and I just didn't think to look for sources in the most obvious place.
So perhaps my explanation of what I wanted to achieve was a bit blurry - I am looking for an easier to use example, not alternatives or reasons to not do it :D While looking for materials, I've seen some 15+ people trying to do the same thing to simplify their production, not to mention those who try to clone ST-link for whatever reasons, so I believe this is a useful exercise.
2023-11-06 06:56 PM
Take a note that setting an RDP level 2 disables the SWD/JTAG debug interfaces completely and permanently.
2023-11-14 11:55 AM
Thanks for your input, this is of course good to remember. Yet this is a slightly different topic. I've really started this hoping that someone might add more information to the links I collected - solutions that are easier to port or test out, vids with explanations, links to repos.