Skip to main content

embflasher

Cross-platform CMSIS-DAP firmware programmer driven by CMSIS FLM flash algorithms, built on pyOCD.

CLI
 ↓
Python API (embflasher.flash)
 ↓
pyOCD
 ↓
DAPLink / CMSIS-DAP
 ↓
MCU

Supports macOS, Windows, and Linux (Ubuntu).

Installation

pip install embflasher

Local development:

git clone <repo-url>
cd embflasher
pip install -e .

Usage

embflasher --help
embflasher probe list
embflasher flash firmware.hex --flm chip.flm

Minimal usage — only firmware and --flm are required, everything else uses a sensible default (sector erase, verify on, reset on, 100k SWD frequency, cortex_m target):

embflasher flash firmware.bin --flm NS800RT50x9.FLM

If more than one DAPLink/CMSIS-DAP probe is connected, select one explicitly:

embflasher probe list
embflasher flash firmware.hex --flm chip.flm --probe <unique-id>

Full option list:

embflasher flash firmware.{bin,hex,elf} --flm chip.flm
  [--probe <unique-id>]
  [--erase auto|sector|chip]      (default: sector)
  [--no-verify]
  [--no-reset]
  [--bin-address 0x...]           (.bin only; default: FLM's Flash start)
  [--frequency 100k]              (default: 100k)
  [--connect halt|pre-reset|under-reset|attach]  (default: under-reset)
  [--target cortex_m]             (default: cortex_m)
  [--ram-start 0x20000000]        (default: 0x20000000)
  [--ram-size 0x...]              (default: max(64KiB, FLM minimum))

Python API

from embflasher import flash, list_probes

flash(firmware="app.hex", flm="chip.flm")

# with overrides
flash(
    firmware="app.bin",
    flm="chip.flm",
    probe="0123456789ABCDEF",
    target="cortex_m",
    frequency="4M",
    erase="chip",
    verify=True,
    reset=True,
)

print(list_probes())

Requirements

  • Python >= 3.10
  • A DAPLink or CMSIS-DAP compatible debug probe
  • pyOCD (installed automatically as a dependency)

USB permissions on Linux

On Ubuntu/Linux, the debug probe usually needs a udev rule to be accessible without root. pyOCD ships one:

python -m pyocd pack update   # optional, first run
sudo curl -o /etc/udev/rules.d/50-cmsis-dap.rules \
  https://raw.githubusercontent.com/pyocd/pyOCD/main/udev/50-cmsis-dap.rules
sudo udevadm control --reload-rules
sudo udevadm trigger

Then unplug and replug the probe.

Releasing a new version (maintainers)

Pushing commits to main does not publish anything by itself. Publishing to PyPI only happens when a GitHub Release is created, and that Release must point at a tag. The chain is:

bump version in pyproject.toml
        ↓
git commit + git push (to main)
        ↓
git tag vX.Y.Z + git push origin vX.Y.Z
        ↓
gh release create vX.Y.Z   (or create it from the GitHub web UI)
        ↓
GitHub Actions: .github/workflows/publish.yml runs automatically
        ↓
  1. checkout, python -m build  → builds dist/*.whl and dist/*.tar.gz
  2. uploads them as a workflow artifact
  3. downloads the artifact into the `pypi` environment job
  4. pypa/gh-action-pypi-publish uploads them to PyPI via
     Trusted Publishing (OIDC) — no API token needed
        ↓
pip install embflasher   ← now installs the new version

Step-by-step for a real release:

# 1. bump the version
#    edit pyproject.toml: version = "0.1.2"
git add pyproject.toml
git commit -m "Bump version to 0.1.2"
git push origin main

# 2. tag the commit that should be released
git tag -a v0.1.2 -m "v0.1.2"
git push origin v0.1.2

# 3. create the GitHub Release — THIS is what triggers the publish workflow
gh release create v0.1.2 --title "v0.1.2" --notes "..."

After step 3, check progress with:

gh run list --workflow=publish.yml --limit 1
gh run watch

Notes:

  • Creating just a tag does not trigger anything. The workflow only fires on: release: types: [published].
  • The PyPI project must have a "pending publisher" (or an existing Trusted Publisher) configured once, at https://pypi.org/manage/account/publishing/, pointing at this repo (codeing-link/embflasher), workflow file publish.yml, and environment name pypi. This is a one-time, manual step done on pypi.org — it cannot be automated from the repo.
  • The repo also needs a GitHub Environment named pypi (Settings → Environments) for the OIDC trust relationship declared in publish.yml (environment: pypi, permissions: id-token: write).
  • PyPI does not allow re-uploading the same version number. If a release fails partway, bump the version again rather than retrying the same tag.
  • This works the same whether the repository is public or private — Trusted Publishing is based on the OIDC token GitHub issues for the workflow run, not on repo visibility.

License

MIT

Metadata

Release files for embflasher 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for embflasher 0.1.1
File Size Uploaded
embflasher-0.1.1.tar.gz 11.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for embflasher 0.1.1
File Interpreter ABI Platform
embflasher-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 21.7 kB

Release files / embflasher-0.1.1.tar.gz

Download URL embflasher-0.1.1.tar.gz
Size 11.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a23e31a857a9810d3593336e2e49c1e4e7f93ea0449a1a6b15e16d47edaa8ed0
BLAKE2b-256 checksum
How to use checksums
b5c918621ae6f6af77c30c39ba7d4469c5585b4ad4729030a38836e823a915b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release files / embflasher-0.1.1-py3-none-any.whl

Download URL embflasher-0.1.1-py3-none-any.whl
Size 10.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
227950a5e13afa6788f75469607b7c0e1c04a35098915473cf9541ecfa668cf0
BLAKE2b-256 checksum
How to use checksums
7afa262a5313e830375b1c64662adc3a97f115e8deaca70b5dfff18800779123
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page