폴더·csproj·어셈블리명·RootNamespace·코드 namespace·x:Class·app.manifest 전부 변경. 빌드 결과가 네이티브로 FirmwareFlasher.exe 로 나온다(dist 수동 리네임 불필요). README 빌드/구조 경로도 갱신. 모델명 "DB720"은 그대로 유지. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
firmware-flasher
ESP32 계열 컨트롤러(DB720·DB402S·DB400S 등)에 펌웨어를 굽는 Windows GUI 도구.
설치·파이썬 없이 도는 단일 실행본으로 배포되고, 모델별 설정은 flash.json 하나로 갈아끼운다.
시작은 DB720(ESP32-P4) 전용 PowerShell 키트였고, 지금은 여러 모델을 GUI로 다룬다. 기존
.ps1스크립트도 그대로 남아 있다(아래).
특징
- 멀티모델 — 칩·offset·baud·쓰기방식이 다른 모델을 프로파일로 분리. 드롭다운에서 고르거나 폴더의
flash.json으로 자동. - 포트 자동 감지 — USB-JTAG(
303A:1001)를 꽂는 즉시 잡아 자동 선택. 리셋으로 COM 번호가 바뀌어 생기는 유령 포트를 열기-probe로 걸러 살아있는 포트로 자동 전환. - esptool 동봉 — esptool v5 단독 실행본을 같이 묶어, 받는 PC에 파이썬이 없어도 동작.
- 안전장치 — "앱만"이 기본(부트로더 안 건드림). "전체"(부트로더 재작성)는 eFuse 영구 굽힘 경고 + 확인 체크.
빠른 시작 (사용자)
- 배포 zip을 풀고
FirmwareFlasher.exe실행. - 펌웨어 폴더 선택 → 앱·모델 확인(폴더에
flash.json있으면 자동). - 포트는 자동으로 잡힘(안 잡히면
↻ 새로고침). - 모드 고르고 플래시 시작.
- 평소: 앱만(가장 안전)
- 새 보드 첫 굽기/복구: 전체 (eFuse 주의)
- 끝나면 보드 전원 재인가.
지원 모델
| 모델 | 칩 | 부트로더 offset | 포트·방식 |
|---|---|---|---|
| DB720 | esp32p4 |
0x2000 |
USB-JTAG · no-stub · 115200 · 영역별 |
| DB402S | esp32s3 |
0x0000 |
UART(TTL) · stub · 921600 · 한 번에 |
| DB400S / DB400Q / DB300eM | esp32 |
0x1000 |
UART(TTL) · stub · 921600 · 한 번에 |
공통 offset: 파티션 0x10000 · ota_data 0x11000 · 앱 0x20000 · (DB720만) www_fs 0x420000.
모델 추가 — flash.json
펌웨어 폴더에 flash.json을 넣으면 앱이 그 폴더만 보고 그대로 굽는다. profiles/에 모델별 템플릿이 있다.
{
"name": "DB402S (ESP32-S3)",
"chip": "esp32s3",
"baud": 921600,
"noStub": false,
"perRegion": false,
"regions": [
{ "file": "bootloader.bin", "offset": "0x0000", "kind": "bootloader" },
{ "file": "partition-table.bin", "offset": "0x10000", "kind": "support" },
{ "file": "ota_data_initial.bin", "offset": "0x11000", "kind": "support" },
{ "app": true, "offset": "0x20000" }
],
"consolePortHint": "10C4:EA60",
"downloadModeHint": "TTL(COM2) 연결, SW1 누른 채 SW2 눌렀다 떼고 SW1 떼면 다운로드 모드"
}
주요 키: chip / baud / noStub(스텁 여부) / perRegion(영역별 vs 한 번에) / flashSize·flashMode·flashFreq(생략 시 자동) / flashPortHint(자동선택 우선 VID:PID) / consolePortHint / appOnlyErasesOtadata.
flash.json이 없어도 됨 — DB720·DB402S·DB400S·DB400Q·DB300eM 설정은 앱에 내장돼 있어 "모델" 드롭다운에서 골라도 동작.
포트 — 유령 COM 주의
ESP32 USB-JTAG는 보드가 리셋될 때마다 USB를 다시 잡아 COM 번호가 올라간다(예: COM17→COM18). 옛 번호는 목록엔 "정상"으로 남지만 열 수 없다(유령 포트). 앱은 최신 번호 우선 + 열기-probe로 살아있는 포트를 자동으로 쓴다. 그래도 안 되면 케이블을 다시 꽂고 ↻ 새로고침.
적재 포트는 측정/표출 중에는 열지 말 것 — DTR/RTS가 보드를 리셋한다.
secure 보드 / eFuse
서명(secure boot) 보드는 부트로더(0x8000 아래) 쓰기를 거부하는 게 정상이다. 그땐 표준/앱만으로(부트로더 건너뜀). 꼭 부트로더를 다시 써야 하면 --force. eFuse는 한 번 구워지면 되돌릴 수 없으니 서명 키 백업 필수.
빌드 (개발)
요구: .NET 9 SDK (Windows), WPF(net9.0-windows).
dotnet build FirmwareFlasher\FirmwareFlasher.csproj
dotnet run --project FirmwareFlasher\FirmwareFlasher.csproj
배포 (단일 실행본)
dotnet publish FirmwareFlasher\FirmwareFlasher.csproj -c Release -r win-x64 `
--self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true
⚠ 단일 파일 publish는 동봉
esptool.exe를 exe 안으로 삼킨다. publish 후tools\esptool\와firmware\를 exe 옆에 따로 복사해 배포 폴더를 만든다(그래야 앱이 esptool을 찾음). 받는 사람은 폴더 통째로 받아FirmwareFlasher.exe실행 — 설치 불필요.
폴더 구조
firmware-flasher/
├─ FirmwareFlasher/ WPF 앱 소스 (+ tools/esptool/ 동봉 엔진)
├─ firmware/ 펌웨어 폴더 (flash.json 포함; 서명 .bin 은 git 제외)
├─ profiles/ 모델별 flash.json 템플릿 (DB720·DB402S·DB400S)
├─ flash_app.ps1 / flash_full.ps1 / list_ports.ps1 기존 PowerShell 키트
└─ README.md
firmware/*.bin(서명 실펌웨어)와dist/(배포본), 빌드 출력은 git에 올리지 않는다(.gitignore). 배포본 zip은 Gitea Releases로.
PowerShell 키트 (기존)
GUI 없이 명령으로 굽는 원래 방식(여전히 사용 가능). DB720 기준:
.\list_ports.ps1 # 적재 포트(303A:1001) 확인
.\flash_app.ps1 -Port COM4 -AppOnly # 앱만 (brick-safe, 권장)
.\flash_full.ps1 -Port COM4 # 전체 (부트로더 포함, eFuse 주의)
일상 적재는
flash_app.ps1(앱만)으로 충분하다.flash_full.ps1은 부트로더가 비어 부팅이 안 될 때만 쓰는 복구 전용. GUI 앱은 동봉 esptool(v5)로 같은 일을 더 안전하게 한다.