Non-secure programming at 0x08020000 succeeds and verifies after changing the STM32U535 flash organization from dual-bank to single-bank with DBANK=0. Correcting the secure watermark remains necessary: the secure region must stop before the non-secure image address. Treat the download-complete message as a transport result only; the readback comparison is the acceptance test.
Failure Signature and Acceptance Criteria
The failing setup used STM32CubeProgrammer v2.22.0, ST-LINK firmware V2J47S7, SWD Hot Plug mode at 4000 KHz, and a target voltage of 3.28 V. The detected device was an STM32U535/STM32U545, device ID 0x455, revision Y, with 256 KBytes of nonvolatile memory.
The command downloaded a 16-byte binary to the non-secure image address:
STM32_Programmer_CLI.exe -c port=SWD mode=HotPlug -d test16.bin 0x08020000 -v
Erase and download both reported completion, but verification read 0x00 where the file contained 0xEF at 0x08020000. That distinction narrows the problem: the host transferred the data, but the final flash contents at the requested address did not match.
| Observation | Engineering meaning | Next check |
|---|---|---|
| Secure memory remains programmable | The probe, SWD link, and general flash interface are operational. | Inspect security attribution at the failing address. |
| Download reaches 100% | The programmer completed its write transaction sequence. | Require readback verification; do not accept download completion alone. |
0x00 read instead of 0xEF
|
The requested byte was not retained or was not read through the expected memory mapping. | Check secure watermarks, write protection, and bank organization. |
| A template TrustZone project also fails | The fault is below application logic and linker content. | Commission option bytes independently of the project. |
Check 1: repeat the 16-byte test with -v. Expect no mismatch at 0x08020000 before treating the flash path as commissioned.
Address Map and Security Boundary
The term secure watermark here means the option-byte range that attributes flash pages to the secure domain. With TZEN=1, an address intended for the non-secure image must fall outside every active secure watermark.
The original configuration placed SECWM1_PSTRT=0x0 at and SECWM1_PEND=0x1F at . For the reported 256-Kbyte device, those displayed endpoints span the flash address space represented by the programmer. The intended non-secure boot address, NSBOOTADD0=0x100400, decoded by the tool as 0x08020000, therefore lay inside that original secure range.
The corrected boundary used SECWM1_PEND=0x0F, displayed as . The next displayed boundary is 0x08020000, so the corrected configuration creates the intended division: secure flash below the non-secure start and non-secure flash beginning at 0x08020000. This is the reported 128-Kbyte/128-Kbyte split.
Bank 2 showed SECWM2_PSTRT=0x1F at and SECWM2_PEND=0x0 at 0x08020000. Because the displayed start is above the end, this range does not describe an ascending secure interval. Confirm the programmer continues to display those exact values after every option-byte operation.
Check 2: display the option bytes and expect NSBOOTADD0 to resolve to 0x08020000, while SECWM1_PEND resolves to . If the secure end again displays , correct the watermark before programming.
Option-Byte Baseline
Capture the active configuration before changing it:
STM32_Programmer_CLI.exe -c port=SWD -ob displ
Use the decoded output rather than relying only on a successful option-byte write message. The relevant baseline values were:
| Field | Reported value | Commissioning interpretation |
|---|---|---|
RDP |
0xAA |
Level 0; keep this state while isolating programming and mapping faults. |
TZEN |
0x1 |
Global TrustZone security enabled. |
SWAP_BANK |
0x0 |
Bank addresses are not swapped. |
DBANK |
0x1 |
Dual-bank flash with contiguous addresses; this was the failing organization. |
NSBOOTADD0 |
0x100400 |
The tool decodes it as 0x08020000. |
HDP1EN, HDP2EN
|
0x0 |
No hidden-protection area was enabled in either bank. |
Changing several protection states at once obscures causality. The attempted recovery moved RDP to 0xBB, then returned it to 0xAA while clearing TZEN. It did not resolve the programming failure after TrustZone and the watermarks were restored. Use that sequence only as a controlled recovery operation, not as the primary correction for this symptom.
Check 3: after reconnecting, run -ob displ again. Expect RDP=0xAA, SWAP_BANK=0x0, and the planned TrustZone state. Stop if the decoded values differ from the values just written.
Write-Protection Exclusion
Write protection must be excluded before changing the bank layout. Both protection ranges were reported unlocked. For Bank 1, WRP1A_PSTRT and WRP1B_PSTRT were 0xF, while both corresponding end values were 0x0; UNLOCK_1A and UNLOCK_1B were 0x1. Bank 2 reported the same start/end pattern through WRP2A_* and WRP2B_*, with both unlock fields at 0x1.
That output separates write protection from security attribution. A non-secure address can be outside an enabled write-protection range yet still be inaccessible because a secure watermark or bank mapping assigns it differently. Clearing write protection repeatedly will not correct an address-attribution fault.
- Display all option bytes with
-ob displ. - Inspect both A and B protection ranges for each displayed bank.
- Confirm the output explicitly describes each range as unlocked.
- Check
HDP1EN=0x0andHDP2EN=0x0so a hidden-protection region is not part of the diagnosis.
Check 4: expect all four reported write-protection areas to remain unlocked and both HDP enable fields to remain zero. If not, correct that protection independently before testing DBANK.
Secure-Watermark Programming
Commission the watermark before loading either image. The attempted combined operation exposed an ordering constraint in the programming workflow: the watermark option names were unavailable while TrustZone was disabled. Enabling TZEN recreated the prior incorrect SECWM1_PEND=0x1F, so the watermark then had to be corrected explicitly.
- At
RDP=0xAA, establish a known erased baseline and confirm that the small binary can be addressed when TrustZone is disabled. - Enable TrustZone using the connection mode that remains reliable for the target. The tested command form was
STM32_Programmer_CLI.exe -c port=SWD mode=HOTPLUG -ob TZEN=1. - Reconnect and display the option bytes. TrustZone activation may expose the secure-watermark field names to the programmer.
- Set
SECWM1_PSTRT=0x0andSECWM1_PEND=0x0F. - Set
SECWM2_PSTRT=0x1FandSECWM2_PEND=0x0. - Reconnect again and read the decoded addresses, not merely the hexadecimal field values.
mode=UR was used during some attempted option-byte writes, while mode=HOTPLUG was used successfully for other TrustZone operations. Connection mode is secondary here: accept a mode only when the subsequent option-byte display reports the intended persistent values.
Check 5: expect , , , and SECWM2_PEND=0x0 (0x08020000).
Single-Bank Flash Selection
Correcting SECWM1_PEND removed the obvious overlap but did not make the non-secure image programmable. The decisive change was DBANK=0. With DBANK=1, the device reported dual-bank flash with contiguous addresses; the erase log identified internal sector 16 for 0x08020000. Bank organization affects how the flash controller and programming algorithm translate logical addresses into physical erase/program units. Security boundaries must agree with that organization.
Set the option byte through the same STM32CubeProgrammer option-byte interface used for the other fields. Using the demonstrated CLI form, the operation is:
STM32_Programmer_CLI.exe -c port=SWD mode=HotPlug -ob DBANK=0
An option-byte change can require the programming session to reconnect before the new memory organization is visible. Do not continue using cached option-byte output or a connection opened before the change.
- Write
DBANK=0. - Disconnect and reconnect the programmer.
- Run
STM32_Programmer_CLI.exe -c port=SWD -ob displ. - Confirm
DBANK : 0x0before erasing or downloading. - Recheck the secure-watermark decoded addresses because the bank-layout change and security configuration must describe the same intended boundary.
Check 6: expect the live option-byte display to report DBANK=0, with the secure region ending before 0x08020000.
End-to-End Programming Verification
Verify the configuration with the smallest failing artifact before loading the complete secure and non-secure applications. This keeps application startup, vector-table content, and inter-domain calls outside the flash-programming test.
- Reconnect over SWD and record the detected device, supply voltage, and option-byte display.
- Confirm
RDP=0xAA,TZEN=0x1,SWAP_BANK=0x0, andDBANK=0. - Confirm the corrected watermark endpoints and all write-protection areas remain unlocked.
- Program the 16-byte binary with
STM32_Programmer_CLI.exe -c port=SWD mode=HotPlug -d test16.bin 0x08020000 -v. - Require verification to complete without
Data mismatch found at address 0x08020000. - Program the non-secure application first, then the secure application.
- Reset and run the target. Confirm execution transfers to the configured non-secure boot address and that a fresh programmer readback still matches the programmed image.
Check 7: expect the byte at 0x08020000 to equal the file value—0xEF in the recorded 16-byte test—not 0x00. This readback is the final proof that erase, programming, security attribution, and flash organization agree.
FAQ
How do I fix STM32U535 non-secure flash verification?
Set DBANK=0, reconnect, and confirm the live option-byte display reports single-bank operation. Keep the corrected secure watermark ending at , then program and verify the non-secure image at 0x08020000.
How do I know whether 0x08020000 is secure or non-secure?
Read the decoded secure-watermark addresses with STM32_Programmer_CLI.exe -c port=SWD -ob displ. For this layout, SECWM1_PEND=0x0F displays , leaving 0x08020000 as the intended start of non-secure flash.
How do I distinguish a download failure from a verify failure?
Use -v and inspect the readback result. A 100% download followed by 0x00 instead of 0xEF at 0x08020000 is a verification failure even though the transfer reported completion.
How do I check whether write protection caused the failure?
Display the option bytes and inspect WRP1A, WRP1B, WRP2A, and WRP2B. The failing setup already reported all four areas unlocked, with UNLOCK_1A=0x1, UNLOCK_1B=0x1, UNLOCK_2A=0x1, and UNLOCK_2B=0x1.
How do I verify the STM32U535 TrustZone fix end to end?
Confirm DBANK=0 and the corrected watermarks, program test16.bin at 0x08020000 with -v, and expect the first byte to read back as 0xEF. Then program the non-secure image followed by the secure image, reset the target, and confirm execution reaches the configured non-secure boot address.