裸机或小RTOS项目最怕裸new/delete:早期return、错误分支、构造成功后某一步失败,都会漏块。C++的RAII把“获取资源”放构造、“释放资源”放析构,智能指针只管所有权。资源受限MCU别直接用标准堆,走unique_ptr+静态缓冲/内存池+定制deleter,既能自动回收,又不引入malloc碎片。
嵌入式多传感器看板别让UI直接读硬件:正确结构是“采集线程/进程→线程安全队列→固定长度环形缓冲→Web定时拉数据画图”。这样串口、CAN、MQTT各跑各的,前端只管最近N点曲线,长时间运行不爆内存、不卡浏览器。
CDC核心不是“都会写”,而是按信号类型选型:单比特电平用同步器,窄脉冲用展宽/toggle,多比特低频配置用手握,持续数据流用异步FIFO。多比特总线直接打两拍最易出错,各bit走线延迟不同会采到中间态。
嵌入式现场拿到“PC=0x08004A2C、LR=0x08001234”这类崩溃日志,手工对着反汇编翻行太低效。固件编译时保留ELF,用Python的pyelftools读符号表、DWARF行号,可把原始地址自动还原成“函数名+源文件+行号”,批量处理上百台设备的crash log也没压力。
MCU上MicroPython慢,通常不在“Python语言”本身,而在字节码解释、堆分配、属性查找和导入开销。按“先测热点、再减分配、最后native/viper”的顺序改,普通数值循环做到3倍加速很现实,极端内存拷贝可更高。
嵌入式C审查靠人眼翻malloc/free容易漏。实用做法是“Python轻筛做全量初检,clang/cppcheck做深度路径分析,报告进CI”:轻筛抓明显坏味道,深分析走AST/CFG查跨分支空指针和未释放路径,误报用白名单和抑制规则压下去。
实时控制、ADC采样、电机电流环里若每个周期都通过基类指针调虚函数,代价不只是“一次间接跳转”:先取对象vptr、再查vtable槽、再间接call,且编译器因不知道最终类型而不敢内联。Cortex-M0/M3没有分支预测,间接调用流水线损失更明显;M4/M7虽有预测,但热路径仍应尽量直调。优化原则不是“全面禁虚函数”,而是先定位热点,再用去虚拟化、CRTP、variant/函数表把vtable查找消掉。
外设配置最怕手写魔法位:0x40011000、(1
自研ARM板跑Linux,最稳的不是手工交叉编译一堆包,而是用Yocto把工具链、U-Boot、内核、设备树、根文件系统全部元数据化。换SoC只改machine和层,换应用只改image配方,重复构建可复现。整体按“建层—写machine—挂内核/dtb—写image—bitbake—烧写排错”六步落地。
嵌入式常量别再靠#define硬算。宏没有类型、没有作用域,复杂分频/CRC/查表容易写错;constexpr用普通C++函数让编译器在构建期算出结果,生成后直接进只读段,上电零初始化、不占RAM、不跑除法。
换MCU最怕业务层直接调厂商HAL:stm32f1xx_hal.c里写HAL_UART_Transmit,gd32f10x.c里又要改usart_data_transmit,换一次改一次。稳定做法是“应用只依赖自有HAL接口,厂商库关在platform实现层”,STM32/GD32/RISC-V都按同一头文件出实现,构建宏切换目录即可。
在MCU底层开发里,改一个寄存器位最常见也最危险。写REG |= (1
裸机或RTOS项目里,最容易出现“驱动调业务”的硬耦合:UART中断里直接ParseModbus、按键扫描里直接ControlRelay、定时器回调里直接BlinkLED。换协议、换板卡就要改驱动源文件,维护成本陡增。用函数指针做回调注册,把“事件发生”和“事件处理”拆开,驱动只负责收数据、置标志、调指针,应用层注册具体函数,复用性会明显提升。