嵌入式开发:MCU启动代码的隐藏世界

更新时间: 2022-08-26 10:28:31来源: 粤嵌教育浏览量:7831

  嵌入式开发人员观看固件在微控制器调试器上运行几乎是一种神奇的体验。按下 IDE 中的那个绿色小按钮,进度条在显示屏上快速完成,直到最后屏幕闪烁,一行代码用 main 一词突出显示。幕后发生了如此多的事情,几乎令人难以置信!让我们检查在到达程序 main 之前发生了什么。

  一旦程序被加载到微控制器上,微处理器首先读取复位向量开始执行。复位向量保存程序的第一条指令所在的内存地址。然而,这些第一条指令并不是 main 中存在的应用程序的开始,而是通常隐藏在启动代码中的初始化例程。

  启动代码执行许多关键功能,这些功能是准备微控制器以开始执行开发人员的应用程序所必需的。启动代码所遵循的确切步骤因微控制器而异,但通常第一步是初始化系统时钟。系统时钟稳定后,必须通过将初始化变量复制到 RAM 来设置内存环境。此过程通常称为“C 向下复制”。这个想法是微控制器的内存被设置为运行应用程序代码将在其下运行的 C 环境。

  启动代码还将初始化堆栈指针。堆栈是存储自动变量、函数参数、中断帧和函数返回地址的内存区域。裸机系统(没有 RTOS 的系统)将只有一个堆栈区域,默认情况下,该区域的大小通常为 0x400 深度。嵌入式开发人员启动代码通常会有一些旨在设置堆栈指针顶部的汇编语言指令。

  一旦时钟被初始化,C 向下复制并且栈顶已经被识别,最后一步是跳转到或调用 main 。一些启动代码将执行跳转到 main 而不是对 main 的函数调用,因为这可以节省一些宝贵的堆栈空间字节。但是,无论使用哪种方法,开发人员都会发现自己处于 main 的开头,调试器暂停并等待执行应用程序的权限。

  


  然而,开发人员通常完全不知道在到达 main 开头之前已执行的所有代码。但是,如果开发人员取消选中“run to main”选项,应用程序不会在 main 的第一行中断,而是在启动代码的第一条指令处中断。然后,开发人员可以在到达 main 之前单步执行用于设置处理器的每一行代码。正如人们所预料的那样,启动代码通常因开发环境而异。在项目开始时,单步执行启动代码通常很有用,因为在到达 main 之前,嵌入式开发人员永远不知道会设置什么有趣的东西。

  如果混合中有引导加载程序,微控制器的启动代码会变得更加复杂。当应用程序启动时,可能会有一段代码执行快速检查以确定是否应执行主应用程序或是否应执行固件更新应用程序。如果执行引导加载程序以更新固件或简单地以已知状态启动系统并执行系统完整性检查,则启动代码可能需要重置堆栈指针,而不是简单地对其进行初始化。

  嵌入式软件开发人员过去了解他们软件的每一个角落。由于微控制器已经采用 32 位,因此开发固件的方式发生了迅速变化。处理器如何启动和代码执行的细节只是开始隐藏在幕后的第一段代码。有一天,嵌入式开发人员可能只知道微控制器级别发生的事情,就像应用程序开发人员了解服务器微处理器级别发生的事情一样多。尽管似乎失去了洞察力,但抽象和隐藏代码的级别无疑将帮助开发人员更快地以更低的成本编写代码,而明显的魔术在幕后起作用。

免费预约试听课