# ST-Link Console

A static browser console for local ST-Link flash operations and receive-only serial logs. **The web server only serves files; hardware connects to the visitor's computer.** Desktop Chrome/Edge accesses it directly through WebUSB and Web Serial after explicit permission.

No server USB passthrough, CubeProgrammer installation, native helper, Node runtime, firmware compilation, CDN, telemetry, firmware upload or application API is needed to use the hosted page. Local USB drivers/permissions may still be required.

**Generic interface does not mean universal chip support:** the current flash driver supports the **STM32G071KB 128 KiB profile** with **ST-LINK/V2 or V2-1** only. Other STM32 families, ST-Link V3 and source-level/breakpoint debugging are not implemented. The driver has simulated tests but **has not been physically qualified**. Keep official STM32CubeProgrammer available for recovery.

## Language / Jazyk

- On first visit, the page chooses the first supported language in the browser's preferred-language list (`navigator.languages`, or `navigator.language` as fallback). Czech regional variants such as `cs-CZ` select Czech; English variants select English. If neither is listed, it uses English.
- The header selector offers **Browser language / English / Čeština**. Manual choice overrides detection and is remembered per browser/origin in localStorage. Choosing Browser language clears that override. This is the browser preference, which may differ from the operating-system language.
- Language changes update titles, labels, confirmations, status, help, activity and known application diagnostics immediately. They do **not** reconnect, halt, reset, start a flash operation or discard a selected image/serial log. Raw device output, filenames, addresses and unknown OS/probe diagnostic details remain verbatim. Native permission dialogs are controlled by the browser/OS, not by this page.
- If storage is blocked, switching still works for the current page; only persistence is unavailable. Only the language choice is saved—never firmware or logs.

**Česky:** Stránka při prvním otevření použije jazyk prohlížeče. Vpravo nahoře lze vybrat **Čeština**, **English** nebo **Podle prohlížeče**. Ruční volba se zapamatuje pro danou adresu webu. Změna jazyka nemění připojení ani stav zařízení. Výpisy zařízení zůstávají v původním znění. Aktuálně je podporován pouze profil STM32G071KB a sondy ST-LINK/V2 a V2-1; nejde o univerzální debugger všech řad STM32.

## Open locally

From the repository root:

```sh
python3 web/serve.py --open
```

Or double-click **`web/Open-Console.command`** on macOS. It opens only a loopback static server and webpage, never USB/serial devices. If the default browser is Safari, copy `http://localhost:8080` into Chrome. Keep the terminal open; Ctrl-C stops the preview. Another port: `python3 web/serve.py --port 8081 --open`.

Python 3 is needed only for this optional preview. The hosted HTTPS page needs no local server or helper. `file://` and plain HTTP on a LAN/VM IP are not supported hardware-access contexts. `http://localhost` is allowed for local development.

## Ready-to-copy Ubuntu VPS package

From the repository root, build a self-contained archive (no frontend build or dependencies):

```sh
python3 scripts/package-console.py
```

The `.tar.gz` and companion `.sha256` are created in `dist/`. Upload both to your VPS, verify the checksum, extract and enter `stlink-console/`. Then:

```sh
# Only if Docker + Compose are not installed:
sudo ./install-docker.sh
sudo ./setup.sh --domain stlink.your-domain.cz --email you@your-domain.cz
sudo ./manage.sh check
```

Caddy serves files directly with automatic HTTPS; no reverse proxy configuration is needed. Setup refuses occupied ports and preserves existing settings. The archive includes `DEPLOY.md` with English/Czech instructions, updates, rollback and troubleshooting. Scripts never change SSH/UFW settings or delete certificate volumes. Docker itself manages networking; published ports can bypass UFW. No real VPS deployment or root installation was executed during development.

## Manual Docker hosting on an Ubuntu VM

Use a public domain pointing to the VM, Docker Engine + Compose, and reachable TCP ports **80/443**. Forward these ports through NAT if necessary. Incorrect/unreachable AAAA records can prevent certificate issuance. Caddy obtains HTTPS certificates automatically.

Copy just the `web/` folder to the VM, then:

```sh
cd web
cp .env.example .env
nano .env                     # real domain and certificate email
# After public DNS and ports are ready:
docker compose up -d --build
```

Open **`https://your-domain`** on the computer with the hardware. Updates: replace static files and run `docker compose up -d --build` again. Certificate data persists in Docker volumes. Troubleshooting: `docker compose logs console`.

The container serves only `index.html`, `styles.css`, `README.md`, `src/` and `vendor/`. It has **no privileged mode, device mounts or backend**. Docker/Caddy runtime deployment has not been exercised in this development environment; the local static preview and mocked Chrome hardware flows have.

With an existing HTTPS host, serve those same files/directories without a build step. Preserve relative paths; do not publish `.env`, tests, launchers or deployment configuration. Apply the headers in `Caddyfile`, particularly `Permissions-Policy: usb=(self), serial=(self)`, the same-origin CSP and `Cache-Control: no-cache`. Use a dedicated trusted origin, not an iframe. A reverse proxy must not disable hardware APIs. No service worker is installed; avoid mixing stale JS versions.

## Use the console

1. Connect and power the target correctly. ST-Link needs SWDIO, SWCLK, common GND and VTref at the target logic voltage. Avoid conflicting supplies. Ensure the target and connected peripherals can safely be halted/reset. Keep the laptop awake, the tab foregrounded and cables connected. Conservative per-doubleword USB programming can take minutes.
2. Click **Connect ST-Link** and select a local V2/V2-1 probe. Identity/protection checks do not request a CPU halt or reset. Close other debuggers first. Wake the target if STOP mode makes SWD unavailable; no automatic under-reset recovery is attempted.
3. Optionally connect the local USB serial port at **115200, 8N1**. Target TX → adapter RX, common GND, matching logic voltage; never connect RS-232 voltage levels directly. Serial is separate from SWD. The monitor never writes commands, but opening a serial adapter can toggle control lines and reset a target.
4. **Download current flash** asks for confirmation, then halts the CPU, captures 128 KiB and requests a timestamped `.bin` download. **The CPU remains halted.** Check browser Downloads: initiating a download is not proof the file reached disk. A retained backup link stays available until replaced or the page closes. Option bytes/OTP are not included.
5. Select/drop a precompiled **ELF, Intel HEX or BIN**. Parsing, bounds checks and SHA-256 are local. BIN starts at `0x08000000`. ELF uses ARM little-endian ELF32 `PT_LOAD` physical addresses; HEX validates checksums. Full applications with plausible stack/reset vectors at the main-flash base are required. Offset-only, RAM, option-byte, malformed and out-of-range images are rejected.
6. **Write & verify** requires typing `FLASH`. A new complete backup is captured before every write. Only changed 2 KiB pages are erased, programmed as 8-byte doublewords and completely verified. Untouched bytes, sparse gaps and partial-page tails are preserved. This deliberately does not erase stale regions outside the image; use official tools if a clean full-chip layout is needed.
7. Successful writing leaves the CPU halted. The separate **Reset & run** requires typing `RUN` and can activate target peripherals. Disconnect/close never intentionally resumes the CPU. Power-cycling or an external reset may restart firmware. A sent reset/run command is not proof of successful target operation.

On failure or **Stop operation**, no automatic retry/restart is sent. Stop is cooperative: the current transfer/doubleword finishes first; partially erased/programmed firmware is possible. The CPU is intended to stay halted, but USB/power loss or an external reset makes state uncertain. Flash is relocked when possible. After a USB timeout/ambiguous transfer, safely unplug/replug the probe before reconnecting: probe firmware can retain an incomplete command. Keep the backup and use official CubeProgrammer for recovery when needed.

### Serial retention

Pause freezes the display, not acquisition. The retained raw log is limited to **1,048,576 characters**, with a visible discarded-character count; the display shows the last 50,000. Save downloads `STLink_serial_<UTC timestamp>.log`. Backups use `STLink_flash_<UTC timestamp>.bin`. Clear resets the log; closing the page loses it. This is not unlimited data acquisition. Other tools cannot simultaneously own the same serial port.

## Hardware and implementation limits

- Flash profile: **STM32G071KBTx**, main flash `0x08000000`, **128 KiB**, **2 KiB pages**, **36 KiB RAM**. Gates check Cortex-M0+, family ID `0x460`, factory flash size and RDP `0xAA`. The shared G07x/G08x family ID is **not exact model/package identification**. Use only a target known to match this profile.
- Probes: ST vendor `0x0483`, V2 PID `0x3748`, V2-1 PID `0x374B`, API-v2 firmware (upstream requires JTAG version ≥21). V3 is not supported. Clones may behave differently; prefer genuine probes.
- No option-byte writes, protection removal, mass erase, bootloader changes, OTA, DFU, compilation, automatic recovery, source-level debugging or breakpoint UI.
- Main-flash backup excludes option bytes, OTP, RAM and external devices. SHA-256 identifies the selected file; it does not authenticate/sign it. Choose trusted, compatible firmware.
- Attaching SWD is real debug access even without an intentional halt/reset. Later operations halt and configure volatile watchdog debug-freeze bits. No guarantee of zero effects on every probe/target is made.
- Pinned MIT `webstlink` transport has narrowly documented patches, checked transfers and timeouts. Its generic flash driver/database is not used. See `vendor/webstlink/NOTICE.md` and `LICENSE`.
- G0 sequences follow the repository's STM32CubeG0 `FLASH_PageErase`, `FLASH_Program_DoubleWord` and CMSIS register definitions. Simulations do not replace reference-manual review and physical qualification.

### Visitor-side OS permissions

These apply on the computer with the hardware, **not the hosting VM**:

- **macOS:** use Chrome/Edge, approve the USB accessory if prompted, and close other debug/serial tools. No helper service is used.
- **Linux:** an administrator may need `/etc/udev/rules.d/60-stlink-console.rules`:

  ```udev
  SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="3748", MODE="0660", TAG+="uaccess"
  SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="374b", MODE="0660", TAG+="uaccess"
  ```

  Run `sudo udevadm control --reload-rules`, then unplug/replug. Serial may require `sudo usermod -aG dialout "$USER"` followed by logout/login. Do not run Chrome as root or make all USB devices world-writable.
- **Windows:** WebUSB needs a suitable WinUSB binding for the ST-Link **debug interface**. Do not replace the whole composite device or its CDC/serial driver. Administrative driver setup may be necessary.
- Managed-browser policies, occupied interfaces, old probe firmware and remote-desktop configurations can prevent access. Safari/Firefox and general mobile use are not supported.

## Tests and physical qualification

No npm dependencies or frontend build. With Node.js 20+ and Python 3:

```sh
cd web
npm test
```

Tests cover parsers, target/protection gates, backup-before-erase, page preservation, aligned programming, verification/relock/errors/cancellation, USB timeouts/late completions, serial retention, static serving, language detection/override/storage restrictions, catalog completeness and diagnostic parameters. An existing compiled Debug ELF is parsed when present.

For simulated end-to-end Chrome tests, start the local preview, load a fresh page, then use DevTools:

```js
await import('./tests/browser-smoke.js').then(m => m.run({language: 'cs'}))
// Reload first, then repeat with language: 'en'.
```

This explicitly installs fake USB/serial and never opens physical devices. It tests flash flows and language switching with retained state, logs and dialogs, and initiates dummy backup downloads. Production containers exclude tests. Reload to remove all fakes before real use.

Before relying on real writes, an authorized operator should use a recoverable, safely isolated fixture: identify the exact chip, compare the browser backup byte-for-byte with CubeProgrammer, program a known-safe image, independently read/verify it, test explicit reset, and qualify cable-loss/watchdog/protection behavior. **No physical qualification has been performed here.**
