Document Si4684 blob procurement and enforce CI policy.
Expand local-only firmware README, add check_si4684_blobs.py to verify gitignore and clean history, and gate main with a new si4684-blobs workflow job. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -44,3 +44,15 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Check manual class sync
|
- name: Check manual class sync
|
||||||
run: python3 tools/check-manual-sync.py --src components --manual docs/manual
|
run: python3 tools/check-manual-sync.py --src components --manual docs/manual
|
||||||
|
|
||||||
|
si4684-blobs:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: Software
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Check Si4684 blob policy
|
||||||
|
run: python3 tools/check_si4684_blobs.py
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ Vertical slices landed on `main` (newest first):
|
|||||||
| **0.5–0.6** | ADAU1701 runtime EQ/mixer, Si4684 tuning & DAB service list, BT1035 driver |
|
| **0.5–0.6** | ADAU1701 runtime EQ/mixer, Si4684 tuning & DAB service list, BT1035 driver |
|
||||||
| **0.3–0.4** | Secure store, Wi-Fi provisioning, companion-chip boot, walking skeleton |
|
| **0.3–0.4** | Secure store, Wi-Fi provisioning, companion-chip boot, walking skeleton |
|
||||||
|
|
||||||
**Next up** ([`Software/docs/TODO.md`](Software/docs/TODO.md)): Si4684 blob procurement docs (T7), NVS/flash encryption (T8).
|
**Next up** ([`Software/docs/TODO.md`](Software/docs/TODO.md)): NVS/flash encryption (T8).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,16 @@ Binary and SigmaStudio exports loaded by the ESP32 at every boot.
|
|||||||
|
|
||||||
## Si4684 blobs
|
## Si4684 blobs
|
||||||
|
|
||||||
`rom_patch_016.bin` and `dab_firmware.bin` are extracted from the
|
Proprietary Skyworks images — **local only**, gitignored (`*.bin`). See
|
||||||
[PE5PVB SI4684-DAB-Receiver](https://github.com/PE5PVB/SI4684-DAB-Receiver)
|
[`Si4684-Firmware/README.md`](Si4684-Firmware/README.md) for procurement and
|
||||||
project. `fm_firmware.bin` comes from the Skyworks Si4684 eval firmware pack
|
legal notes. Populate with:
|
||||||
(see `tools/fetch_si4684_firmware.py --si46xx-dir`).
|
|
||||||
|
```bash
|
||||||
|
cd Software
|
||||||
|
python3 tools/fetch_si4684_firmware.py --dab-only
|
||||||
|
python3 tools/fetch_si4684_firmware.py --si46xx-dir /path/to/si46xx_firmware
|
||||||
|
python3 tools/check_si4684_blobs.py
|
||||||
|
```
|
||||||
|
|
||||||
## ADAU1701 export
|
## ADAU1701 export
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +1,89 @@
|
|||||||
# Si4684 firmware images
|
# Si4684 firmware images (local only — not in git)
|
||||||
|
|
||||||
|
Skyworks Si4684 application firmware is **proprietary**. This directory holds
|
||||||
|
the three binary blobs your build embeds via `HOST_LOAD`; they must **never**
|
||||||
|
be committed to the public repository.
|
||||||
|
|
||||||
| File | Size (typ.) | Role |
|
| File | Size (typ.) | Role |
|
||||||
|------|-------------|------|
|
|------|-------------|------|
|
||||||
| `rom_patch_016.bin` | 5796 | ROM patch / bootloader helper (HOST_LOAD before main image) |
|
| `rom_patch_016.bin` | 5796 B | ROM patch / bootloader helper (HOST_LOAD before main image) |
|
||||||
| `dab_firmware.bin` | ~517 KB | DAB+ application image (PE5PVB / Skyworks BIF) |
|
| `dab_firmware.bin` | ~517 KB | DAB+ application image (PE5PVB / Skyworks BIF) |
|
||||||
| `fm_firmware.bin` | ~530 KB | FM application image (Skyworks `fm_radio_5_1_0.bin`, AN649 A10) |
|
| `fm_firmware.bin` | ~530 KB | FM application image (Skyworks `fm_radio_5_1_0.bin`, AN649 A10) |
|
||||||
|
|
||||||
Boot sequence: AN649 — POWER_UP → LOAD_INIT → HOST_LOAD(patch) → LOAD_INIT →
|
Boot sequence (AN649): POWER_UP → LOAD_INIT → HOST_LOAD(patch) → LOAD_INIT →
|
||||||
HOST_LOAD(image) → BOOT. DAB and FM use the same patch; only the application
|
HOST_LOAD(image) → BOOT. DAB and FM share the same patch; only the application
|
||||||
image differs.
|
image differs.
|
||||||
|
|
||||||
## Refresh blobs
|
## Legal / redistribution
|
||||||
|
|
||||||
|
- **Do not** commit `*.bin` files here, attach them to GitHub releases, or
|
||||||
|
redistribute them with this open-source tree.
|
||||||
|
- DAB images extracted from [PE5PVB/SI4684-DAB-Receiver](https://github.com/PE5PVB/SI4684-DAB-Receiver) are community-sourced; FM images come from the
|
||||||
|
Skyworks evaluation package or equivalent local sources (see below).
|
||||||
|
- Keep blobs on your machine only. CI verifies they are gitignored and absent
|
||||||
|
from history (`python3 tools/check_si4684_blobs.py`).
|
||||||
|
|
||||||
|
## Before you build
|
||||||
|
|
||||||
|
From `Software/`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# DAB + patch from PE5PVB GitHub (always safe to re-run):
|
python3 tools/fetch_si4684_firmware.py --dab-only # patch + DAB
|
||||||
python3 tools/fetch_si4684_firmware.py --dab-only
|
python3 tools/fetch_si4684_firmware.py --si46xx-dir /path # add FM (see below)
|
||||||
|
ls -la Firmware/Si4684-Firmware/*.bin # expect 3 files
|
||||||
# FM from Skyworks eval / dabpi si46xx_firmware folder:
|
|
||||||
python3 tools/fetch_si4684_firmware.py --si46xx-dir /path/to/si46xx_firmware
|
|
||||||
|
|
||||||
# FM extracted from uGreen DABBoard radio_cli (Files_v16.zip from ugreen.eu/downloads):
|
|
||||||
python3 tools/fetch_si4684_firmware.py --from-ugreen-radio-cli ~/Downloads/Files_v16.zip
|
|
||||||
|
|
||||||
# Patch + DAB + FM entirely from uGreen radio_cli (overrides PE5PVB DAB):
|
|
||||||
python3 tools/fetch_si4684_firmware.py --from-ugreen-radio-cli ~/Downloads/Files_v16.zip --ugreen-all
|
|
||||||
|
|
||||||
# FM extracted from a full SPI flash dump (TechniSat layout, dirb.me tech wiki):
|
|
||||||
python3 tools/fetch_si4684_firmware.py --flash-dump technisat_spi.bin
|
|
||||||
```
|
```
|
||||||
|
|
||||||
FM images are **not** redistributed with PE5PVB (DAB-only project). Obtain
|
`idf.py build` fails at link/embed time if blobs are missing.
|
||||||
`fm_radio_5_1_0.bin` from the Si4684 evaluation package (AN649 table 1),
|
|
||||||
community `si46xx_firmware/` folders used by [teknoid/dabpi](https://github.com/teknoid/dabpi),
|
|
||||||
or extract from a uGreen [DABBoard](https://ugreen.eu/downloads/) `radio_cli`
|
|
||||||
binary (proprietary — keep local, do not commit to public git).
|
|
||||||
|
|
||||||
Low-level conversion helper:
|
## Obtain images locally
|
||||||
|
|
||||||
|
### Patch + DAB (automated, network)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 tools/extract_si4684_blob.py --copy /path/to/fm_radio_5_1_0.bin \\
|
cd Software
|
||||||
|
python3 tools/fetch_si4684_firmware.py --dab-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Clones PE5PVB/SI4684-DAB-Receiver and writes `rom_patch_016.bin` and
|
||||||
|
`dab_firmware.bin`.
|
||||||
|
|
||||||
|
### FM image (manual source — pick one)
|
||||||
|
|
||||||
|
FM is **not** shipped with PE5PVB. Supply one of:
|
||||||
|
|
||||||
|
| Source | Command |
|
||||||
|
|--------|---------|
|
||||||
|
| Skyworks eval / dabpi `si46xx_firmware/` | `python3 tools/fetch_si4684_firmware.py --si46xx-dir /path/to/si46xx_firmware` |
|
||||||
|
| uGreen DABBoard `Files_v16.zip` | `python3 tools/fetch_si4684_firmware.py --from-ugreen-radio-cli ~/Downloads/Files_v16.zip` |
|
||||||
|
| Full SPI flash dump (TechniSat layout) | `python3 tools/fetch_si4684_firmware.py --flash-dump technisat_spi.bin` |
|
||||||
|
|
||||||
|
Candidate FM filenames (AN649 / community): `fm_radio_5_1_0.bin`,
|
||||||
|
`fm_radio_5_0_9.bin`, `fmhd_radio_5_1_0.bin`, `fmhd_radio_5_0_4.bin`.
|
||||||
|
|
||||||
|
Manual copy helper:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/extract_si4684_blob.py --copy /path/to/fm_radio_5_1_0.bin \
|
||||||
--out Firmware/Si4684-Firmware/fm_firmware.bin
|
--out Firmware/Si4684-Firmware/fm_firmware.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### All three from uGreen radio_cli
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 tools/fetch_si4684_firmware.py --from-ugreen-radio-cli ~/Downloads/Files_v16.zip --ugreen-all
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verify your checkout
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd Software
|
||||||
|
python3 tools/check_si4684_blobs.py # must exit 0
|
||||||
|
git ls-files 'Firmware/Si4684-Firmware/*.bin' # must print nothing
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Skyworks **AN649** — Si4684 programming API and boot flow
|
||||||
|
- `tools/fetch_si4684_firmware.py` — fetch/extract orchestration
|
||||||
|
- `tools/extract_si4684_blob.py` — header/array → raw `.bin`
|
||||||
|
- `docs/manual/ch-si4684.tex` — driver boot integration in DigiRadio
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ Documentation gates (must exit 0 before merging; also enforced in CI):
|
|||||||
```bash
|
```bash
|
||||||
doxygen Doxyfile
|
doxygen Doxyfile
|
||||||
python3 tools/check-manual-sync.py
|
python3 tools/check-manual-sync.py
|
||||||
|
python3 tools/check_si4684_blobs.py
|
||||||
python3 tools/gzip-www.sh # after editing components/net/www/index.html
|
python3 tools/gzip-www.sh # after editing components/net/www/index.html
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+4
-12
@@ -69,18 +69,10 @@ embedded gzip blob. No debug routes in `SetupWebServer`.
|
|||||||
|
|
||||||
## P3 — Procurement & hardening
|
## P3 — Procurement & hardening
|
||||||
|
|
||||||
### T7. Si4684 firmware blob strategy (legal)
|
### T7. Si4684 firmware blob strategy (legal) — **DONE (fw 0.8.2)**
|
||||||
**Why:** the Si4684 images are proprietary (Skyworks). Tools to fetch/
|
`Firmware/Si4684-Firmware/*.bin` gitignored; no blobs in git history.
|
||||||
extract exist under `tools/`, but the `.bin` images must **not** be
|
Procurement documented in `Si4684-Firmware/README.md`; CI job
|
||||||
committed to the public repo.
|
`si4684-blobs` runs `tools/check_si4684_blobs.py`.
|
||||||
**What:**
|
|
||||||
- Confirm `*.bin` (patch, FM, DAB images) are in `.gitignore` and absent
|
|
||||||
from git history.
|
|
||||||
- Document in `Software/Firmware/Si4684-Firmware/README.md` how a builder
|
|
||||||
obtains the images locally (tools + AN649 reference), without
|
|
||||||
redistributing proprietary binaries.
|
|
||||||
**Done when:** no proprietary blob is tracked; the procurement path is
|
|
||||||
documented and reproducible.
|
|
||||||
|
|
||||||
### T8. Flash/NVS encryption enablement
|
### T8. Flash/NVS encryption enablement
|
||||||
**Why:** secure storage holds Wi-Fi and user credentials; encryption at
|
**Why:** secure storage holds Wi-Fi and user credentials; encryption at
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""check_si4684_blobs.py — CI gate: no proprietary Si4684 blobs in git.
|
||||||
|
|
||||||
|
DigiRadio firmware — https://github.com/manvalan/DigiRadio
|
||||||
|
|
||||||
|
Copyright 2026 Michele Bigi
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
Skyworks / uGreen Si4684 application images must live only on the builder's
|
||||||
|
machine under Firmware/Si4684-Firmware/*.bin (gitignored). This script fails
|
||||||
|
if any such blob is tracked, appears in git history, or is missing from
|
||||||
|
.gitignore.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
FW_DIR = ROOT / "Firmware" / "Si4684-Firmware"
|
||||||
|
GITIGNORE = ROOT / ".gitignore"
|
||||||
|
IGNORE_LINE = "Firmware/Si4684-Firmware/*.bin"
|
||||||
|
|
||||||
|
|
||||||
|
def git(*args: str) -> str:
|
||||||
|
result = subprocess.run(
|
||||||
|
["git", *args],
|
||||||
|
cwd=ROOT.parent,
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
return result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def check_gitignore() -> list[str]:
|
||||||
|
errors: list[str] = []
|
||||||
|
if not GITIGNORE.is_file():
|
||||||
|
errors.append(f"missing {GITIGNORE.relative_to(ROOT)}")
|
||||||
|
return errors
|
||||||
|
text = GITIGNORE.read_text(encoding="utf-8")
|
||||||
|
if IGNORE_LINE not in text:
|
||||||
|
errors.append(
|
||||||
|
f".gitignore must contain {IGNORE_LINE!r} "
|
||||||
|
"(proprietary Si4684 blobs)"
|
||||||
|
)
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def check_tracked_bins() -> list[str]:
|
||||||
|
out = git("ls-files", "--", "Software/Firmware/Si4684-Firmware/*.bin")
|
||||||
|
tracked = [line for line in out.splitlines() if line.strip()]
|
||||||
|
if not tracked:
|
||||||
|
return []
|
||||||
|
return [
|
||||||
|
"tracked Si4684 blob(s) in git index (remove and keep local only): "
|
||||||
|
+ ", ".join(tracked)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def check_history() -> list[str]:
|
||||||
|
out = git(
|
||||||
|
"log",
|
||||||
|
"--all",
|
||||||
|
"--oneline",
|
||||||
|
"--",
|
||||||
|
"Software/Firmware/Si4684-Firmware/*.bin",
|
||||||
|
)
|
||||||
|
lines = [line for line in out.splitlines() if line.strip()]
|
||||||
|
if not lines:
|
||||||
|
return []
|
||||||
|
return [
|
||||||
|
"Si4684 .bin file(s) found in git history — "
|
||||||
|
"history rewrite required before publishing: "
|
||||||
|
+ "; ".join(lines[:5])
|
||||||
|
+ (" …" if len(lines) > 5 else "")
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Ensure Si4684 firmware blobs are not in git."
|
||||||
|
)
|
||||||
|
parser.parse_args()
|
||||||
|
errors = check_gitignore() + check_tracked_bins() + check_history()
|
||||||
|
if errors:
|
||||||
|
for err in errors:
|
||||||
|
print(f"check_si4684_blobs: error: {err}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
print(
|
||||||
|
"Si4684 blob policy OK: "
|
||||||
|
f"{IGNORE_LINE} gitignored, no tracked blobs, clean history."
|
||||||
|
)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user