智能小车(六):Arduino程序的实际执行机制

星期三, 11月 27, 2024 | 3分钟阅读 | 更新于 星期日, 12月 8, 2024

YuanFeng Xie

历史回顾

引言

很多Arduino初学者都会困惑:为什么Arduino程序只需要写setup()和loop()这两个函数就能运行?程序的入口main()函数去哪了?今天就让我们揭开Arduino程序执行的神秘面纱。

安全须知

    / [pdf]

表象与本质

我们看到的Arduino程序

在Arduino IDE中,一个最基本的程序是这样的:

void setup() {
    // 初始化代码
}

void loop() {
    // 循环执行的代码
}

看起来非常简单,但这只是表象。

实际的执行过程

实际上,Arduino程序的执行过程是这样的:

int main(void) {
    init();         // 初始化Arduino硬件
    initVariant();  // 初始化板子特定设置
    
    setup();        // 调用用户的setup()
    
    while(true) {
        loop();     // 调用用户的loop()
        
        if (serialEventRun) 
            serialEventRun();  // 处理串口事件
    }
    return 0;
}

这个main()函数藏在Arduino核心库中,对用户完全透明。

编译过程揭秘

代码转换流程

当你点击Arduino IDE的"编译"按钮时,实际发生了这些事:

// 你的.ino文件
void setup() { ... }
void loop() { ... }

// 转换为
#include <Arduino.h>
void setup();
void loop();
// 你的代码内容
  1. 与核心库合并
  2. 编译链接
  3. 生成最终程序

文件位置

Arduino核心库的关键文件位置:

  • Windows: C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\
  • Mac: /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/
  • Linux: /usr/share/arduino/hardware/arduino/avr/cores/arduino/

深入理解执行流程

完整的启动流程

  1. 硬件上电或复位
  2. bootloader启动
  3. main()函数开始
  4. 硬件初始化
  5. 调用setup()
  6. 进入loop()循环

关键代码解析

Arduino核心库中的初始化过程:

void init() {
    // 配置时钟
    // 初始化定时器
    // 配置默认引脚状态
    // 使能中断
    // ...其他硬件初始化
}

void initVariant() {
    // 针对特定开发板的初始化
}

实用技巧

查看编译细节

想要了解编译过程,可以:

  1. 打开Arduino IDE
  2. 选择 文件 → 首选项
  3. 勾选"编译时显示详细输出"

查看临时文件

编译过程生成的临时文件位于:

  • Windows: %TEMP%\arduino_build_*
  • Mac/Linux: /tmp/arduino_build_*

实际编译命令示例

avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions 
-ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD 
-flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10813 
-DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR sketch.cpp -o sketch.cpp.o

原理图解

用户的.ino文件
Arduino IDE处理
 ├── 添加头文件
 ├── 添加声明
 └── 生成.cpp
与核心库合并
 ├── main.cpp
 ├── 硬件库
 └── 其他文件
编译链接
生成最终程序

实际应用意义

理解Arduino的执行机制有助于:

  • 调试问题:
    • 知道程序卡在哪个阶段
    • 理解初始化过程
    • 解决启动问题
  • 优化代码:
    • 合理安排初始化顺序
    • 优化loop()执行效率
    • 避免常见陷阱
  • 开发更复杂的应用:
    • 理解中断处理
    • 实现定时任务
    • 处理硬件异常

总结

虽然Arduino IDE通过隐藏复杂的实现细节,让编程变得简单易上手,但了解其背后的执行机制对于开发更复杂的应用和解决问题都很有帮助。希望这篇文章能帮助你更深入地理解Arduino程序是如何运行的。

扩展阅读

  • Arduino官方文档:https://docs.arduino.cc/language-reference/
  • AVR GCC编译器手册:https://gcc.gnu.org/wiki/avr-gcc
  • Arduino核心库源码:https://github.com/arduino/ArduinoCore-avr

© 2024 小谢同学的修行小屋

🌱 Powered by Hugo with theme Dream.

关于我

一名喜欢RUST的菜鸟程序员

教育背景(研二在读)

  • 2019.09 - 2023.06 天津大学 · 智能与计算学部 · 网络安全专业 · 全日制 · 本科
  • 2023.09 - 2026.06 天津大学 · 智能与计算学部 · 电子信息专业 · 全日制 · 硕士研究生
浏览器漏洞挖掘项目

V8引擎的模糊测试工具改进

时间:2021.09-2022.04

内容:聚焦于优化JavaScript引擎的测试方法。研究团队基于SOAT改进部署了V8引擎测试环境,并通过分析测例覆盖率和已知CVE,优化了测试流程。

成果:成功捕获了一个谷歌引擎的逻辑漏洞,获得了修复反馈

JS引擎WASM模块漏洞挖掘研究

时间:2023.11-2024.4

内容:阅读标准手动编写了WASM语法规则,调研了主流JS引擎的WASM支持情况,并基于V8构建了WASM二进制框架。

成果:语法规则、调研报告和二进制构建框架,成功捕获特性缺陷并得到修复

数据库缺陷研究项目

关系型数据库缺陷的实证研究

时间:2022.12-2023.11

内容:通过构建统一的数据库逻辑框架,系统收集并分析了大量数据库缺陷。对777个缺陷进行了深入分析,特别聚焦SQL数据类型问题,并据此改进了模糊测试方法。

成果:构建缺陷数据集, 开发SQLT测试框架

网络协议漏洞挖掘项目

基于 RFC的 SSL/TLS模糊测试

时间:2024.4 – today

内容:梳理TLS协议模糊测试的相关工作,关注基于状态机的网络协议模糊测试方法。复现历史漏洞,了解TLS报文结构,追溯相关漏洞代码。分析RFC文档,提取字段约束,构建状态转移范式,并据此完善了TLS协议的有限状态机模型。

成果:完成相关工作调研, 漏洞复现报告, 状态范式数据集