7
31
Fork
You've already forked blackmagic
23

Fix: ADI JTAG ensure_idle behaviour #2248

Merged
esden merged 1 commit from fix/adi-jtag-ensure-idle-behaviour into main 2026年05月06日 21:39:01 +02:00

Detailed description

In this PR we tweak the ensure_idle behaviour introduced in #2072 as while the behaviour established was correct and fine for targets that had entered Test-Logic-Reset (TLR), it would mis-step and transition targets in Run/Test-Idle (RTI) into an invalid state unknowingly. This is patched by always running a full JTAG state machine reset to get back into RTI from an unknown state as part of ensuring idle.

Tested working against STM32L4 and STM32F4 parts.

Your checklist for this pull request

Closing issues

Fixes #2241

<!-- Filling this template is mandatory --> ## Detailed description In this PR we tweak the ensure_idle behaviour introduced in #2072 as while the behaviour established was correct and fine for targets that had entered Test-Logic-Reset (TLR), it would mis-step and transition targets in Run/Test-Idle (RTI) into an invalid state unknowingly. This is patched by always running a full JTAG state machine reset to get back into RTI from an unknown state as part of ensuring idle. Tested working against STM32L4 and STM32F4 parts. ## Your checklist for this pull request * [x] I've read the [Code of Conduct](https://codeberg.org/blackmagic-debug/blackmagic/src/CODE_OF_CONDUCT.md) * [x] I've read the [guidelines for contributing](https://codeberg.org/blackmagic-debug/blackmagic/src/CONTRIBUTING.md) to this repository * [x] It builds for hardware native (see [Building the firmware](https://codeberg.org/blackmagic-debug/blackmagic?tab=readme-ov-file#building-the-firmware)) * [x] It builds as BMDA (see [Building the BMDA](https://codeberg.org/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-app)) * [x] I've tested it to the best of my ability * [x] My commit messages provide a useful short description of what the commits do ## Closing issues Fixes #2241
adiv5_jtag: Fixed adiv5_jtag_ensure_idle() so it doesn't mis-step the state machine when in idle already
Some checks failed
ci/woodpecker/pr/build-firmware/18 Pipeline failed
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-linux/1 Pipeline was successful
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-windows Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/push/build-firmware/8 Pipeline failed
ci/woodpecker/push/build-firmware/2 Pipeline was successful
ci/woodpecker/push/build-firmware/1 Pipeline was successful
ci/woodpecker/push/build-firmware/6 Pipeline was successful
ci/woodpecker/push/build-firmware/5 Pipeline was successful
ci/woodpecker/push/build-firmware/3 Pipeline was successful
ci/woodpecker/push/build-firmware/7 Pipeline was successful
ci/woodpecker/push/build-firmware/4 Pipeline was successful
ci/woodpecker/push/build-firmware/9 Pipeline was successful
ci/woodpecker/push/build-firmware/15 Pipeline was successful
ci/woodpecker/push/build-firmware/13 Pipeline failed
ci/woodpecker/push/build-firmware/14 Pipeline was successful
ci/woodpecker/push/build-firmware/10 Pipeline was successful
ci/woodpecker/push/build-firmware/17 Pipeline was successful
ci/woodpecker/push/build-firmware/11 Pipeline was successful
ci/woodpecker/push/build-firmware/16 Pipeline was successful
ci/woodpecker/push/build-firmware/12 Pipeline was successful
ci/woodpecker/push/build-firmware/18 Pipeline failed
ci/woodpecker/push/build-linux/1 Pipeline was successful
ci/woodpecker/push/build-firmware/20 Pipeline was successful
ci/woodpecker/push/build-firmware/19 Pipeline was successful
ci/woodpecker/push/build-linux/2 Pipeline was successful
ci/woodpecker/push/build-windows Pipeline was successful
de3341ecc1
northernpaws left a comment
Copy link

Looks good to me!

Looks good to me!
Contributor
Copy link

Thanks for fixing the incorrect execution of correct intent! However, as I don't see a "tested on AT32F403A" line, and original issue happened on these, please let me test this on the boards I have; as much as I'd like to fix the regression introduced for other Cortex-M SWJ-DP targets in JTAG transport mode, it should ideally still work on the problematic one.

Thanks for fixing the incorrect execution of correct intent! However, as I don't see a "tested on AT32F403A" line, and original issue happened on these, please let me test this on the boards I have; as much as I'd like to fix the regression introduced for other Cortex-M SWJ-DP targets in JTAG transport mode, it should ideally still work on the problematic one.
Contributor
Copy link

Okay, I have tested it on AT32F403A connected to vanilla bluepill (STM32F103CB like on BMPv2) with 4 JTAG wires and nRST, it works on v2.0.0-559-g de3341ec commit from BMDA, but it encounters an exception for standalone BMF during cortexm_reset().

JTAG access resulted in: 0:0
JTAG access resulted in: 1:0
Exception caught while detaching from target: JTAG-DP invalid ACK
(gdb) bt
#0 raise_exception (type=type@entry=1, msg=msg@entry=0x801a1b1 "JTAG-DP invalid ACK") at ../src/exception.c:28
#1 0x08005d42 in adiv5_jtag_raw_access (dp=dp@entry=0x200023b0, rnw=rnw@entry=1 '001円', addr=<optimized out>, 
 value=value@entry=0) at ../src/target/adiv5_jtag.c:166
#2 0x08005d82 in adiv5_jtag_read (dp=0x200023b0, addr=<optimized out>) at ../src/target/adiv5_jtag.c:107
#3 0x08005d9c in adiv5_dp_read (addr=4, dp=0x200023b0) at ../src/target/adiv5_interface.h:55
#4 adiv5_jtag_clear_error (dp=0x200023b0, protocol_recovery=<optimized out>) at ../src/target/adiv5_jtag.c:114
#5 0x08009f08 in adiv5_dp_error (dp=<optimized out>) at ../src/target/adiv5_interface.h:85
#6 cortex_check_error (target=<optimized out>) at ../src/target/cortex.c:61
#7 0x080080b6 in target_mem32_write (target=target@entry=0x20002428, dest=dest@entry=3758157068, 
 src=src@entry=0x20000e5c, len=len@entry=4) at ../src/target/target.c:372
#8 0x080082a6 in target_mem32_write32 (target=target@entry=0x20002428, addr=addr@entry=3758157068, 
 value=<optimized out>, value@entry=100270084) at ../src/target/target.c:637
#9 0x08009116 in cortexm_reset (target=0x20002428) at ../src/target/cortexm.c:807
#10 0x080083f4 in target_enter_flash_mode (target=target@entry=0x20002428) at ../src/target/target_flash.c:63
#11 0x0800851a in target_flash_erase (target=0x20002428, addr=134225920, len=110592)
 at ../src/target/target_flash.c:141
#12 0x08002e5a in exec_v_flash_erase (packet=<optimized out>, length=<optimized out>) at ../src/gdb_main.c:836
#13 0x08002dd4 in exec_command (packet=packet@entry=0x20001188 <packet_buffer> "vFlashErase:08002000,0001b000", 
 length=29, exec=0x801d248 <v_commands+32>) at ../src/gdb_main.c:405
#14 0x0800351a in handle_v_packet (packet=<optimized out>) at ../src/gdb_main.c:900
#15 gdb_main_loop (tc=tc@entry=0x20001004 <gdb_controller>, packet=0x20001188 <packet_buffer>, 
 in_syscall=in_syscall@entry=false) at ../src/gdb_main.c:383
#16 0x080035ba in gdb_main (packet=<optimized out>) at ../src/gdb_main.c:945
#17 0x08003bb2 in bmp_poll_loop () at ../src/main.c:61
#18 main () at ../src/main.c:76

I think I know why this happens. If I insert a platform_delay(1) between nrst_set_val edges on line 793, then it works.
stlink and blackpill-f411ce platforms don't incorporate delays in their platform_nrst_set_val() methods. This is #1868 point 2.
Specifically AT32F403A needs a reset by wire, because otherwise BMD gets another JTAG-DP invalid Ack exception during cortex_check_error trying to write AIRCR SYSRESETREQ ... because JTAG TAP gets reset, too. I don't know how to easily fix that, given BMD architecture.
After that addition, flashing from BMF works through JTAG. And BMDA has enough delay between BMPremote "reset" packets. This can be a separate PR.

Okay, I have tested it on AT32F403A connected to vanilla bluepill (STM32F103CB like on BMPv2) with 4 JTAG wires and nRST, it works on v2.0.0-559-g de3341ec commit from BMDA, but it encounters an exception for standalone BMF during `cortexm_reset()`. ``` JTAG access resulted in: 0:0 JTAG access resulted in: 1:0 Exception caught while detaching from target: JTAG-DP invalid ACK ``` ```js (gdb) bt #0 raise_exception (type=type@entry=1, msg=msg@entry=0x801a1b1 "JTAG-DP invalid ACK") at ../src/exception.c:28 #1 0x08005d42 in adiv5_jtag_raw_access (dp=dp@entry=0x200023b0, rnw=rnw@entry=1 '001円', addr=<optimized out>, value=value@entry=0) at ../src/target/adiv5_jtag.c:166 #2 0x08005d82 in adiv5_jtag_read (dp=0x200023b0, addr=<optimized out>) at ../src/target/adiv5_jtag.c:107 #3 0x08005d9c in adiv5_dp_read (addr=4, dp=0x200023b0) at ../src/target/adiv5_interface.h:55 #4 adiv5_jtag_clear_error (dp=0x200023b0, protocol_recovery=<optimized out>) at ../src/target/adiv5_jtag.c:114 #5 0x08009f08 in adiv5_dp_error (dp=<optimized out>) at ../src/target/adiv5_interface.h:85 #6 cortex_check_error (target=<optimized out>) at ../src/target/cortex.c:61 #7 0x080080b6 in target_mem32_write (target=target@entry=0x20002428, dest=dest@entry=3758157068, src=src@entry=0x20000e5c, len=len@entry=4) at ../src/target/target.c:372 #8 0x080082a6 in target_mem32_write32 (target=target@entry=0x20002428, addr=addr@entry=3758157068, value=<optimized out>, value@entry=100270084) at ../src/target/target.c:637 #9 0x08009116 in cortexm_reset (target=0x20002428) at ../src/target/cortexm.c:807 #10 0x080083f4 in target_enter_flash_mode (target=target@entry=0x20002428) at ../src/target/target_flash.c:63 #11 0x0800851a in target_flash_erase (target=0x20002428, addr=134225920, len=110592) at ../src/target/target_flash.c:141 #12 0x08002e5a in exec_v_flash_erase (packet=<optimized out>, length=<optimized out>) at ../src/gdb_main.c:836 #13 0x08002dd4 in exec_command (packet=packet@entry=0x20001188 <packet_buffer> "vFlashErase:08002000,0001b000", length=29, exec=0x801d248 <v_commands+32>) at ../src/gdb_main.c:405 #14 0x0800351a in handle_v_packet (packet=<optimized out>) at ../src/gdb_main.c:900 #15 gdb_main_loop (tc=tc@entry=0x20001004 <gdb_controller>, packet=0x20001188 <packet_buffer>, in_syscall=in_syscall@entry=false) at ../src/gdb_main.c:383 #16 0x080035ba in gdb_main (packet=<optimized out>) at ../src/gdb_main.c:945 #17 0x08003bb2 in bmp_poll_loop () at ../src/main.c:61 #18 main () at ../src/main.c:76 ``` I think I know why this happens. If I insert a `platform_delay(1)` between nrst_set_val edges on line 793, then it works. `stlink` and `blackpill-f411ce` platforms don't incorporate delays in their `platform_nrst_set_val()` methods. This is #1868 point 2. Specifically AT32F403A needs a reset by wire, because otherwise BMD gets another JTAG-DP invalid Ack exception during cortex_check_error trying to write AIRCR SYSRESETREQ ... because JTAG TAP gets reset, too. I don't know how to easily fix that, given BMD architecture. After that addition, flashing from BMF works through JTAG. And BMDA has enough delay between BMPremote "reset" packets. This can be a separate PR.
Author
Owner
Copy link

Arguably platforms aren't meant to, so native having a busy loop is.. wrong..

Lines 792 to 793 in 85fcb0e
platform_nrst_set_val(true);
platform_nrst_set_val(false);

should really have platform_delay(1) between the two calls.

Agreed about that being a second PR though.

Arguably platforms aren't meant to, so native having a busy loop is.. wrong.. https://codeberg.org/blackmagic-debug/blackmagic/src/commit/85fcb0ef1d14ad652f9e7b30a410efd23360ba0f/src/target/cortexm.c#L792-L793 should really have `platform_delay(1)` between the two calls. Agreed about that being a second PR though.
esden left a comment
Copy link

Double checked everything and tested using several targets that were showing issues before. This patch fixes them and looks good to be merged for me.

Will merge if/when @northernpaws checkes off on this. :)

Edit: should have reloaded the PR, did not realize there was additional activity here. 😓 That said, I guess we are ready to merge this :D

Double checked everything and tested using several targets that were showing issues before. This patch fixes them and looks good to be merged for me. Will merge if/when @northernpaws checkes off on this. :) Edit: should have reloaded the PR, did not realize there was additional activity here. 😓 That said, I guess we are ready to merge this :D
esden deleted branch fix/adi-jtag-ensure-idle-behaviour 2026年05月06日 21:39:06 +02:00
Sign in to join this conversation.
No reviewers
Labels
Clear labels
BMD App
Black Magic Debug App (aka. PC hosted) (not firmware)
BMP Firmware
Black Magic Probe Firmware (not PC hosted software)
Bug
Confirmed bug
Build system
Build system
Can't reproduce
Maintainers can't reproduce this problem
CI
Continuous Integration System
Contribution wanted
User contributions welcome
Documentation
Project documentation
Draft
Work in progress draft
Duplicate
This issue or pull request already exists
Enhancement
General project improvement
Feedback wanted
Requires additional submitter feedback
Foreign Host Board
Non Native hardware to runing Black Magic firmware on
GDB
Issue/PR related to GDB
Good first issue
Good for newcommers
HwIssue Mitigation
Solving or mitigating a Hardware issue in Software
Information Needed
Maintainers need more information
NativeHardware
Official Black Magic Debug Hardware
New Host Board
New hardware to run Black Magic firmware on
New Target
New debug target
Off Topic
Something that does not involve the project in any way
Potential Bug
A potential, unconfirmed or very special circumstance bug
Regression
Bug caused by a regression
User Interest Needed
More user interest required before consideration
User Testing Needed
Looking for user testing reports
Won't fix
Outside of the project scope or works as intended
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
blackmagic-debug/blackmagic!2248
Reference in a new issue
blackmagic-debug/blackmagic
No description provided.
Delete branch "fix/adi-jtag-ensure-idle-behaviour"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?