# Zepto Flashing

## Current live path

The current intended host-side path is:

- `bb-imager-rs`
- `bb-imager-cli`
- feature set: `zepto_i2c`
- destination device: `/dev/i2c-1` for the Zepto currently attached on J6

## Board state

Validated on this board:

- J6 is exposed as `/dev/i2c-1`
- J7 is exposed as `/dev/i2c-3`
- the Zepto in MSPM0 BSL mode ACKs at `0x48` on `/dev/i2c-1`

## Repo wrappers

- `scripts/build_bb_imager_cli_zepto_i2c.sh`
- `scripts/list_zepto_i2c_destinations.sh`
- `scripts/probe_zepto_bsl_active.sh`
- `scripts/flash_zepto_bsl.sh`
- `scripts/flash_zepto_blink.sh`

## Automated Control Direction

The BeagleBadge Grove connector is now wired into the attached Zepto control signals:

- Grove pin 1 (yellow) -> Zepto `BSL`
- Grove pin 2 (white) -> Zepto `RST`

See [ZeptoControlWiring.md](/root/interactor/badge-demo/docs/ZeptoControlWiring.md#L1).

This should allow the host to automate Zepto BSL entry once the Linux GPIO line mapping and pinmux state for those Grove pins are identified.

## Expected CLI flow

Build:

```sh
scripts/build_bb_imager_cli_zepto_i2c.sh
```

List destinations:

```sh
scripts/list_zepto_i2c_destinations.sh
```

Current local patch direction:

- `bb-flasher-mspm0` now probes each `/dev/i2c-*` bus with the MSPM0 BSL connection request and keeps only ACKing buses
- `bb-imager-cli` Zepto listing was also fixed so it does not invert `--no-filter` and accidentally bypass that probe logic
- the remaining verification step is to rerun destination listing after the rebuilt CLI binary finishes linking on-device

## Timing note

Live probing on this board shows the Zepto BSL is not always reachable immediately after the manual BOOT/RST sequence.

- one successful user-run probe only received the first ACK on attempt `13/50`
- that delay was caused by the user invoking BSL while the probe loop was already running, not by a demonstrated intrinsic BSL startup delay

The probe now treats only `0x00` as a valid BSL ACK.
Other returned bytes such as `0x02` or `0x06` are reported as unexpected responses rather than successful readiness.

## Current flashing stance

The wrapper-level wait/retry behavior is kept in this repo.

The deeper MSPM0 transport changes inside `bb-imager-rs` were backed out so the actual flash sequence again follows the previously debugged upstream path.

## Known-good reference (maintainer, 2026-11-08)

The maintainer validated Grove RESET/BSL flashing with their bb-imager-rs
fork. Treat zepto-bridge's RESET/BSL handling and
`scripts/flash_zepto_bsl_direct_i2c.py` as unverified until checked against it.

- Fork: https://github.com/embedconsult/bb-imager-rs, branch `badge-snake`
  (head `4f19a1b`, 2026-06-19)
- I2C fix: https://github.com/embedconsult/bb-imager-rs/commit/7834626722f2ca5e3ba04a9e5bbbca68d576d45d
- RESET/BSL sequence: `bsl_gpio_cdev_by_name` in `bb-flasher-mspm0/src/lib.rs`,
  from upstream "mspm0: Add BSL invoke support" (`00e3238`), used through
  `bb-imager-cli flash zepto IMG /dev/i2c-N --reset-gpio NAME --bsl-gpio NAME`.

What that sequence does, as written (lines found by name, both requested as
outputs starting inactive):

1. BSL active, wait 1 s.
2. RESET active, wait 1 s.
3. RESET inactive, then RESET back to an input.
4. Wait 1 s; BSL inactive, then BSL back to an input.
5. Only then does the BSL I2C exchange start.

How zepto-bridge (`bridge/src/hardware.cr`) differs, as written:

- Line numbers and pad values are fixed (gpiochip1 line 27, PADCONFIG42/43),
  not found by name.
- It pulses BSL=1, RST=0 for 0.25 s, then holds BSL=1, RST=1 for the whole
  flash instead of releasing both lines to inputs before it.

Which difference matters, if any, is not known yet. Whether the fork's
"active" means high depends on how the lines are named and configured on the
badge; check that before comparing levels.

## Current live limitation

Live testing on 2026-06-18 found:

- host-driven BSL entry now works when Grove signal pads are put in a non-`TX_DIS` GPIO-capable state
- the MSPM0 I2C flasher path in `bb-flasher-mspm0` works once `standalone_verification` is skipped on I2C
- a separate active BSL probe immediately before flashing can consume the first response packet and make the next `get_device_info` request fail
- the wrapper therefore must not actively probe the Zepto right before invoking the Rust flasher
- linking the full `bb-imager-cli` binary on-device can still hit the BeagleBadge memory limit, so lower-level validation was done with `bb-flasher-mspm0/examples/flash_i2c.rs`

Until the full `bb-imager-cli` path is rebuilt and revalidated on-device, this repo still includes a direct raw-I2C fallback flasher:

```sh
scripts/flash_zepto_bsl_direct_i2c.py <IMAGE.bin>
```

That helper:

- patches `PADCONFIG42/43` live with `busybox devmem`
- drives Grove `BSL` / `RST` through `gpioset`
- enters MSPM0 BSL over `/dev/i2c-1`
- performs `connect`, `get_device_info`, `unlock`, `mass_erase`, `program_data`, and `start_application`
- restores the original pad configuration on exit

Flash a Zepto image:

```sh
components/bb-imager-rs/target/debug/bb-imager-cli flash zepto <IMAGE> /dev/i2c-1
```

The flasher accepts `bin`, `hex`, `txt`, and `xz` inputs through the MSPM0 flasher path.
