tinygo是独立编译器,不支持//go:build等指令及os/net等标准库包;必须用tinygo build -target指定硬件平台,仅导入machine、time(有限)等兼容包,并显式configure引脚。

不能直接跑标准 Go,必须用 TinyGo,且必须放弃“移植现有代码”的幻想。
tinygo build 为什么报 unsupported compiler
因为 TinyGo 不是 Go 的编译器插件,而是独立重写的工具链——它不识别 //go:build、//go:embed,也不加载 go.mod 中的非 TinyGo 兼容包。你用 go build 能过的代码,tinygo build 很可能在第一行就失败。
- 常见错误:
undefined: os.Stdout、error: unsupported compiler directive: //go:build - 根本原因:TinyGo 裁剪了
os、log、net等依赖系统调用的包,bare-metal target 下默认不可用 - 正确做法:只导入
machine、time(有限)、unsafe和 TinyGo 自带的runtime;避免任何第三方包(如golang.org/x/sys)
machine.Pin.Configure 怎么设推挽/上拉才不白忙活
配置引脚不是写个 pinMode() 就完事,TinyGo 要求显式调用 Configure(),且参数组合错一点就静默失效——尤其在 ATSAMD 或 RP2040 上。
- 推挽输出(如驱动 LED):
led.Configure(machine.PinConfig{Mode: machine.PinOutput}),之后用led.High()/led.Low() - 上拉输入(如读按键):
button.Configure(machine.PinConfig{Mode: machine.PinInputPullup})—— 注意不是PinInput+ 外部电阻,PinInputPullup才启用内部上拉 - RP2040 支持
PinInputPulldown,但 ATSAMD 系列不支持,硬配不会报错,但实际没生效 - 配置必须在
main()开头一次性完成,运行时重复调用Configure()多数 target 会忽略
machine.Sleep() 三种模式怎么选才真省电
time.Sleep() 在 MCU 上只是协程挂起,CPU 仍在跑;真正降功耗得靠 machine.Sleep() 触发硬件级休眠,但每种模式行为差异极大,选错等于白睡。
-
machine.IDLE:CPU 停,外设全开(UART/I2C/ADC),唤醒快(微秒级),功耗约 1–5 mA —— 适合等串口数据或传感器中断 -
machine.DEEPSLEEP:关掉大部分时钟域,仅 RTC 和唤醒引脚供电,功耗压到 10–100 μA,但唤醒后需重初始化所有外设,GPIO 状态不保留 -
machine.STANDBY:功耗最低,但部分芯片(如 STM32)需额外配置备份寄存器才能保存关键状态 - 关键坑:DEEPSLEEP 模式下还依赖未持久化的全局变量,唤醒后值全为零;正确做法是把状态写进 RTC 备份寄存器或 EEPROM
- 唤醒源必须手动使能:比如按钮唤醒,得提前配置引脚为外部中断,
machine.Sleep()本身不注册任何唤醒源
二进制体积和启动内存怎么压到 KB 级
TinyGo 默认生成的固件仍可能超限,尤其在 RAM ≤64KB、Flash ≤256KB 的 MCU 上。光靠 tinygo build 不够,得主动干预链接与运行时。
- 强制静态链接:
TINYGO_TARGET=your-board tinygo build -o firmware.hex -target=your-board ./main.go,别漏-target - 裁剪调试信息:
-ldflags="-s -w"可减体积 20%+,对 Flash 紧缺的设备至关重要 - 禁用反射和 GC(若不需要):加
-gc-flag=-d=disable-gc和-tags=norace,可进一步压小 runtime - 字符串拼接不用
fmt.Sprintf:改用unsafe.String+ 手动填充字节数组,避免隐式堆分配 - 验证输出:
size firmware.hex查各段大小,file firmware.hex确认是裸机格式(不含 ELF header 或 dynamic section)
最易被忽略的一点:哪怕代码逻辑完全正确,只要没在 main() 开头调用 machine.Init()(部分 target 需要),或没确认目标板的 tinygo targets 输出里真包含你的型号(比如 ESP32-C3 是 esp32c3,不是 esp32),烧录后就是黑屏或复位循环——这种问题不会报错,只会沉默。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











