Files
radar_system/device_firmware/multi_libreVNA_firmware/reproduce
AyzenandClaude Opus 5 dfb285ab93 add windows install/build scripts for per-point switching
Скрипты, которыми правки ставятся в дерево LibreVNA на сборочной машине и
собирается прошивка MCU мастера её штатным тулчейном (STM32CubeIDE 1.17.0,
gcc 12.3.1). Оригиналы шести изменённых файлов сохраняются в backup_original,
так что откат — обратный xcopy.

Проверено на месте: все 7 файлов легли побайтово (сверил sha256 каждого),
прошивка мастера собралась, эталон предыдущей прошивки остался цел в
extracted/master_stm32.bin.

Битстрим FPGA этими скриптами не собирается — нужна ISE 14.7 в виртуалке,
процедура описана в README.txt и per_point_switching.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 12:48:52 +03:00
..
2026-09-09 21:08:02 +03:00

Воспроизведение прошивок LibreVNA

Здесь всё, что нужно, чтобы пересобрать прошивки из device_firmware/ с нуля. Проект лежит целиком — не патч, а полное дерево с уже внесёнными доработками.

Исходники опережают бинарники. В дерево внесено переключение стимула внутри частотной точки (см. ../../per_point_switching.md), а лежащие рядом .vnafw, extracted/ и build*/ — это ПРЕДЫДУЩАЯ прошивка, собранная до этой доработки и сейчас залитая в приборы. Поэтому:

  • ./build.sh без аргументов по-прежнему даёт побайтовое совпадение — он только переупаковывает готовые .bin, не трогая исходники;
  • ./build.sh --stm32 и любая сборка FPGA дадут другие бинарники, уже с новой логикой — это ожидаемо, а не поломка;
  • исходники, из которых собраны текущие .vnafw, лежат в git-коммите d2338ff.

После сборки и проверки на железе обновите .vnafw, extracted/, build*/ и SHA256SUMS, и этот блок можно будет убрать.

Что где

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.

Разложить готовый файл на части:

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

Аппаратный триггер и external-LO slave — 13 файлов (не 12: в списке не значился PC_Application/LibreVNA-GUI/Traces/trace.cpp, правка в GUI, к прошивкам отношения не имеющая). Переключение стимула внутри точки добавило ещё 5 изменённых файлов и один новый. Всё остальное дерево совпадает с апстримом байт в байт.

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.

Переключение стимула внутри частотной точки

Внесено позже остального, бинарников рядом ещё нет (см. блок в начале файла). Полное описание — ../../per_point_switching.md.

FPGA/VNA/Sweep.vhd — порт излучает не в одной стадии, а в БЛОКЕ подряд идущих: младшие SUBSTAGE_BITS бит счётчика стадий стали положением выходного ключа, старшие выбирают порт. Вынесено в функцию port_excites. Значение порт-стадии выше последней никогда не совпадает — так хост глушит излучение слейвов, посылая им 7.

FPGA/VNA/SPIConfig.vhd, FPGA/VNA/top.vhd — новый вход SUBSTAGE_BITS из свободных битов 8:6 регистра SweepSetup (адрес 6) и его проброс в Sweep.

Application/Drivers/FPGA/FPGA.{hpp,cpp} — у SetupSweep добавлен параметр substage_bits со значением по умолчанию 0, чтобы вызовы из ручного режима и анализатора спектра не менялись.

Application/VNA.cpp — ширина под-стадии берётся из port3Stage: у этого железа нет порта 3, поле свободно, и его переиспользование не меняет формат пакета.

При SUBSTAGE_BITS = 0 логика бит в бит совпадает с апстримом — это проверено симуляцией.

Новый файл FPGA/VNA/Test_Sweep.vhd — самопроверяющийся тестбенч на четыре сценария (сток, два положения ключа, приёмник без излучения, четыре положения). В проект ISE не добавлен, на сборку не влияет. Запуск любым VHDL-симулятором:

ghdl -a --std=93 Sweep.vhd Test_Sweep.vhd && ghdl -r --std=93 Test_Sweep

Прочее

AssembleFirmware.py — переписан: добавлены --bitstream, --mcu, --output (в апстриме пути зашиты жёстко). Формат выходного файла не менялся.

Пересборка

Только упаковка .vnafw — самое быстрое

cd device_firmware/reproduce
./build.sh

Берёт готовые .bin из LibreVNA/ и собирает обе прошивки в out/, затем сверяет с эталонами. Даёт побайтовое совпадение с device_firmware/*.vnafw — проверено.

STM32 из исходников

./build.sh --stm32

или вручную:

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.

Проверка целостности

cd device_firmware/reproduce
sha256sum -c SHA256SUMS