11

我正在使用嵌入式板,但我不知道相同的启动代码(C/程序集)的流程。

在嵌入式系统的情况下,我们能否讨论启动操作所执行的一般模块/步骤。

只是一个高级概述(算法)就足够了。欢迎所有示例。

/卡努__

4

5 回答 5

27
  1. CPU 上电复位,并跳转到定​​义的点:复位向量、闪存的开头、ROM 等。
  2. 运行启动代码(crt - C 运行时)。这是您的编译器/libc 生成的一段重要代码,它执行:
    1. 配置并打开任何外部存储器(如果绝对需要,否则留给以后的用户代码使用)。
    2. 建立堆栈指针
    3. 清除 .bss 段(通常)。.bss是未初始化(或归零)全局内存区域的名称。没有初始化值(超过 0)的全局变量、数组等位于此处。微控制器的一般做法是在该区域上循环并在启动时将所有字节设置为 0。
    4. 从 .text 的末尾复制非 const .data。由于大多数微控制器都是从闪存运行的,因此它们无法在其中存储可变数据。对于诸如 的语句int thisGlobal = 5;,必须将 的值thisGlobal从持久区域(通常在闪存中的程序之后,由链接器生成)复制到 RAM。这适用于静态值和函数中的静态值。未定义的值不会被复制,而是作为步骤 2 的一部分被清除。
    5. 执行其他静态初始化程序。
    6. 称呼main()

从这里开始运行您的代码。通常,CPU 处于中断关闭状态(取决于平台)。

于 2010-08-03T04:58:57.320 回答
3

相当开放式的问题,但这里有一些我收集的东西。

对于超简单的处理器,没有真正的启动代码。cpu 获得电源,然后开始运行其内存中的第一条指令:no muss no fuss。

再往上一点,我们有像 avr's 和 pic's 这样的 mcu。这些启动代码很少。唯一真正需要做的就是用适当的地址设置中断跳转表。之后,由应用程序代码(唯一的程序)来做它的事情。好消息是,作为开发人员,您通常不必担心这些事情:就是libc 的用途

之后我们就有了简单的基于手臂的芯片之类的东西;比 avr 和 pic 更复杂,但仍然很简单。这些还必须设置中断表,确保时钟设置正确,并启动任何需要的片上组件(基本中断等)。看看Atmel 的这个 pdf,它详细介绍了 ARM 7 芯片的启动过程。

在食物链的更远处,我们拥有完整的 PC(x86、amd64 等)。这些的启动代码实际上是 BIOS,它非常复杂

于 2010-08-03T05:14:13.340 回答
1

最大的问题是您的嵌入式系统是否将运行操作系统。一般来说,你要么想运行你的操作系统,要么启动某种形式的控制反转(我记得一个学校项目的例子是一个 telnet,它可以使用 RL-ARM 或开源 tcp/ip 来监听请求堆栈,然后在建立连接/接收数据时执行回调),或者进入您自己的控制循环(可能显示一个菜单然后循环直到按下一个键)。

于 2010-08-03T04:58:15.917 回答
1

C/C++ 启动代码的功能

  1. 禁用所有中断
  2. 将任何初始化数据从 ROM 复制到 RAM
  3. 未初始化的数据区设置为零。
  4. 为堆栈分配空间并初始化堆栈
  5. 初始化处理器的堆栈指针
  6. 创建并初始化堆
  7. 执行所有全局变量的构造函数和初始化程序(仅限 C++)
  8. 启用中断
  9. 调用主
于 2015-06-09T08:04:31.620 回答
0

那么“BOOT LOADER”放在哪里呢?它应该放在启动代码之前吧?据我了解,从复位向量控制转到引导加载程序。代码在那里等待一小段时间,在此期间它期望数据被刷新/下载到控制器/处理器。如果它没有检测到数据,则控制将转移到 theatrus 指定的下一步。但我怀疑 BOOT LOADER 代码是否可以重写。例如:可以将 UART 引导加载程序更改为 ETHERNET/CAN 引导加载程序,还是使用任何协议发送的数据使用网关转换为 UART 然后刷新。

于 2010-08-03T09:19:55.743 回答