C语言 嵌入式系统中的启动代码流程,引导加载程序的概念?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3393611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Flow of Startup code in an embedded system , concept of boot loader?
提问by Renjith G
I am working with an embedded board , but i don't know the flow of the start up code(C/assembly) of the same.
我正在使用嵌入式板,但我不知道相同的启动代码(C/汇编)的流程。
Can we discuss the general modules/steps acted upon by the start up action in the case of an embedded system.
在嵌入式系统的情况下,我们能否讨论启动操作所作用的一般模块/步骤。
Just a high level overview(algorithmic) is enough.All examples are welcome.
只需高级概述(算法)就足够了。欢迎所有示例。
/Kanu__
/卡努__
回答by Yann Ramin
- CPU gets a power on reset, and jumps to a defined point: the reset vector, beginning of flash, ROM, etc.
- The startup code (crt - C runtime) is run. This is an important piece of code generated by your compiler/libc, which performs:
- Configure and turn on any external memory (if absolutely required, otherwise left for later user code).
- Establish a stack pointer
- Clear the .bss segment (usually).
.bssis the name for the uninitialized (or zeroed) global memory region. Global variables, arrays, etc which don't have an initializing value (beyond 0) are located here. The general practice on a microcontroller is to loop over this region and set all bytes to 0 at startup. - Copy from the end of .text the non-const .data. As most microcontrollers run from flash, they cannot store variable data there. For statements such as
int thisGlobal = 5;, the value ofthisGlobalmust be copied from a persistent area (usually after the program in flash, as generated by your linker) to RAM. This applies to static values, and static values in functions. Values which are left undefined are not copied but instead cleared as part of step 2. - Perform other static initializers.
- Call
main()
- CPU 获得上电复位,并跳转到一个定义的点:复位向量、闪存开始、ROM 等。
- 启动代码(crt - C 运行时)运行。这是由您的编译器/libc 生成的一段重要代码,它执行:
- 配置并打开任何外部存储器(如果绝对需要,否则留给以后的用户代码)。
- 建立堆栈指针
- 清除 .bss 段(通常)。
.bss是未初始化(或归零)全局内存区域的名称。没有初始化值(超过 0)的全局变量、数组等位于此处。微控制器的一般做法是在该区域上循环并在启动时将所有字节设置为 0。 - 从 .text 的末尾复制非常量的 .data。由于大多数微控制器从闪存运行,它们无法在那里存储可变数据。对于诸如 之类的语句
int thisGlobal = 5;,thisGlobal必须将的值从持久区域(通常在闪存中的程序之后,由链接器生成)复制到 RAM。这适用于静态值和函数中的静态值。未定义的值不会被复制,而是作为步骤 2 的一部分被清除。 - 执行其他静态初始化程序。
- 称呼
main()
From here, your code is run. Generally, the CPU is left in an interrupts-off state (platform dependent).
从这里,您的代码运行。通常,CPU 处于中断关闭状态(取决于平台)。
回答by zdav
Pretty open-ended question, but here are a few things I have picked up.
相当开放式的问题,但这里有一些我已经拾起的东西。
For super simple processors, there is no true startup code. The cpu gets power and then starts running the first instruction in its memory: no muss no fuss.
对于超级简单的处理器,没有真正的启动代码。cpu 获得电源,然后开始运行其内存中的第一条指令:不用大惊小怪。
A little further up we have mcu's like avr's and pic's. These have very little start up code. The only thing that really needs to be done is to set up the interrupt jump tablewith appropriate addresses. After that it is up to the application code (the only program) to do its thing. The good news is that you as the developer doesn't generally have to worry about these things: that'swhat libc is for.
再往上一点,我们有像 avr 和 pic 这样的 mcu。这些有很少的启动代码。唯一真正需要做的是用适当的地址设置中断跳转表。之后,由应用程序代码(唯一的程序)来做它的事情。好消息是,作为开发人员的您通常不必担心这些事情:这就是libc 的用途。
After that we have things like simple arm based chips; more complicated than the avr's and pic's, but still pretty simple. These also have to setup the interrupt table, as well as make sure the clock is set correctly, and start any needed on chip components (basic interrupts etc.). Have a look at this pdf from Atmel, it details the start up procedure for an ARM 7 chip.
之后,我们有了简单的基于手臂的芯片之类的东西;比 avr 和 pic 更复杂,但仍然很简单。这些还必须设置中断表,并确保正确设置时钟,并启动任何需要的片上组件(基本中断等)。看看Atmel 的这个 pdf,它详细介绍了 ARM 7 芯片的启动程序。
Farther up the food chain we have full-on PCs (x86, amd64, etc.). The startup code for these is really the BIOS, which are horrendously complicated.
在食物链的更上游,我们拥有完整的 PC(x86、amd64 等)。这些的启动代码实际上是 BIOS,它们非常复杂。
回答by marr75
The big question is whether or not your embedded system will be running an operating system. In general, you'll either want to run your operating system, start up some form of inversion of control (an example I remember from a school project was a telnet that would listen for requests using RL-ARM or an open source tcp/ip stack and then had callbacks that it would execute when connections were made/data was received), or enter your own control loop (maybe displaying a menu then looping until a key has been pressed).
最大的问题是您的嵌入式系统是否将运行操作系统。一般来说,你要么想要运行你的操作系统,要么启动某种形式的控制反转(我记得一个学校项目的例子是一个 telnet,它会使用 RL-ARM 或开源 tcp/ip 侦听请求堆栈,然后在建立连接/接收数据时执行回调),或进入您自己的控制循环(可能显示菜单然后循环直到按下某个键)。
回答by Rishad
Functions of Startup Code for C/C++
C/C++启动代码的功能
- Disables all interrupts
- Copies any initialized data from ROM to RAM
- Uninitialized data area is set to zero.
- Allocates space for and initializes the stack
- Initializes the processor's stack pointer
- Creates and initializes the heap
- Executes the constructors and initializers for all global variables (C++ only)
- Enables interrupts
- Calls main
- 禁用所有中断
- 将任何初始化数据从 ROM 复制到 RAM
- 未初始化的数据区设置为零。
- 为堆栈分配空间并初始化堆栈
- 初始化处理器的堆栈指针
- 创建并初始化堆
- 执行所有全局变量的构造函数和初始值设定项(仅限 C++)
- 启用中断
- 调用 main
回答by Jijo
Where is "BOOT LOADER" placed then? It should be placed before the start-up code right? As per my understanding, from the reset vector the control goes to the boot loader. There the code waits for a small period of time during which it expects for data to be flashed/downloaded to the controller/processor. If it does not detect a data then the control gets transferred to the next step as specified by theatrus. But my doubt is whether the BOOT LOADER code can be re-written. Eg: Can a UART bootloader be changed to a ETHERNET/CAN bootloader or is it that data sent using any protocol are converted to UART using a gateway and then flashed.
那么“BOOT LOADER”放在哪里?应该放在启动代码之前吧?根据我的理解,控制权从重置向量转到引导加载程序。在那里代码等待一小段时间,在此期间它期望数据被刷入/下载到控制器/处理器。如果它没有检测到数据,那么控制将被转移到剧院指定的下一步。但我怀疑是否可以重新编写 BOOT LOADER 代码。例如:可以将 UART 引导加载程序更改为 ETHERNET/CAN 引导加载程序,还是使用任何协议发送的数据使用网关转换为 UART 然后刷新。

