diff --git a/.gitignore b/.gitignore index fb133f3a..e0ce0887 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ __pycache__ 78e43b91-b6a2-4e0a-99c2-3f6f74828063_ExportBlock-935e0d48-7286-4b74-aa60-ccd18217ac01 node_modules/ CLAUDE.md +.build/ diff --git a/.husky/commit-msg b/.husky/commit-msg index f6f2ce3f..9dc7802a 100644 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,2 +1,6 @@ #!/usr/bin/env sh +if [ ! -d node_modules ]; then + echo "Error: node_modules is missing. Run 'make setup' or 'npm install' first." + exit 1 +fi npx --no-install commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit index 1d606c6e..64edfee0 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1,6 @@ #!/usr/bin/env sh +if [ ! -d node_modules ]; then + echo "Error: node_modules is missing. Run 'make setup' or 'npm install' first." + exit 1 +fi npx --no-install validate-branch-name && npx --no-install git-precommit-checks && npx --no-install lint-staged diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53d74824..f3bc0a18 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,6 +92,8 @@ test(mcp23009e): Add mock scenarios for mcp23009e driver. 5. Commit — the git hooks will automatically check your commit message and run ruff on staged files 6. Push your branch and open a Pull Request +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. + ## Continuous Integration All pull requests must pass these checks: @@ -122,6 +124,26 @@ make bump PART=minor # minor: v1.0.1 → v1.1.0 make bump PART=major # major: v1.1.0 → v2.0.0 ``` +## Firmware build and deploy + +The drivers are "frozen" into the MicroPython firmware for the STeaMi board. The Makefile automates cloning, building, and flashing: + +```bash +make firmware # Clone micropython-steami (if needed), link local drivers, build +make firmware-update # Refresh the MicroPython clone and board-specific submodules +make deploy # Flash firmware via OpenOCD +make run SCRIPT=lib/steami_config/examples/show_config.py # Run with live output +make deploy-script SCRIPT=lib/.../calibrate_magnetometer.py # Deploy as main.py for autonomous use +make run-main # Re-execute the deployed main.py +make firmware-clean # Clean firmware build artifacts +``` + +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. + +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. + +**Requirements**: `arm-none-eabi-gcc` toolchain, OpenOCD for flashing, and `mpremote` for running scripts on the board. + ## Notes * Keep implementations simple and readable diff --git a/Makefile b/Makefile index 9f06d607..69fed4c7 100644 --- a/Makefile +++ b/Makefile @@ -79,6 +79,61 @@ ci: lint test test-examples ## Run all CI checks (lint + tests + examples) .PHONY: build build: lint test ## Build (lint + test) +# --- Firmware --- + +$(MPY_DIR): + @echo "Cloning micropython-steami into $(CURDIR)/$(MPY_DIR)..." + @mkdir -p $(dir $(CURDIR)/$(MPY_DIR)) + git clone --branch $(MICROPYTHON_BRANCH) $(MICROPYTHON_REPO) $(CURDIR)/$(MPY_DIR) + cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) submodules + +.PHONY: firmware +firmware: $(MPY_DIR) ## Build MicroPython firmware with current drivers + @echo "Linking local drivers..." + rm -rf $(CURDIR)/$(MPY_DIR)/lib/micropython-steami-lib + ln -s $(CURDIR) $(CURDIR)/$(MPY_DIR)/lib/micropython-steami-lib + @echo "Building firmware for $(BOARD)..." + cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) + @echo "Firmware ready: $(CURDIR)/$(MPY_DIR)/ports/stm32/build-$(BOARD)/firmware.hex" + +.PHONY: firmware-update +firmware-update: $(MPY_DIR) ## Update the MicroPython clone and board-specific submodules + @echo "Updating micropython-steami..." + rm -rf $(CURDIR)/$(MPY_DIR)/lib/micropython-steami-lib + cd $(CURDIR)/$(MPY_DIR) && git fetch origin && git checkout $(MICROPYTHON_BRANCH) && git checkout -- lib/micropython-steami-lib && git pull --ff-only + @echo "Updating required submodules for $(BOARD)..." + cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) submodules + +.PHONY: deploy +deploy: $(MPY_DIR) ## Flash firmware to the board via OpenOCD + cd $(CURDIR)/$(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) deploy-openocd + +.PHONY: run +run: ## Run a script on the board with live output (SCRIPT=path/to/file.py) + @if [ -z "$(SCRIPT)" ]; then \ + echo "Error: SCRIPT is required. Usage: make run SCRIPT=lib/.../example.py"; exit 1; \ + fi + mpremote connect $(PORT) run $(SCRIPT) + +.PHONY: deploy-script +deploy-script: ## Deploy a script as main.py for autonomous execution (SCRIPT=path/to/file.py) + @if [ -z "$(SCRIPT)" ]; then \ + echo "Error: SCRIPT is required. Usage: make deploy-script SCRIPT=lib/.../example.py"; exit 1; \ + fi + mpremote connect $(PORT) cp $(SCRIPT) :main.py + mpremote connect $(PORT) reset + @echo "Script deployed as main.py and board reset." + +.PHONY: run-main +run-main: ## Re-execute main.py on the board and capture output + mpremote connect $(PORT) exec "exec(open('/flash/main.py').read())" + +.PHONY: firmware-clean +firmware-clean: ## Clean firmware build artifacts + @if [ -d "$(MPY_DIR)/ports/stm32" ]; then \ + cd $(MPY_DIR)/ports/stm32 && $(MAKE) BOARD=$(BOARD) clean; \ + fi + # --- Hardware --- .PHONY: repl @@ -141,8 +196,9 @@ clean: ## Remove build artifacts and caches find . -type d -name .mypy_cache -exec rm -rf {} + 2>/dev/null || true .PHONY: deepclean -deepclean: clean ## Remove everything including node_modules +deepclean: clean ## Remove everything including node_modules and firmware rm -rf node_modules + @if [ -d "$(BUILD_DIR)" ]; then rm -rf "$(BUILD_DIR)"; fi .PHONY: help help: ## Show this help @@ -159,4 +215,4 @@ printvars: # Affiche toutes les cibles disponibles dans le Makefile .PHONY: list list: - @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 '^$@$$' \ No newline at end of file + @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 '^$@$$' diff --git a/env.mk b/env.mk index 61b7103d..88de225d 100644 --- a/env.mk +++ b/env.mk @@ -1,2 +1,9 @@ export PATH := $(CURDIR)/node_modules/.bin:$(PATH) PORT ?= /dev/ttyACM0 + +# Firmware build configuration +MICROPYTHON_REPO ?= https://github.com/steamicc/micropython-steami.git +MICROPYTHON_BRANCH ?= stm32-steami-rev1d-final +BOARD ?= STEAM32_WB55RG +BUILD_DIR ?= .build +MPY_DIR ?= $(BUILD_DIR)/micropython-steami