SWD Wasn't Talking, So I Changed the Target: SWD Reconnaissance, DAP Failures, and a Dual-Bank Plot Twist

There is a quiet threshold in hardware security when you move from reading datasheets to physically talking to the chip.

In software, a crash usually gives you a stack trace. On a circuit board, an unresponsive debug interface gives you nothing but silence. You’re left staring at a few exposed copper pads, wondering whether your probes slipped half a millimetre, your clock signal is too noisy, or the chip has simply decided you’re not getting in today.

Recently, I spent time exploring Serial Wire Debug (SWD) across two very different targets: a compact embedded GNSS node and a Cube Orange Plus flight controller. I started with a simple vision in mind; identify the pins, connect a debugger and inspect memory. Along the way I ended up learning about signal integrity, ARM CoreSight debugging mechanics, Readout Protection (RDP), and dual-bank flash layouts.

Here is how it went.

Visual Recon: Following the Wrong Copper First

Before hooking up logic analyzers or debuggers, you have to follow the physical traces.

Working under an AmScope stereo microscope, I started tracing the PCB of the small GNSS target. Near one edge sat an 8-pin SOIC package labeled A51/3, 5480RC. My initial thought was that I’d stumbled onto an external SPI flash chip containing non-volatile configuration or firmware.

A quick datasheet lookup killed that hypothesis immediately: it was an NXP TJA1051T/3, a high-speed CAN transceiver. Useful if I wanted to tap the bus, but completely irrelevant for direct firmware extraction.

Continuing the board scan brought me to the actual primary controller: an STM32F302K8 (ARM Cortex-M4), housed in a compact 32-pin UFQFPN package with a 0.5 mm pitch.

Using a digital multimeter in continuity mode, I traced the core debug signals from the exposed test pads back to the MCU pins:

  • PA13 → SWDIO (Serial Wire Data Input/Output)

  • PA14 → SWCLK (Serial Wire Clock)

  • NRST → Hardware Reset

  • VDD / VSS → Power and Reference Ground

Once physical continuity was confirmed, it was time to bring out the J-Link.

When the DAP Refuses to Talk

I hooked up a SEGGER J-Link Pro to the GNSS board’s test pads using PCBite spring probes and launched JLinkExe.

Instead of reading a valid Debug Access Port (DAP) signature, the J-Link Commander threw an initialization failure:

Connecting to target via SWD
InitTarget() start
SWD selected. Executing JTAG -> SWD switching sequence.
Error: Failed to initialize DAP.
Can not attach to CPU.
Trying connect under reset...

This failure happens at the low-level CoreSight handshake before the debugger can even establish communication with the Cortex-M core.

My first thought was physical signal degradation. At default SWD clock speeds (~4 MHz), jumper capacitance and spring probe contact could introduce enough ringing and rise-time distortion to invalidate the SWD sequence, a plausible signal-integrity failure mode.

I dropped the SWD clock speed down to 100 kHz:

J-Link> Speed 100
J-Link> r

Reducing the clock frequency increases the available timing margin and provides a useful test for frequency-dependent communication failures. It made zero difference, the exact same DAP initialization error persisted.

So I shifted the investigation toward target-side configuration, reset behavior, and other board-level faults.

At that point, the remaining hypotheses included:

  1. Target-side option-byte or flash were either configured wrong or corrupted.

  2. The running firmware quickly reconfigured PA13 / PA14 into standard GPIOs upon boot, disabling the debug peripheral before the probe attached.

  3. The hardware reset line (NRST) wasn’t holding the target in reset long enough for a successful Connect Under Reset sequence.

  4. Or maybe some totally different board-level fault affecting the debug path.

With so many possibilities, rather than burning hours guessing on a single board I decided to isolate the debugger itself.

Changing the Target to Isolate the Tool

To verify if my debug probe, software configuration, or cable setup was broken, I swapped out the GNSS board for a target I knew was intact: a Cube Orange Plus flight controller built around an STM32H757ZI.

Same SEGGER J-Link Pro. Same computer. Same software commands.

The moment I ran the attach sequence, the target responded immediately:

The DPIDR (Debug Port Identification Register) value 0x6BA02477 confirmed an ARM CoreSight SW-DP interface responding cleanly over the wire. The same debugger and host-side setup successfully communicated with another STM32 target, making a target-specific problem on the GNSS board significantly more likely.

Now I could pivot fully to probing the STM32H7 target.

Verifying Readout Protection (RDP)

Before attempting a full memory dump, I needed to check if chip readout protection was enabled.

On the STM32H7 series, the active protection level is stored in the Option Status Register (FLASH_OPTSR_CUR) located at memory address 0x5200201C. I issued a direct 32-bit memory read over SWD:

J-Link> mem32 0x5200201C 1
5200201C = 1B86AAF0

The RDP field in the returned value was 0xAA, corresponding to RDP Level 0.

In the ST ecosystem, an RDP byte value of 0xAA indicates Level 0 (unprotected). If it had returned 0x55 (Level 1) or any arbitrary non-0xAA/0x55 value (Level 2), readout would be blocked or permanently locked.

This indicated that RDP was at Level 0, so readout protection was not preventing the SWD memory accesses used in this investigation.

The “Blank” Flash Confusion

With RDP confirmed at Level 0, I issued a read command starting at the standard STM32 flash base address (0x08000000):

J-Link> mem32 0x08000000 4
08000000 = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF

Nothing. All unprogrammed 0xFF bytes.

For a second, it looked like the chip’s main memory bank was erased. But flight controllers don’t boot off of nothing right?

That’s when I pondered over its architecture: the STM32H757ZI uses a dual-bank flash structure:

  • Bank 1: 0x08000000 to 0x080FFFFF (1 MB)

  • Bank 2: 0x08100000 to 0x081FFFFF (1 MB)

The STM32H757ZI uses a 2 MB dual-bank flash architecture, with the two 1 MB regions accessible at 0x08000000–0x080FFFFF and 0x08100000–0x081FFFFF. One of the major advantages of dual-bank flash is supporting safer firmware-update strategies: while one bank contains the currently running firmware, the other can be programmed with a new image without modifying the bank being executed. If the update mechanism is designed for it, the original image can remain available as a fallback if the new image fails validation or the update is interrupted.

I checked the second flash region.

I offset the target address to 0x08100000 and re-ran the read:

J-Link> mem32 0x08100000 4
08100000 = F894AF3A E73631DF 27062605 3170F884

The returned data was structured and non-erased, consistent with a programmed firmware image.

Extracting the Binary

With the correct memory layout confirmed, dumping the binary was straightforward using J-Link’s savebin utility:

J-Link> savebin C:\Users\Public\cube_bank2_firmware.bin, 0x08100000, 0x100000
Reading 1048576 bytes from 0x08100000 into binary file... O.K.

(Note: If you run savebin into a system directory like C:\Program Files\, Windows permission boundaries can prevent the file from being written. Dropping the output path to a fully writable user directory bypasses the issue.)

The probe streamed the full 1 MB image from Bank 2 over SWD, giving me a raw binary preserved for subsequent static analysis in Ghidra.

Realizations

  1. Datasheets beat visual assumptions every time. Don’t assume an 8-pin IC next to a microcontroller is an SPI EEPROM/Flash. Verify part numbers before wasting time soldering leads.

  2. Methodical isolation saves hours. When a debug handshake fails, don’t spend endless time tweaking clock rates or jumper wires on one target. Swap to a target with known hardware behavior to isolate probe software issues from hardware line locks.

  3. Empty base memory doesn’t mean empty silicon. Modern dual-bank MCUs routinely boot from remapped address spaces or secondary banks. If 0x08000000 returns 0xFFFFFFFF, check the option bytes and memory maps before assuming the target is blanked.

Technical Notes & Assumptions

  • GNSS Target DAP Failure: The underlying root cause on the GNSS board remains unresolved. If I end up soldering logic analyzer channels onto SWDIO/SWCLK during reset on that board later, I’ll write up a follow-up.

Closing Thoughts

The most useful part of this investigation was the process of getting there: identifying the hardware correctly, isolating variables when SWD failed, verifying the protection state, and questioning an apparently blank memory region instead of accepting the first explanation.

Hardware security rarely gives you the clean feedback that software does. Sometimes the chip doesn’t tell you what’s wrong, you have to eliminate possibilities until the silicon finally gives you something useful.

In this case, it was a different flash address.

1 Like