added librevna firmware reproduce kit

Полное дерево LibreVNA v1.6.5 с доработками master/slave, эталонные битстримы
и прошивки STM32, упаковщик .vnafw. Проверено: build.sh пересобирает обе
прошивки побайтово идентично лежащим рядом .vnafw.

Мастер-битстрим (top_master.bin / extracted/master_fpga.bin) больше нигде не
существует — place&route в ISE недетерминирован, из исходников он не
восстанавливается.

Положено в multi_libreVNA_firmware/reproduce, а не в device_firmware/reproduce
как сказано в README комплекта: SHA256SUMS и build.sh ссылаются на
../combined.vnafw, а .vnafw лежат здесь.

Корневые правила .gitignore build*/build/ выбрасывали 482 файла, включая сам
build.sh и эталонные прошивки STM32 из SHA256SUMS — дописано разыгноривание.
Оставшиеся 7 файлов перебивал вложенный апстримный .gitignore (более глубокий
имеет приоритет), они добавлены force-add'ом. Промежуточные .o/.d/.su из
build-каталогов убраны, .bin/.elf/.hex/.map оставлены.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ayzen
2026-09-09 21:08:02 +03:00
co-authored by Claude Opus 5
parent 7997abe2d9
commit d2338ff10c
1241 changed files with 645541 additions and 1 deletions
@@ -0,0 +1,205 @@
# Воспроизведение прошивок LibreVNA
Здесь всё, что нужно, чтобы пересобрать прошивки из [`device_firmware/`](../) с нуля.
Проект лежит целиком — не патч, а полное дерево с уже внесёнными доработками.
## Что где
```
reproduce/
├── LibreVNA/ полный проект: апстрим v1.6.5 + доработки master/slave
│ ├── Software/VNA_embedded/ прошивка STM32G431CBUx (CubeIDE + Makefile)
│ │ ├── build/ собранный мастер (VNA_embedded.bin/.elf/.map)
│ │ └── build_external_lo_slave/ собранный slave
│ ├── FPGA/VNA/ VHDL-проект под Xilinx ISE 14.7
│ │ ├── top_master.bin битстрим мастера ← из combined.vnafw
│ │ ├── top_external_lo_slave.bin битстрим slave
│ │ └── top.bin СТОКОВЫЙ апстримный, не наш (см. ниже)
│ └── AssembleFirmware.py упаковщик .vnafw
├── extracted/ секции, вынутые из готовых .vnafw
├── build.sh пересборка + сверка с эталоном
└── SHA256SUMS эталонные хеши (sha256sum -c SHA256SUMS)
```
Из `LibreVNA/` исключены только `.git` (снапшот с одним коммитом `init`, истории правок
в нём нет) и `.venv`.
## Железо и версии
| | |
|---|---|
| MCU | STM32G431CBUx, Cortex-M4, 128 КБ флеш / 32 КБ RAM |
| Линкер | `STM32G431CBUX_FLASH.ld`, образ с `0x08000000` |
| FPGA | Xilinx, битстрим 341 712 Б, проект под ISE 14.7 |
| Версия ПО | FW 1.6.5, `HW_REVISION='B'` (задано в Makefile) |
| Тулчейн STM32 | STM32CubeIDE 1.17.0, gcc arm-none-eabi **12.3.1** |
| Апстрим | github.com/jankae/LibreVNA, тег **v1.6.5** |
## Две сборки
Различие мастер/slave — **один флаг**, отдельных веток кода нет.
| | STM32 | FPGA |
|---|---|---|
| мастер | `make` (`EXTERNAL_MASTER_LO_SLAVE=0`) | проект `VNA.xise` → `BuildConfig.vhd` (`false`) |
| slave | `make EXTERNAL_MASTER_LO_SLAVE=1` | `VNA_external_lo_slave.xise` → `BuildConfig_external_lo_slave.vhd` (`true`) |
Два `.xise` отличаются ровно одной строкой — каким из двух `BuildConfig` подключаться.
## Формат .vnafw
Заголовок 24 байта, little-endian (см. `AssembleFirmware.py`):
| Смещение | Поле |
|---|---|
| 0x00 | магия `VNA!` |
| 0x04 | смещение FPGA-битстрима (всегда 24) |
| 0x08 | размер FPGA-битстрима |
| 0x0C | смещение прошивки MCU (= 24 + размер FPGA) |
| 0x10 | размер прошивки MCU |
| 0x14 | CRC32 по (битстрим + прошивка MCU), начальное значение `0xFFFFFFFF` |
Дальше подряд битстрим и прошивка MCU, хвост добит нулями до кратности 256.
Разложить готовый файл на части:
```bash
tail -c +25 combined.vnafw | head -c 341712 > top.bin # FPGA
tail -c +341737 combined.vnafw | head -c 85004 > VNA_embedded.bin # STM32
```
## Отличия от апстрима v1.6.5
Всего 12 файлов. Всё остальное дерево совпадает с апстримом байт в байт.
### STM32 — поддержка аппаратного триггера (это и есть съём без USB)
**`Application/Trigger.cpp`** (+45/−3) — главное изменение, работает в **обеих** сборках.
В апстриме `Trigger::Init()` только вешал EXTI на `FPGA_TRIGGER_OUT`, а `FPGA_TRIGGER_IN`
всегда оставался выходом STM (триггер эмулировался по USB). Добавлены
`ConfigureInputPin()` / `ConfigureOutputMonitorPin()`, которые в режиме `Mode::Trigger`
(`syncMode = 3`) убирают STM с обеих линий:
* `FPGA_TRIGGER_IN` → вход без подтяжки: линию гонит внешняя триггер-петля, а не STM;
* `FPGA_TRIGGER_OUT` → вход без подтяжки, EXTI снимается: FPGA драйвит линию напрямую
на второе устройство.
В остальных режимах поведение прежнее. Конфигурация пинов теперь вызывается и из
`Trigger::SetMode()`, а не только при инициализации.
**`Application/Hardware.cpp`** (+29/−2) — в `HW::SetIdle()` вместо `Trigger::SetInput(false)`
теперь `Trigger::SetMode(Trigger::Mode::Off)` (безусловно, обе сборки). Остальное под
`#if EXTERNAL_MASTER_LO_SLAVE`: гасится Si5351-канал LO1, LO1 не инициализируется как PLL,
статус LO1 всегда «locked», температура LO1 = 0.
**`Application/VNA.cpp`** (+33/−6) — вынесены `UpdateLO1ReferenceClock()` /
`DisableLO1ReferenceClock()`; в slave-сборке `VNA::Setup()` отклоняет свип, если
`syncMode != Trigger` или `syncMaster != 0`. Плюс безусловный багфикс: клампы `points` и
`dwell_time` применялись к старому `settings` вместо нового `s`.
**`Application/App.cpp`** (+28/−1) — только под `#if EXTERNAL_MASTER_LO_SLAVE`: slave
отвечает `Nack` на `ManualControl`, `Generator`, `SpectrumAnalyzerSettings` и на свипы,
не проходящие `ExternalLOSlaveSweepSupported()`. Также `SweepSettings` теперь отвечает
`Nack`, если `VNA::Setup()` вернул false.
**`Application/Hardware.hpp`** (+3) — дефолт `EXTERNAL_MASTER_LO_SLAVE 0`.
**`Makefile`** (+2) — `EXTERNAL_MASTER_LO_SLAVE ?= 0` и проброс в `-D`.
### FPGA — глушение LO1 в slave
**`FPGA/VNA/top.vhd`** (+14/−8) — подключён `use work.BuildConfig.all`, заведены сигналы
`SPI_LO1_CE` / `SPI_LO1_RF_EN`, и под `EXTERNAL_MASTER_LO_SLAVE` глушатся `LO1_RF_EN`,
`LO1_CE`, `LO1_CLK`, `LO1_MOSI`, `LO1_LE`; `plls_locked` перестаёт ждать захвата LO,
`lo_unlocked` фиксируется в `'0'`.
Все правки — под этим флагом. **При `false` логика полностью совпадает с апстримом.**
Новые файлы: `BuildConfig.vhd`, `BuildConfig_external_lo_slave.vhd`,
`VNA_external_lo_slave.xise`; в `VNA.xise` добавлена ссылка на `BuildConfig.vhd`.
### Прочее
**`AssembleFirmware.py`** — переписан: добавлены `--bitstream`, `--mcu`, `--output`
(в апстриме пути зашиты жёстко). Формат выходного файла не менялся.
## Пересборка
### Только упаковка .vnafw — самое быстрое
```bash
cd device_firmware/reproduce
./build.sh
```
Берёт готовые `.bin` из `LibreVNA/` и собирает обе прошивки в `out/`, затем сверяет
с эталонами. **Даёт побайтовое совпадение** с `device_firmware/*.vnafw` — проверено.
### STM32 из исходников
```bash
./build.sh --stm32
```
или вручную:
```bash
cd LibreVNA/Software/VNA_embedded
BIN='C:/ST/STM32CubeIDE_1.17.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.12.3.rel1.win32_1.1.0.202410251130/tools/bin'
make BINPATH="$BIN" -j4 # мастер
make BINPATH="$BIN" -j4 EXTERNAL_MASTER_LO_SLAVE=1 BUILD_DIR=build_external_lo_slave
```
`BINPATH` обязателен: по умолчанию в Makefile стоит `/usr/bin`, под Windows это не сработает.
`make.exe` берите из CubeIDE (`...externaltools.make.win32.../tools/bin`).
### FPGA — только вручную, в Xilinx ISE 14.7
ISE стоит в виртуалке VirtualBox `ISE_14.7_VIRTUAL_MACHINE`; её общая папка — хостовая
`C:\shared`, внутри гостя это `/home/ise/shared`.
1. Скопировать `LibreVNA/FPGA` в `C:\shared\LibreVNA\FPGA`.
2. В ISE открыть нужный проект:
* мастер — `/home/ise/shared/LibreVNA/FPGA/VNA/VNA.xise`
* slave — `.../VNA_external_lo_slave.xise`
3. Process → **Generate Programming File**.
4. Результат — `top.bit` и `top.bin` в каталоге проекта.
Оба проекта пишут в один и тот же `top.bin`, поэтому **последняя сборка затирает
предыдущую** — забирайте файл сразу и переименовывайте (`top_master.bin` /
`top_external_lo_slave.bin`). Именно так и потерялся исходный мастер-битстрим: slave-сборка
от 20.04 перезаписала его.
## Что воспроизводится побайтово
| | |
|---|---|
| `.vnafw` из готовых `.bin` | **да** — проверено, обе прошивки совпали с `device_firmware/` |
| STM32 из исходников | **да** — проверено, обе сборки (мастер `ba729999…`, slave `56654a03…`) совпали побайтово на тулчейне CubeIDE 1.17.0 / gcc 12.3.1 |
| FPGA-битстрим из ISE | **нет** — place & route недетерминирован, плюс timestamp внутри битстрима. Логика идентична, файл будет другой |
Поэтому мастер-битстрим сохранён отдельно: `extracted/master_fpga.bin` и
`LibreVNA/FPGA/VNA/top_master.bin`. Больше **нигде** на машине его нет — он существовал
только внутри `combined.vnafw`.
Внимание: `LibreVNA/FPGA/VNA/top.bin` — это **стоковый апстримный** битстрим (тот же, что
в официальном релизе v1.6.5), а не наш мастер. Не перепутайте при упаковке.
## Откуда что собрано
| `.vnafw` | FPGA-битстрим | STM32 |
|---|---|---|
| `combined.vnafw` | `top_master.bin` (только из этого файла) | `build/VNA_embedded.bin` |
| `combined_external_lo_slave.vnafw` | `top_external_lo_slave.bin` | `build_external_lo_slave/VNA_embedded.bin` |
## Прошивка устройства
Штатным LibreVNA-GUI: **Device → Firmware Update**, скармливать `.vnafw` целиком —
GUI сам разложит битстрим и прошивку MCU. Отдельный `master_stm32.bin` нужен, только
если шить STM напрямую через ST-Link/DFU на `0x08000000`.
## Проверка целостности
```bash
cd device_firmware/reproduce
sha256sum -c SHA256SUMS
```