Прошивка моста BL616 для Tang Primer 25K и программатор TangProgrammer
- src/: прошивка встроенного отладчика BL616 — составное USB-устройство 1209:C0CA: DirtyJTAG v3 (WinUSB через MS OS 2.0) + CDC-ACM UART к FPGA B3/C3; UART до 20 Мбод на DMA, JTAG до 30 МГц через аппаратный SPI; - bin/: загрузчик Sipeed (0x0) и штатная прошивка 2025030317 для отката; - gui/: TangProgrammer.exe (C# WinForms, .NET Framework 4) — загрузка FPGA в SRAM и во флеш-память, копия и стирание флеш-памяти FPGA, прошивка моста; светлая и тёмная тема; - scripts/: setup, build, flash, build_gui, make_portable, а также make_release и publish_release для релизов Gitea; - fpga_test/, tests/: тестовые проекты Gowin (loopback, stream) и тесты UART на Python; - tools/openFPGALoader/: openFPGALoader 1.1.1 для Windows x64.
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
# Прошивка отладчика BL616 для Tang Primer 25K
|
||||
|
||||
Замена штатной прошивки встроенного отладчика (BL616) на плате **Sipeed Tang
|
||||
Primer 25K Dock**. Вместо эмуляции FT2232 плата становится составным
|
||||
USB-устройством из двух независимых функций:
|
||||
|
||||
| Функция | Что это | Драйвер Windows |
|
||||
|---|---|---|
|
||||
| **JTAG** | DirtyJTAG v3 (`1209:C0CA`, интерфейс 0) для `openFPGALoader -c dirtyJtag` | WinUSB, ставится сам (MS OS 2.0) — Zadig не нужен |
|
||||
| **UART** | CDC-ACM, обычный COM-порт к пинам FPGA **B3/C3** | встроенный `usbser.sys` |
|
||||
|
||||
Оба работают одновременно: можно грузить битстрим, не закрывая терминал.
|
||||
|
||||
## Скачать
|
||||
|
||||
Готовые файлы — в [релизах](http://gitea.vector.ru/Gromov_IA/BL616-firmware/releases):
|
||||
|
||||
| Файл | Что это |
|
||||
|---|---|
|
||||
| `TangProgrammer-<версия>-win64.zip` | **программатор с окном** — распаковать и запустить, внутри всё нужное (openFPGALoader, BLFlashCommand, прошивки моста) |
|
||||
| `TangProgrammer.exe` | только программа — для клона этого репозитория (рядом должна быть папка `tools\`) |
|
||||
| `tang25k_debugger_bl616.bin` | прошивка моста, пишется по адресу `0x20000` |
|
||||
| `bl616_bootloader_0x20000_nano20k_signed.bin` | загрузчик Sipeed, пишется по адресу `0x0` вместе с прошивкой моста |
|
||||
| `bl616_fpga_partner_25kDock.bin` | штатная прошивка Sipeed (`0x0`) — для отката |
|
||||
| `fpga_test_bitstreams-GW5A-25.zip` | тестовые битстримы `loopback.fs` и `stream.fs` для проверки UART |
|
||||
| `SHA256SUMS.txt` | контрольные суммы |
|
||||
|
||||
Чтобы только пользоваться платой, достаточно архива `TangProgrammer-…-win64.zip`:
|
||||
он прошивает и мост (один раз), и FPGA. SDK и сборка не нужны.
|
||||
|
||||
## Что получилось (проверено на плате)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| UART, скорости | любые от 300 бод до 20 Мбод (делитель от 160 МГц); проверено 9600 … **12 Мбод в обе стороны без единой потери** |
|
||||
| UART, формат | 5–8 бит, чётность none/odd/even, 1 / 1.5 / 2 стоп-бита |
|
||||
| UART, поток FPGA → ПК | 10 Мбод непрерывно (1 МБ/с) 30 с — 0 ошибок; точность частоты подтверждена генератором FPGA |
|
||||
| UART, ПК → FPGA | управление потоком по USB (NAK), данные не теряются при любой скорости |
|
||||
| UART, буфер | кольцевой DMA-буфер 64 КБ на приём, 16 КБ на передачу |
|
||||
| JTAG | `--detect` за ~40 мс; загрузка GW5A-25 в SRAM ≈ 2 с при 6 МГц |
|
||||
| JTAG, частота | до 30 МГц; длинные сдвиги идут через аппаратный SPI BL616 |
|
||||
|
||||
Стресс-тест: сотни прогонов петли с произвольными скоростями и объёмами — без ошибок.
|
||||
|
||||
## Как это устроено
|
||||
|
||||
**Загрузка.** У BL616 на этих платах прожжён eFuse: ROM запускает с адреса
|
||||
`0x0` только образ, зашифрованный ключом Sipeed. Поэтому по `0x0` пишется
|
||||
загрузчик Sipeed (`bin/bl616_bootloader_0x20000_nano20k_signed.bin`,
|
||||
выпущен Sipeed для Nano 20K; ключ у всех плат серии общий — проверено
|
||||
сравнением шифротекстов штатных прошивок), а он безусловно передаёт
|
||||
управление нашей прошивке по `0x20000`.
|
||||
|
||||
**Распиновка BL616** (схема `Tang_25K_60033`):
|
||||
|
||||
| Сигнал | BL616 | FPGA |
|
||||
|---|---|---|
|
||||
| TMS | GPIO0 | B1 |
|
||||
| TCK | GPIO1 | C1 |
|
||||
| TDO | GPIO2 (он же BOOT) | A2 |
|
||||
| TDI | GPIO3 | A3 |
|
||||
| UART TX (ПК → FPGA) | GPIO11 | **B3** (`uart_rx` в FPGA) |
|
||||
| UART RX (FPGA → ПК) | GPIO10 | **C3** (`uart_tx` в FPGA) |
|
||||
| светодиод LED5 | GPIO20 | — |
|
||||
| кнопка S3 | GPIO12 | — |
|
||||
|
||||
Кварц BL616 на Dock — **26 МГц** (а не 40 МГц, как в SDK по умолчанию).
|
||||
|
||||
**Почему штатный UART работал плохо, а этот нет** — коротко о найденных
|
||||
особенностях BL616, которые обходит прошивка:
|
||||
|
||||
* приёмник UART BL616 намертво зависает, если сменить скорость посреди
|
||||
приходящего байта (типичная ситуация: FPGA уже шлёт данные, а терминал
|
||||
открывается на другой скорости); сброс бита EN, как делает SDK, не
|
||||
помогает — прошивка делает полный программный сброс блока UART1 при
|
||||
каждой реальной смене параметров и держит сторожевой таймер;
|
||||
* `usbser.sys` пишет порциями, кратными 512 байтам, без завершающего
|
||||
нулевого пакета — приём ведётся строго по одному пакету;
|
||||
* нулевой пакет (ZLP) на IN, запрошенный пока прошлый пакет ещё в FIFO,
|
||||
теряется — передачи к ПК всегда заканчиваются коротким пакетом.
|
||||
|
||||
## Установка (один раз)
|
||||
|
||||
1. Закройте Gowin Programmer / BouffaloLabDevCube, если они открыты.
|
||||
2. Отключите USB-C (JTAG/UART) от платы.
|
||||
3. Замкните тестовые точки **TDO** и **3V3** (нижняя сторона Dock, левый
|
||||
верхний угол), подключите USB, разомкните. Появится устройство
|
||||
«Bouffalo CDC DEMO» (COM-порт).
|
||||
4. Прошейте мост одним из способов:
|
||||
* **TangProgrammer** из релиза: вкладка «Прошивка моста (BL616)» →
|
||||
«Записать прошивку моста»;
|
||||
* из исходников (нужны `scripts\setup.ps1` и `scripts\build.ps1`):
|
||||
```powershell
|
||||
.\scripts\flash.ps1
|
||||
```
|
||||
*(пишет загрузчик Sipeed из `bin\` и собранную прошивку моста
|
||||
`build\build_out\tang25k_debugger_bl616.bin`)*;
|
||||
* вручную, BouffaloLabDevCube или BLFlashCommand: файлы из релиза,
|
||||
`bl616_bootloader_0x20000_nano20k_signed.bin` по адресу `0x0` и
|
||||
`tang25k_debugger_bl616.bin` по адресу `0x20000`.
|
||||
5. Переподключите USB. Появятся «DirtyJTAG» и новый COM-порт.
|
||||
|
||||
Перед первой прошивкой стоит сохранить полный дамп флеш-памяти BL616
|
||||
(плата в загрузчике, как в шаге 3):
|
||||
```powershell
|
||||
.\third_party\bouffalo_sdk\tools\bflb_tools\bouffalo_flash_cube\BLFlashCommand.exe --interface=uart --baudrate=2000000 --port=COMxx --chipname=bl616 --cpu_id= --flash --read --start=0x0 --len=0x400000 --file=backup\flash_full_4M.bin
|
||||
```
|
||||
Папка `backup\` в git не попадает.
|
||||
|
||||
## Обновление прошивки
|
||||
|
||||
```powershell
|
||||
.\scripts\build.ps1
|
||||
.\scripts\flash.ps1
|
||||
```
|
||||
`flash.ps1` сам переводит работающую прошивку в загрузчик (открывает её
|
||||
COM-порт на «магической» скорости **1234 бод**) и прошивает. После записи
|
||||
**переподключите USB** — флаг «загрузиться в ISP» живёт до снятия питания.
|
||||
|
||||
Другие способы попасть в загрузчик: держать **S3** при подключении USB
|
||||
(если эта прошивка уже стоит) или перемычка TDO→3V3 (работает всегда).
|
||||
|
||||
## Возврат штатной прошивки Sipeed
|
||||
|
||||
```powershell
|
||||
.\scripts\flash.ps1 -Restore
|
||||
```
|
||||
(или в TangProgrammer: «Вернуть штатную прошивку Sipeed»). Пишет `bin/bl616_fpga_partner_25kDock.bin` (версия 2025030317, sha256
|
||||
`1be5c1f9…aacd`) — ровно то, что стояло на плате.
|
||||
|
||||
## Программатор с окном: `TangProgrammer.exe`
|
||||
|
||||
Замена Gowin Programmer поверх openFPGALoader, без консоли. Готовая программа —
|
||||
архив `TangProgrammer-…-win64.zip` из релиза; в клоне репозитория её собирает
|
||||
`.\scripts\build_gui.ps1` (появляется `TangProgrammer.exe` в корне, рядом с
|
||||
`tools\`). Ничего ставить не нужно (.NET Framework 4 есть в Windows). Вверху окна — состояние моста
|
||||
(подключён / загрузчик BL616 / штатная прошивка / нет платы), оно
|
||||
обновляется само при подключении USB.
|
||||
|
||||
**Вкладка «FPGA»**
|
||||
* битстрим `.fs` выбирается кнопкой «Обзор…» (Ctrl+O), из списка последних или
|
||||
перетаскиванием в окно; под полем — модель FPGA из файла, размер и время
|
||||
сборки (предупреждение, если файл собран не для GW5A-25);
|
||||
* «Загрузить в SRAM» (F5) — до отключения питания; «Записать во Flash» — во
|
||||
внешнюю флеш-память FPGA, с проверкой;
|
||||
* «Загружать в SRAM автоматически, когда файл пересобран» — для работы вместе с
|
||||
Gowin IDE: после каждой сборки новый `.fs` сразу попадает в FPGA;
|
||||
* «Определить FPGA», «Перезапуск из Flash» (FPGA заново грузится из своей
|
||||
флеш-памяти, как после включения питания).
|
||||
|
||||
**Вкладка «Флеш-память FPGA»** — определение микросхемы (на этой плате XTX,
|
||||
JEDEC `0B4017`, 8 МБ), резервная копия в `.bin` (первый 1 МБ с конфигурацией
|
||||
или вся микросхема; по умолчанию читается дважды и сравнивается), запись
|
||||
`.bin`/`.fs` во флеш (пустой хвост 0xFF не пишется) и стирание всей микросхемы.
|
||||
Время на этой плате: запись `.fs` с проверкой ≈ 8 с, копия 1 МБ ≈ 3 с на одно
|
||||
чтение, стирание ≈ 13 с.
|
||||
|
||||
**Вкладка «Прошивка моста (BL616)»** — то же, что `scripts\flash.ps1`: записать
|
||||
прошивку моста или вернуть штатную Sipeed.
|
||||
|
||||
Справа вверху — тема: как в Windows, светлая или тёмная. Настройки хранятся в
|
||||
`%LOCALAPPDATA%\Tang25kProgrammer\settings.ini`. Пересборка программы:
|
||||
`.\scripts\build_gui.ps1` (исходники — в `gui\`).
|
||||
|
||||
Если запись во флеш-память FPGA прервалась с ошибкой, программа сама повторяет
|
||||
её один раз: недописанная флеш-память означает, что FPGA не загрузится при
|
||||
включении.
|
||||
|
||||
**На другой компьютер** — архив из релиза или свой:
|
||||
`.\scripts\make_portable.ps1` собирает `dist\TangProgrammer\` и
|
||||
`dist\TangProgrammer.zip` (≈ 14 МБ) — программа, openFPGALoader, BLFlashCommand
|
||||
(только exe и `chips\` вместо 238 МБ папки SDK), прошивки моста и памятка
|
||||
`README.txt`. Распаковать в любую папку, куда можно писать (не в Program Files),
|
||||
и запустить `TangProgrammer.exe`. Нужна Windows 10/11 x64; драйверы для платы
|
||||
Windows ставит сама.
|
||||
|
||||
## Использование из консоли
|
||||
|
||||
JTAG — нужен **openFPGALoader ≥ 1.1.0** (в 1.1.0 исправлена работа DirtyJTAG
|
||||
с GW5A). Готовая сборка для Windows лежит в `tools\openFPGALoader\bin`.
|
||||
|
||||
```powershell
|
||||
$ofl = ".\tools\openFPGALoader\bin\openFPGALoader.exe"
|
||||
& $ofl -c dirtyJtag --detect # GW5A-25, idcode 0x0001281b
|
||||
& $ofl -c dirtyJtag design.fs # загрузить битстрим в SRAM (до отключения питания)
|
||||
& $ofl -c dirtyJtag --freq 15M design.fs # загрузить в SRAM быстрее
|
||||
& $ofl -c dirtyJtag -f design.fs # прошить битстрим во внешнюю флеш-память FPGA (навсегда)
|
||||
& $ofl -c dirtyJtag --dump-flash --file-size 1048576 copy.bin # копия первого 1 МБ флеш-памяти FPGA
|
||||
& $ofl -c dirtyJtag -f copy.bin # записать образ обратно (с адреса 0)
|
||||
& $ofl -c dirtyJtag --bulk-erase # стереть всю флеш-память FPGA
|
||||
```
|
||||
`--unprotect-flash` с этой микросхемой флеш-памяти не использовать: её нет в
|
||||
справочнике openFPGALoader 1.1.1, и эта функция на ней падает. Защита записи
|
||||
(биты BP) на плате и так снята.
|
||||
|
||||
UART — любой терминал или pyserial на появившемся COM-порту, скорость и
|
||||
формат задаются как обычно. При открытии порта (DTR=1) накопленные за время
|
||||
простоя данные сбрасываются, как у FTDI.
|
||||
|
||||
**Gowin Programmer эта прошивка не поддерживает** (он работает только с FTDI).
|
||||
Для него — `flash.ps1 -Restore`.
|
||||
|
||||
## Сборка из исходников
|
||||
|
||||
```powershell
|
||||
.\scripts\setup.ps1 # Bouffalo SDK v2.3.16 + тулчейн T-Head в third_party\
|
||||
.\scripts\build.ps1 # build\build_out\tang25k_debugger_bl616.bin
|
||||
```
|
||||
Если проект лежит на сетевом диске, который смотрит на эту же машину
|
||||
(например `D:` → `\\PC\Projects`), скрипты сами собирают по локальному пути
|
||||
— через SMB сборка в десятки раз медленнее.
|
||||
|
||||
## Тесты
|
||||
|
||||
`fpga_test\` — два тестовых проекта Gowin (готовые `.fs` есть в релизе):
|
||||
|
||||
* `loopback` — `uart_tx = uart_rx`, петля на любой скорости;
|
||||
* `stream` — FPGA сама шлёт счётчик на ровно 10 Мбод.
|
||||
|
||||
Сборка — из папки проекта, например:
|
||||
```powershell
|
||||
cd fpga_test\loopback; & C:\Gowin\Gowin_V1.9.12_x64\IDE\bin\gw_sh.exe build.tcl; cd ..\..
|
||||
```
|
||||
|
||||
```powershell
|
||||
& $ofl -c dirtyJtag fpga_test\loopback\impl\pnr\loopback.fs
|
||||
python tests\uart_loopback_test.py --port COM14
|
||||
& $ofl -c dirtyJtag fpga_test\stream\impl\pnr\stream.fs
|
||||
python tests\uart_stream_test.py --port COM14 --seconds 30 --switches 10
|
||||
```
|
||||
|
||||
## Выпуск релиза
|
||||
|
||||
1. Поднять `FW_VERSION_STR` в `src/sys.h` и описать изменения в `CHANGELOG.md`.
|
||||
2. Собрать прошивку и тестовые битстримы, затем файлы релиза:
|
||||
```powershell
|
||||
.\scripts\build.ps1
|
||||
.\scripts\make_release.ps1 # dist\release\v<версия>\ + SHA256SUMS.txt
|
||||
```
|
||||
3. Закоммитить, поставить тег и отправить:
|
||||
```powershell
|
||||
git tag -a v1.0.0 -m "v1.0.0"
|
||||
git push origin main v1.0.0
|
||||
```
|
||||
4. Опубликовать релиз с файлами — нужен токен Gitea с правом
|
||||
`write:repository` (Настройки → Приложения → Создать токен):
|
||||
```powershell
|
||||
$env:GITEA_TOKEN = "<токен>"
|
||||
.\scripts\publish_release.ps1
|
||||
```
|
||||
Или вручную: «Релизы» → «Новый релиз» → тег, текст из `CHANGELOG.md`,
|
||||
файлы из `dist\release\v<версия>\`.
|
||||
|
||||
## Ограничения
|
||||
|
||||
* Gowin Programmer не работает (только openFPGALoader).
|
||||
* Чётность mark/space не поддерживается аппаратно (передаётся как «нет»).
|
||||
* DTR/RTS и BREAK не выведены на FPGA — на плате нет таких линий.
|
||||
* Нулевой пакет на JTAG-IN не отправляется: клиенты DirtyJTAG читают ответ
|
||||
известной длины.
|
||||
|
||||
## Структура
|
||||
|
||||
```
|
||||
src/ прошивка (main, JTAG, UART-мост, USB-дескрипторы, плата)
|
||||
gui/ исходники TangProgrammer.exe (C# WinForms, .NET Framework 4)
|
||||
bin/ загрузчик Sipeed и штатная прошивка для отката
|
||||
scripts/ setup / build / flash / build_gui / make_portable / make_release / publish_release
|
||||
fpga_test/ тестовые проекты Gowin (loopback, stream)
|
||||
tests/ тесты UART на Python (pyserial)
|
||||
tools/ openFPGALoader 1.1.1 для Windows
|
||||
```
|
||||
|
||||
Не в git (создаются скриптами):
|
||||
|
||||
```
|
||||
third_party/ Bouffalo SDK и тулчейн (setup.ps1)
|
||||
build/ сборка прошивки моста: build\build_out\tang25k_debugger_bl616.bin (build.ps1)
|
||||
dist/ переносная версия программы и файлы релиза (make_portable.ps1, make_release.ps1)
|
||||
backup/ дампы флеш-памяти своей платы
|
||||
```
|
||||
|
||||
Диагностика: vendor-запрос `0x42` к устройству (`bmRequestType=0xC0`)
|
||||
возвращает версию, частоту JTAG, скорость UART и счётчики байт.
|
||||
Reference in New Issue
Block a user