Skip to content

Commit ecc704b

Browse files
authored
tooling: Add firmware build and deploy targets. (#246)
* tooling: Add firmware build and deploy targets. * tooling: Fix firmware targets using absolute paths. * tooling: Fix firmware targets using absolute paths. * tooling: Auto-install npm deps in husky hooks after deepclean. * tooling: Address PR review feedback on firmware targets. * tooling: Separate firmware-update from firmware build.
1 parent 2c5f280 commit ecc704b

6 files changed

Lines changed: 96 additions & 2 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ __pycache__
77
78e43b91-b6a2-4e0a-99c2-3f6f74828063_ExportBlock-935e0d48-7286-4b74-aa60-ccd18217ac01
88
node_modules/
99
CLAUDE.md
10+
.build/

.husky/commit-msg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
#!/usr/bin/env sh
2+
if [ ! -d node_modules ]; then
3+
echo "Error: node_modules is missing. Run 'make setup' or 'npm install' first."
4+
exit 1
5+
fi
26
npx --no-install commitlint --edit "$1"

.husky/pre-commit

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
#!/usr/bin/env sh
2+
if [ ! -d node_modules ]; then
3+
echo "Error: node_modules is missing. Run 'make setup' or 'npm install' first."
4+
exit 1
5+
fi
26
npx --no-install validate-branch-name && npx --no-install git-precommit-checks && npx --no-install lint-staged

CONTRIBUTING.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ test(mcp23009e): Add mock scenarios for mcp23009e driver.
9292
5. Commit — the git hooks will automatically check your commit message and run ruff on staged files
9393
6. Push your branch and open a Pull Request
9494

95+
If git hooks fail because `node_modules/` is missing (for example on a fresh clone or after `make deepclean`), run `make setup` or `npm install` before committing.
96+
9597
## Continuous Integration
9698

9799
All pull requests must pass these checks:
@@ -122,6 +124,26 @@ make bump PART=minor # minor: v1.0.1 → v1.1.0
122124
make bump PART=major # major: v1.1.0 → v2.0.0
123125
```
124126

127+
## Firmware build and deploy
128+
129+
The drivers are "frozen" into the MicroPython firmware for the STeaMi board. The Makefile automates cloning, building, and flashing:
130+
131+
```bash
132+
make firmware # Clone micropython-steami (if needed), link local drivers, build
133+
make firmware-update # Refresh the MicroPython clone and board-specific submodules
134+
make deploy # Flash firmware via OpenOCD
135+
make run SCRIPT=lib/steami_config/examples/show_config.py # Run with live output
136+
make deploy-script SCRIPT=lib/.../calibrate_magnetometer.py # Deploy as main.py for autonomous use
137+
make run-main # Re-execute the deployed main.py
138+
make firmware-clean # Clean firmware build artifacts
139+
```
140+
141+
The firmware source is cloned into `.build/micropython-steami/` (gitignored). A symbolic link replaces the submodule `lib/micropython-steami-lib` with your local working directory, so the firmware always includes your latest changes — even uncommitted ones.
142+
143+
Use `make firmware` for normal rebuilds from the existing local clone. Use `make firmware-update` only when you want to refresh the `micropython-steami` checkout itself or resync the board-specific submodules before rebuilding.
144+
145+
**Requirements**: `arm-none-eabi-gcc` toolchain, OpenOCD for flashing, and `mpremote` for running scripts on the board.
146+
125147
## Notes
126148

127149
* Keep implementations simple and readable

Makefile

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,61 @@ ci: lint test test-examples ## Run all CI checks (lint + tests + examples)
7979
.PHONY: build
8080
build: lint test ## Build (lint + test)
8181

82+
# --- Firmware ---
83+
84+
$(MPY_DIR):
85+
@echo "Cloning micropython-steami into $(CURDIR)/$(MPY_DIR)..."
86+
@mkdir -p $(dir $(CURDIR)/$(MPY_DIR))
87+
git clone --branch $(MICROPYTHON_BRANCH) $(MICROPYTHON_REPO) $(CURDIR)/$(MPY_DIR)
88+
cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) submodules
89+
90+
.PHONY: firmware
91+
firmware: $(MPY_DIR) ## Build MicroPython firmware with current drivers
92+
@echo "Linking local drivers..."
93+
rm -rf $(CURDIR)/$(MPY_DIR)/lib/micropython-steami-lib
94+
ln -s $(CURDIR) $(CURDIR)/$(MPY_DIR)/lib/micropython-steami-lib
95+
@echo "Building firmware for $(BOARD)..."
96+
cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD)
97+
@echo "Firmware ready: $(CURDIR)/$(MPY_DIR)/ports/stm32/build-$(BOARD)/firmware.hex"
98+
99+
.PHONY: firmware-update
100+
firmware-update: $(MPY_DIR) ## Update the MicroPython clone and board-specific submodules
101+
@echo "Updating micropython-steami..."
102+
rm -rf $(CURDIR)/$(MPY_DIR)/lib/micropython-steami-lib
103+
cd $(CURDIR)/$(MPY_DIR) && git fetch origin && git checkout $(MICROPYTHON_BRANCH) && git checkout -- lib/micropython-steami-lib && git pull --ff-only
104+
@echo "Updating required submodules for $(BOARD)..."
105+
cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) submodules
106+
107+
.PHONY: deploy
108+
deploy: $(MPY_DIR) ## Flash firmware to the board via OpenOCD
109+
cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) deploy-openocd
110+
111+
.PHONY: run
112+
run: ## Run a script on the board with live output (SCRIPT=path/to/file.py)
113+
@if [ -z "$(SCRIPT)" ]; then \
114+
echo "Error: SCRIPT is required. Usage: make run SCRIPT=lib/.../example.py"; exit 1; \
115+
fi
116+
mpremote connect $(PORT) run $(SCRIPT)
117+
118+
.PHONY: deploy-script
119+
deploy-script: ## Deploy a script as main.py for autonomous execution (SCRIPT=path/to/file.py)
120+
@if [ -z "$(SCRIPT)" ]; then \
121+
echo "Error: SCRIPT is required. Usage: make deploy-script SCRIPT=lib/.../example.py"; exit 1; \
122+
fi
123+
mpremote connect $(PORT) cp $(SCRIPT) :main.py
124+
mpremote connect $(PORT) reset
125+
@echo "Script deployed as main.py and board reset."
126+
127+
.PHONY: run-main
128+
run-main: ## Re-execute main.py on the board and capture output
129+
mpremote connect $(PORT) exec "exec(open('/flash/main.py').read())"
130+
131+
.PHONY: firmware-clean
132+
firmware-clean: ## Clean firmware build artifacts
133+
@if [ -d "$(MPY_DIR)/ports/stm32" ]; then \
134+
cd $(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) clean; \
135+
fi
136+
82137
# --- Hardware ---
83138

84139
.PHONY: repl
@@ -141,8 +196,9 @@ clean: ## Remove build artifacts and caches
141196
find . -type d -name .mypy_cache -exec rm -rf {} + 2>/dev/null || true
142197

143198
.PHONY: deepclean
144-
deepclean: clean ## Remove everything including node_modules
199+
deepclean: clean ## Remove everything including node_modules and firmware
145200
rm -rf node_modules
201+
@if [ -d "$(BUILD_DIR)" ]; then rm -rf "$(BUILD_DIR)"; fi
146202

147203
.PHONY: help
148204
help: ## Show this help
@@ -159,4 +215,4 @@ printvars:
159215
# Affiche toutes les cibles disponibles dans le Makefile
160216
.PHONY: list
161217
list:
162-
@LC_ALL=C $(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$'
218+
@LC_ALL=C $(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$'

env.mk

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
export PATH := $(CURDIR)/node_modules/.bin:$(PATH)
22
PORT ?= /dev/ttyACM0
3+
4+
# Firmware build configuration
5+
MICROPYTHON_REPO ?= https://github.com/steamicc/micropython-steami.git
6+
MICROPYTHON_BRANCH ?= stm32-steami-rev1d-final
7+
BOARD ?= STEAM32_WB55RG
8+
BUILD_DIR ?= .build
9+
MPY_DIR ?= $(BUILD_DIR)/micropython-steami

0 commit comments

Comments
 (0)