Sync betaflight to Gitea

This commit is contained in:
2026-08-03 16:37:10 +08:00
commit ad3163cf91
4712 changed files with 3301380 additions and 0 deletions
+183
View File
@@ -0,0 +1,183 @@
# Unbricking the STM32N6 (TSV + system DFU)
Use this when OBL or BF in XSPI flash is broken and the board no longer
boots into a usable state — `bl rom` from the BF CLI, OBL DFU on a
crashed BF, and SWD-load workflows are all unavailable. The boot ROM's
built-in system DFU is always reachable, but it can't write the on-board
XSPI flash on its own; CubeProgrammer drives it through a TSV that
stages two helper binaries into RAM first.
## Why the on-chip DFU can't just write XSPI
The N6 boot ROM exposes a system DFU bootloader (`0483:DF11` with the
ST descriptor "STM32 BOOTLOADER", reached via BOOT0=DEV) but the alts
it offers are RAM- and OTP-shaped:
```
@FSBL /0x34180400/01*512Kg -- staged FSBL → AXISRAM2 secure
@RSSE_FW ...
@RSSE_BLOB ...
@RSSE_PLUGIN ...
@virtual ...
```
There's no `@nor0` alt and no XSPI alt — the ROM has no XSPI driver. To
write nor0 you have to:
1. Upload a signed FSBL into RAM via the `@FSBL` alt. The ROM verifies
it, copies it to AXISRAM2, and runs it.
2. The FSBL you upload is itself a DFU loader (ST's "OpenBootloader")
that exposes `@nor0` plus an "external memory loader" alt for the
chosen flash chip's driver.
3. Upload the matching XSPI flash driver into RAM via the `@External
memory loader` alt; the OpenBootloader links it in and the rest of
the DFU session can read/write nor0.
4. Now write your application binary to nor0 at the right offset.
The TSV (Target Sequence Vector) file is just a script for
`STM32_Programmer_CLI -d <FlashLayout.tsv>` that orchestrates these
four steps in order so it looks like a single flash operation from the
host's point of view.
## When to use this
- `bl rom` from BF CLI / OBL DFU `:leave` doesn't reboot the chip into
a working state.
- BF crashes early enough that the BF↔OBL IWDG-recovery path doesn't
trigger (e.g., a fault before OBL's iwdg_start runs, or OBL itself is
corrupt).
- You want to nuke and re-flash both OBL and BF from a clean slate.
If the chip is reachable via SWD (BOOT1 in the position that bypasses
the FSBL on the dev kit, or BF still alive enough that OBL DFU comes
up), prefer the SWD-load or OBL-DFU paths — they don't require touching
hardware switches.
## What you need
- **STM32CubeProgrammer 2.18+ with the N6 patches installed.** The
Linux build prior to 2.22 has bugs around the N6 external-loader
workflow; current ST tooling works.
- **`OpenBootloader_STM32N6570-DK-trusted.stm32`** — ST's signed
OpenBootloader image. Ships in CubeN6 at
`lib/modules/STM32N6/Projects/STM32N6570-DK/Applications/OpenBootloader/Binaries/NOR_Binary/`.
- **`MX66UW1G45G_STM32N6570-DK.bin`** — XSPI flash driver matching the
on-board MX66UW1G45G. Same directory in CubeN6.
- The binaries you want in nor0:
- `obl_mx66uw1g45g_signed.stm32` — our OBL, output of
`make -C lib/main/STM32/n6_obl signed`.
- Optionally `betaflight_<version>_STM32N657_<config>.bin` — your BF
build, if you're flashing OBL + BF together. Skip when you want
only the OBL written and the BF slot zeroed (next section).
## Recovery image variants
| Variant | What lands in nor0 | When to use |
|------------------------|--------------------------------------------------------------|-------------|
| **OBL + BF combined** | OBL at `0x0..0x87A0`, zeros to `0x100000`, BF at `0x100000+` | Normal flash after both binaries are ready. |
| **OBL only, BF erased**| OBL at `0x0..0x87A0`, zeros from end-of-OBL through `0x200000` | After an OBL change that may make BF crash on first boot (e.g. when OBL now transfers to BF in NS state). The empty BF slot fails OBL's vector-table validity check, so the next boot lands straight in OBL DFU recovery — no IWDG round-trip needed. |
### Combined image construction (OBL + BF)
```bash
cp lib/main/STM32/n6_obl/prebuilt/obl_mx66uw1g45g_signed.stm32 /tmp/obl_bf_combined.bin
truncate -s 1048576 /tmp/obl_bf_combined.bin
cat obj/betaflight_*_OPENN657V1.bin >> /tmp/obl_bf_combined.bin
```
Layout to use: `lib/main/STM32/n6_fsbl/FlashLayout_OBL.tsv`.
### OBL-only image construction (BF slot erased)
```bash
install -m 0644 lib/main/STM32/n6_obl/prebuilt/obl_mx66uw1g45g_signed.stm32 \
lib/main/STM32/n6_obl/prebuilt/obl_only_combined.bin
truncate -s 2097152 lib/main/STM32/n6_obl/prebuilt/obl_only_combined.bin
```
The 2 MiB size covers both the 1 MiB OBL slot and the 1 MiB BF slot with
a single contiguous write at nor0 offset 0; everything past the OBL
payload is zero from `truncate`, so the BF slot lands erased.
Layout to use: `lib/main/STM32/n6_fsbl/FlashLayout_OBL_only.tsv`.
## TSV layout
Save as `Unbricking.tsv` next to `OpenBootloader_STM32N6570-DK-trusted.stm32`
and `MX66UW1G45G_STM32N6570-DK.bin`, then edit the two
`<...your-path...>` lines to point at your OBL and BF artefacts.
```tsv
#Opt Id Name Type IP Offset Binary
P 0x1 fsbl-openbl Binary none 0x0 OpenBootloader_STM32N6570-DK-trusted.stm32
P 0x3 fsbl-extfl Binary none 0x0 MX66UW1G45G_STM32N6570-DK.bin
P 0x2 obl-app Binary nor0 0x0 <path/to>/obl_mx66uw1g45g_signed.stm32
P 0x4 bf-app Binary nor0 0x100000 <path/to>/obj/betaflight_<version>_STM32N657_<config>.bin
```
Columns:
- `Opt`: `P` = program (write); `PE` = program + erase first.
- `Id`: ST's partition ID. The OpenBootloader recognises:
- `0x1` → @FSBL: stage a signed FSBL image to AXISRAM2.
- `0x2` → nor0 offset 0 (OBL slot, signed `.stm32` artefact).
- `0x3` → @External memory loader: stage the XSPI driver to RAM.
- `0x4` → nor0 offset 0x100000 (BF slot).
- `Name`: free-text label, shown in CubeProg output.
- `Type`: `Binary` for raw bytes; `Force not used` to skip a row.
- `IP`: target memory — `none` means "load to RAM" (used by Id 0x1
and 0x3); `nor0` is the on-board XSPI flash.
- `Offset`: byte offset inside the target memory.
- `Binary`: path (relative to the TSV) of the file to write.
## Procedure
1. Power cycle the board.
2. Slide **BOOT0** to **DEV** (toward the edge of the board on the
N6570-DK; the boot ROM samples this pin at reset and enters system
DFU when high).
3. Press the reset button. `lsusb` should now show:
```
Bus xxx Device xxx: ID 0483:df11 STMicroelectronics STM Device in DFU Mode
```
4. Run CubeProg against the TSV (substitute `FlashLayout_OBL_only.tsv`
if you want OBL written and the BF slot erased):
```bash
~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer_CLI \
-c port=USB1 -d Unbricking.tsv
```
You'll see four phases scroll past — `fsbl-openbl` upload, then a
re-enumeration as the OpenBootloader starts, then `fsbl-extfl`
upload, then `obl-app` and `bf-app` writes to nor0.
5. Slide **BOOT0** back to **USER**.
6. Press reset. The chip boots from XSPI into our OBL → BF.
## Verifying
After the reset in step 6:
```bash
lsusb | grep 0483
# Expect:
# Bus xxx Device xxx: ID 0483:3754 STMicroelectronics STLINK-V3
# Bus xxx Device xxx: ID 0483:5740 STMicroelectronics Virtual COM Port
```
`/dev/ttyACM1` is the BF VCP. Send `#` + LF to escape MSP into the BF
CLI; `version` should report the build you just flashed.
## Footnotes
- `STM32_Programmer_CLI -el .stldr -w` with the `.stldr` form of the
XSPI driver SIGSEGVs on Linux at least up to v2.22.0; the TSV path
works around that.
- `port=USB1` selects the first USB DFU device; if you have several DFU
devices attached, add `sn=<serial>` to disambiguate. List with
`STM32_Programmer_CLI --list usb`.
- The TSV's relative-path resolution is done from the TSV's own
directory, which is why ST's two helper binaries are kept alongside
it. OBL and BF artefact paths can be absolute or relative to that
same directory.