本文记录在 NixOS 上自编译 esp32-c3 micropython v1.28.0 固件,并内置 esptouch(ESP-Touch + AirKiss)智能配网与 coretemp(芯片内置温度传感器)两个模块的完整过程。
本文主要内容由skill自动创建,你如果觉得本文过度复杂不够条理,可以直接丢给AI参考。
前作 esp32-s2-mpy-smartconfig 基于 ubuntu + micropython 1.20 + esp-idf 4.4,本文把版本栈更新到 v1.28 + ESP-IDF 5.x,平台换成 NixOS,并补上了挖过的几个坑。文末附 flake 开发环境、编译脚本和 C 模块完整源码。
为什么自编译
- 只加入自己需要的模块,降低资源占用
- 把 .py 编译成中间码烧进固件,方便量产、一定程度保护代码
- 内置 smartconfig 类 C 模块,比纯 Python 实现更省内存、更稳定
详细好处见 esp32-s2-mpy-smartconfig 和 esp32-mpy-code-to-bin。
版本与结构变化
- micropython v1.28.0(2026-04-06),
ports/esp32/README.md推荐 ESP-IDF v5.5.1,同时支持 v5.3 / v5.4 / v5.4.1 / v5.4.2;本文使用 v5.3.2。 - 与老文(v1.20 + IDF v4.4.5)相比,有三个直接影响移植的差异:
MICROPY_SOURCE_PORT列表从ports/esp32/main/CMakeLists.txt移到了ports/esp32/esp32_common.cmake,注入 C 模块的位置变了- 端口源码从
STATIC宏改为普通static,照抄老代码会编译报错 - IDF 5.x 的
esp_smartconfig.h位于components/esp_wifi/include/,smartconfig 已并入 esp_wifi 组件
NixOS 环境要点
NixOS 不能直接照搬官方 ubuntu 流程,需要处理几个点:
- ESP-IDF 预编译工具链是动态链接的,依赖
/lib64/ld-linux-x86-64.so.2。NixOS 默认没有,需要系统层启用 nix-ld(或等价兼容),否则riscv32-esp-elf-gcc直接报No such file or directory。 source export.sh会因为没安装 xtensa-esp-elf / gdb / openocd 等非 C3 工具而报错退出。实际编译 esp32-c3 只需要 riscv32 工具链 + cmake + ninja + python 环境,手动注入即可,见下面脚本。- espressif 的预编译工具(如 esp-clang)依赖
libxml2.so.2,而 nix 仓库里是libxml2.so.16。用 LD_LIBRARY_PATH + 软链兼容,社区 rust 项目 esp-idf-sys 也是这么处理的。 - NixOS 系统 PATH 里的 cmake 是 4.x、ninja 是 1.13,IDF 要求固定版本,脚本需要把 IDF 自带的 cmake 3.30.2 / ninja 1.12.1 放到 PATH 前面。
IDF 工具版本可以直接从 tools/tools.json 读推荐值:riscv32-esp-elf esp-13.2.0_20240530、cmake 3.30.2、ninja 1.12.1。
flake.nix 开发环境
项目 devShell 由 flake.nix 引入 flake_pkgs_let.nix 的配置组。编译固件需要 gcc(host,编 mpy-cross)、make、git、curl、unzip、python3、jq,这些在基础组都有;esp-idf 本体和工具链复用项目目录 .embuild/espressif(rust esp-idf-sys 产物,同样是标准 IDF 目录布局)。
flake.nix
以下为项目 flake.nix 完整内容(隐去项目名):
flake.nix (74 行)
| |
flake_pkgs_let.nix
所有包组集中在一个文件,项目 flake.nix 按需 inherit。固件编译相关的重点是 espPackages(esptool / espflash / mpremote / python3 等)和 basePackages(gcc / make / git / curl / unzip / jq)。完整内容如下:
flake_pkgs_let.nix (317 行)
| |
编译脚本
脚本做这些事:
clone:浅克隆 micropython v1.28.0 到构建目录patch:把mpy-fw/目录下全部.c模块复制进ports/esp32/,并在esp32_common.cmake的MICROPY_SOURCE_PORT逐个追加(幂等)- 注入 IDF 环境:
IDF_PATH/IDF_TOOLS_PATH/IDF_PYTHON_ENV_PATH,PATH 前置 venv + riscv32 + cmake + ninja +$IDF_PATH/tools,LD_LIBRARY_PATH 补 libxml2 兼容 make -C mpy-cross(host gcc)make submodules(第一次会拉取网络依赖,包括组件管理器要的 espressif/mdns)make BOARD=ESP32_GENERIC_C3(增量)- 复制
firmware.bin/micropython.elf/micropython.map并打印 SHA-256 - 校验:ELF 里有各模块
*_user_cmodule符号(当前 esptouch_native / coretemp)、生成的genhdr/moduledefs.h登记了模块、esptool 能解析镜像
下面的脚本是项目脚本的精简版,目录名做了泛化(fw-build / fw-bin / mpy-fw)。
mpy-build.sh (224 行)
| |
注意首次 make 会通过 IDF 组件管理器拉取 espressif/mdns(main/idf_component.yml 声明),需要网络;之后都是增量构建。
esptouch_native 模块
Python API
esptouch_native.start():开始 ESP-Touch/AirKiss;已在运行则无副作用esptouch_native.stop():请求停止,幂等esptouch_native.success():是否已收到 SSID/密码esptouch_native.info():返回(ssid, password, type, token)esptouch_native.active():smartconfig 是否运行中- 常量:
TYPE_UNKNOWN = -1、TYPE_ESPTOUCH = 0、TYPE_AIRKISS = 1、TYPE_ESPTOUCH_AIRKISS = 2
与老文的差异
和 esp32-s2-mpy-smartconfig 的 smartconfig.c 相比主要改动:
- 模块名用
esptouch_native,暴露start/stop/success/info/active STATIC改成static(v1.28 已移除 STATIC 宏)- 生命周期由 FreeRTOS 事件组管理:
start()建任务,收到凭据或stop()时任务内esp_smartconfig_stop()并自删,支持反复 start/stop - 事件回调和 MicroPython 任务之间用
portMUX_TYPE自旋锁保护凭据缓冲,任意时刻读success()/info()都安全 - WiFi 未启动时自动以 STA 模式拉起,但建议调用方先
WLAN(STA_IF).active(True) - 错误统一转
OSError,详细码打到 ESP_LOG
完整源码
esptouch_native.c (273 行)
| |
coretemp 模块(芯片内置温度传感器)
micropython 官方固件没有提供读芯片内置温度(核心温度)的 Python API。参考 esp32 s2 C3 在micropython下使用内置温度传感器,基于 IDF v5.3.2 的 driver/temperature_sensor.h(handle API)实现 coretemp。
Python API
coretemp.init([min_c, max_c]):安装并启动传感器,量程默认 10~50℃,可选传 min/max;已启用时幂等coretemp.read():返回当前核心温度(float,摄氏度)coretemp.stop():停止传感器,幂等
与老文的差异
- 模块名
coretemp;错误不再ESP_ERROR_CHECK(会重启设备),统一转OSError并打 ESP_LOG - init 支持量程参数、启停幂等,重复调用安全
- v1.28 端口源码
STATIC已换成static
使用方法
| |
内置传感器读数通常比环境温度高 1~3℃,稳定环境可校准后作为参考温度。
完整源码
coretemp.c (106 行)
| |
编译与验证
| |
验证模块确实进固件:
build-ESP32_GENERIC_C3/genhdr/qstrdefs.generated.h出现QDEF1(MP_QSTR_esptouch_native, ...)和QDEF1(MP_QSTR_coretemp, ...)build-ESP32_GENERIC_C3/genhdr/moduledefs.h的模块注册表里有MODULE_DEF_ESPTOUCH_NATIVE和MODULE_DEF_CORETEMP- ELF 里能查到
esptouch_native_user_cmodule、coretemp_user_cmodule符号 esptool.py image_info firmware.bin能正常解析为 ESP32-C3 镜像
本次构建产物 SHA-256(bin 约 1.73MB):
| |
相关文章
- esp32自行编译micropython固件并支持smartconfig方法 —— 老版本 ubuntu + v1.20 流程,本文是其 v1.28 + NixOS 升级版
- esp32 micropython添加C模块 —— 添加 C 模块的通用方法(v1.20 的 CMakeLists 位置与 v1.28 不同)
- esp32自行编译micropython固件并添加基于python的模块 —— 添加 py 模块到固件
- esp32 s2 C3 在micropython下使用内置温度传感器 —— 内置温度传感器参考,本文 coretemp 模块实现来源(v1.22.1 + IDF v5.0.4)
- micropython代码压缩和简单加密 mpy-cross —— mpy-cross 用法
- nixos 从0实现全集(flakes 篇) —— NixOS flakes 基础,本文 flake 是其实际应用