Files
n_signer/firmware

Feather S3 TFT Firmware

This directory contains the ESP-IDF firmware for the Feather S3 TFT signer target.

USB transport mode

Firmware now runs in TinyUSB composite mode (single USB peripheral owned by TinyUSB), exposing:

  • CDC-ACM interface for Python/serial tooling (/dev/ttyACM*)
  • Vendor interface for WebUSB browser transport

Expected runtime USB identity:

  • VID:PID 303a:4001
  • Product string: Feather S3 TFT n_signer

Flashing workflow (important)

Because TinyUSB owns USB at runtime, normal app mode is not the ROM USB-Serial/JTAG flashing interface.

Use this workflow for flashing:

  1. Enter bootloader mode: hold BOOT, tap RESET, release BOOT.
  2. Confirm bootloader USB device appears (typically /dev/ttyACM0).
  3. Flash:
cd firmware/feather_s3_tft
idf.py -p /dev/ttyACM0 flash
  1. Exit bootloader and run app: ensure BOOT is released, then tap RESET once.
  2. Confirm app USB identity:
lsusb | grep -i 303a
# expect: 303a:4001 n_signer Feather S3 TFT n_signer

Quick validation

CDC path:

./.venv/bin/python ./examples/feather_get_public_key.py /dev/ttyACM0
./.venv/bin/python ./examples/feather_sign_event.py /dev/ttyACM0

WebUSB path:

Linux WebUSB host setup (one-time)

Chrome and Edge need permission to open the device on Linux. Install a udev rule for the firmware VID:PID and reload rules:

sudo tee /etc/udev/rules.d/99-nsigner-webusb.rules >/dev/null <<'EOF'
SUBSYSTEM=="usb", ATTR{idVendor}=="303a", ATTR{idProduct}=="4001", MODE="0666", GROUP="plugdev", TAG+="uaccess"
EOF
sudo udevadm control --reload-rules
sudo udevadm trigger

After installing the rule, unplug and replug the device once, then reload the demo page.

Troubleshooting

  • If lsusb shows 303a:1001, the board is still in ROM bootloader mode. Tap RESET with BOOT released.
  • If CDC command hangs, verify app-mode VID:PID is 303a:4001, not 303a:1001.
  • If no /dev/ttyACM* appears, unplug/replug after reset and re-check lsusb.
  • If WebUSB connect throws SecurityError: Access denied, install the Linux udev rule above and replug.