复位时嵌入式系统会发生什么?
我对由于加电而导致的重置有疑问:
据我所知,微控制器是硬连线的,以在加电时从某些特定的内存位置(例如 0000H)开始。在0000h处,是否编写中断服务程序进行复位(堆栈指针和程序计数器等的初始化)或复位地址位于0000h(例如7000),以便微控制器跳转到7000地址并写入堆栈和PC的初始化.
谁编写了这个重置服务例程?微控制器芯片制造商(Intel 或 microchip 等)或任何程序员都可以更改此复位服务例程(例如,程序员在上电复位时将 PC 从 7000h 更改为 4000h,导致第一条指令从 4000 获取,而不是7000)。
如何将堆栈指针和程序计数器初始化为各自的初始地址,因为上电时微控制器不处于将地址放入堆栈指针和程序计数器寄存器的状态(直到复位服务程序才进行初始化)。
考虑到所有可能性,重置服务例程中应该采取哪些步骤?
I have a doubt regarding the reset due to power up:
As I know that microcontroller is hardwired to start with some particular memory location say 0000H on power up. At 0000h, whether interrupt service routine is written for reset(initialization of stack pointer and program counter etc) or the reset address is there at 0000h(say 7000) so that micro controller jumps at 7000 address and there initialization of stack and PC is written.
Who writes this reset service routine? Is it the manufacturer of microcontroller chip(Intel or microchip etc) or any programmer can change this reset service routine(For example, programmer changed the PC to 4000h from 7000h on power up reset resulting into the first instruction to be fetched from 4000 instead of 7000).
How the stack pointer and program counter are initialized to the respective initial addresses as on power up microcontroller is not in the state to put the address into stack pointer and program counter registers(there is no initialization done till reset service routine).
What should be the steps in the reset service routine considering all possibilities?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
参考您的编号:
硬件重置过程取决于处理器,并将在该部件的数据表或参考手册中完整描述,但您的描述通常是这种情况 - 不同的架构可能有细微的变化。
在 ARM Cortex-M 设备上,实际上初始 PC 和堆栈指针实际上是由硬件加载的,它们存储在复位地址并在上电时加载。然而,在一般情况下,你是对的,复位地址要么包含启动代码,要么包含启动代码的向量,在 Cortex 之前的 ARM 架构上,复位地址实际上包含跳转指令而不是真正的向量地址。无论哪种方式,C/C++ 运行时的启动代码必须至少初始化堆栈指针、初始化静态数据、执行任何必要的 C 库初始化并跳转到 main()。对于 C++,它还必须在调用 main() 之前执行任何全局静态对象的构造函数。
With reference to your numbering:
The hardware reset process is processor dependent and will be fully described in the data sheet or reference manual for the part, but your description is generally the case - different architectures may have subtle variations.
While some microcontrollers include a ROM based boot-loader that may contain start-up code, typically such bootloaders are only used to load code over a communications port, either to program flash memory directly or to load and execute a secondary bootloader to RAM that then programs flash memory. As far as C runtime start-up goes, this is either provided with the compiler/toolchain, or you write it yourself in assembler. Normally even when start-up code is provided by the compiler vendor, it is supplied as source to be assembled and linked with your application. The compiler vendor cannot always know things like memory map, SDRAM mapping and timing, or processor clock speed or what oscillator crystal is used in your hardware, so the start-up code will generally need customisation or extension through initialisation stubs that you must implement for your hardware.
On ARM Cortex-M devices in fact the initial PC and stack-pointer are in fact loaded by hardware, they are stored at the reset address and loaded on power-up. However in the general case you are right, the reset address either contains the start-up code or a vector to the start-up code, on pre-Cortex ARM architectures, the reset address actually contains a jump instruction rather than a true vector address. Either way, the start-up code for a C/C++ runtime must at least initialise the stack pointer, initialise static data, perform any necessary C library initialisation and jump to main(). In the case of C++ it must also execute the constructors of any global static objects before calling main().
正如您所说,处理器内核通常具有某种表的起始地址,可以是地址列表,也可以是像 ARM 一样执行指令的位置。包裹在该核心周围,但在芯片内部可能会有所不同。非特定于芯片供应商的内核(如 8051、mips、arm、xscale 等)将有更广泛的不同答案。例如,一些微控制器供应商会查看带引脚,如果在复位释放时带以某种方式接线,那么它会从芯片内的特殊引导闪存执行,这是一个引导加载程序,您可以使用它来对用户引导闪存进行编程。如果带子没有以某种方式系紧,那么有时它会启动您的用户代码。我知道的一个供应商仍然会引导他们的引导加载程序闪存,如果向量表具有有效的校验和,那么他们会跳转到向量表中的重置向量,否则他们会处于引导加载程序模式等待您与他们交谈。
当您使用更大的处理器(非微控制器)时,软件位于处理器外部,或者位于启动闪存(与处理器分离的芯片)上,或者在重置之前以某种方式进行管理的某些 RAM 上,等等。这些通常遵循核心规则,从地址 0xFFFFFFF0 开始或从地址 0x00000000 开始,如果那里有垃圾,哦,我们会触发未定义的指令向量,如果那是垃圾,则挂在那里或坐在无限循环中调用未定义的指令向量。这对于 ARM 来说效果很好,例如您可以构建一个带有从工厂擦除的启动闪存(所有 0xFF)的板,然后您可以使用 jtag 来停止手臂并第一次对闪存进行编程,并且您不必拆焊或套接字或预编程任何东西。只要您的引导加载程序不悬挂手臂,您就可以拥有坚不可摧的设计。 (实际上,您通常可以将手臂保持在重置状态,并且仍然可以使用 jtag 调试器进行调试,而不必担心不良代码会弄乱 jtag 引脚或挂起手臂核心)。
简而言之:有多少家不同的处理器芯片供应商?有许多不同的解决方案,您能想到的都有,并且已经部署了更多。不过,将重置处理程序地址放置在内存中的已知位置是最常见的。
编辑:
问题 2 和 3。如果您购买芯片,某些微控制器具有此受保护的引导加载程序,但即使如此,通常您也会编写产品将使用的引导代码。引导代码的一部分是初始化堆栈指针并准备内存并调出芯片的各个部分和所有这些好东西。有时芯片供应商会提供示例。如果您购买板级产品,那么您通常会找到板级支持包 (BSP),其中包含可启动板的工作示例代码,或许还可以执行一些操作。例如,beagleboard 或 open-rd 或embeddedarm.com 带有引导加载程序(u-boot 或其他),有些已经预装了linux。像这样的板,用户通常只是编写一些Linux应用程序/驱动程序并将它们添加到bsp中,但您并不限于此,通常欢迎您完全重写和替换引导加载程序。无论谁编写引导加载程序,都必须设置堆栈并启动硬件等。
像 Gameboy advance 或 nds 之类的系统,供应商有一些启动代码来调用您的启动代码。所以他们可能有堆栈和这样的设置,但他们正在移交给你,所以系统的大部分内容可能已经启动,你只需决定如何分割存储器,你想要你的堆栈,数据,程序,等等。
一些供应商希望对这些东西进行控制或保密,而其他供应商则不想。在某些情况下,您可能最终得到的板或芯片没有示例代码,只有一些数据表和参考手册。
如果你想进入这个行业,但你需要准备编写这个启动代码(用汇编程序),它可能会调用一些 C 代码来启动系统的其余部分,那么这可能会启动主操作系统或应用程序,或者任何。微控制器听起来就像你正在玩的东西,你的问题的答案在芯片供应商的用户指南中,一些供应商比其他供应商更好。在文档中搜索“reset”或“boot”一词,尝试找出它们的启动方案。我建议您使用“美元选票”来选择更好的供应商。一个有糟糕文档、秘密文档、糟糕支持的供应商,不要给他们你的钱,把你的钱花在那些可以免费下载、写得很好的文档、写得很好的例子和/或用户论坛上,并有全职员工到处回答问题的供应商身上。有时,除了严肃的付费客户之外,这些文档是不可用的,这取决于市场。大多数通用嵌入式系统都有公开文档。质量差异很大,但文档等都在那里。
The processor cores normally have as you say a starting address of some sort of table either a list of addresses or like ARM a place where instructions are executed. Wrapped around that core but within the chip can vary. Cores that are not specific to the chip vendor like 8051, mips, arm, xscale, etc are going to have a much wider range of different answers. Some microcontroller vendors for example will look at strap pins and if the strap is wired a certain way when reset is released then it executes from a special boot flash inside the chip, a bootloader that you can for example use to program the user boot flash with. If the strap is not tied that certain way then sometimes it boots your user code. One vendor I know of still has it boot their bootloader flash, if the vector table has a valid checksum then they jump to the reset vector in your vector table otherwise they sit in their bootloader mode waiting for you to talk to them.
When you get into the bigger processors, non-microcontrollers, where software lives outside the processor either on a boot flash (separate chip from the processor) or some ram that is managed somehow before reset, etc. Those usually follow the rule for the core, start at address 0xFFFFFFF0 or start at address 0x00000000, if there is garbage there, oh well fire off the undefined instruction vector, if that is garbage just hang there or sit in an infinite loop calling the undefined instruction vector. this works well for an ARM for example you can build a board with a boot flash that is erased from the factory (all 0xFFs) then you can use jtag to stop the arm and program the flash the first time and you dont have to unsolder or socket or pre-program anything. So long as your bootloader doesnt hang the arm you can have an unbrickable design. (actually you can often hold the arm in reset and still get at it with the jtag debugger and not worry about bad code messing with jtag pins or hanging the arm core).
The short answer: How many different processor chip vendors have there been? There are many different solutions, as many as you can think of and more have been deployed. Placing a reset handler address in a known place in memory is the most common though.
EDIT:
Questions 2 and 3. if you are buying a chip, some of the microcontrollers have this protected bootloader, but even with that normally you write the boot code that will be used by the product. And part of that boot code is to initialize the stack pointers and prepare memory and bring up parts of the chip and all those good things. Sometimes chip vendors will provide examples. if you are buying a board level product, then often you will find a board support package (BSP) which has working example code to bring up the board and perhaps do a few things. Say the beagleboard for example or the open-rd or embeddedarm.com come with a bootloader (u-boot or other) and some already have linux pre-installed. boards like that the user usually just writes some linux apps/drivers and adds them to the bsp, but you are not limited to that, you are often welcome to completely re-write and replace the bootloader. And whoever writes the bootloader has to setup the stacks and bring up the hardware, etc.
systems like the gameboy advance or nds or the like, the vendor has some startup code that calls your startup code. so they may have the stack and such setup for them but they are handing off to you, so much of the system may be up, you just get to decide how to slice up the memorires, where you want your stack, data, program, etc.
some vendors want to keep this stuff controlled or a secret, others do not. in some cases you may end up with a board or chip with no example code, just some data sheets and reference manuals.
if you want to get into this business though you need to be prepared to write this startup code (in assembler) that may call some C code to bring up the rest of the system, then that might start up the main operating system or application or whatever. Microcotrollers sounds like what you are playing with, the answers to your questions are in the chip vendors users guides, some vendors are better than others. search for the word reset or boot in the document to try to figure out what their boot schemes are. I recommend you use "dollar votes" to choose the better vendors. A vendor with bad docs, secret docs, bad support, dont give them your money, spend your money on vendors with freely downloadable, well written docs, with well written examples and or user forums with full time employees trolling around answering questions. There are times where the docs are not available except to serious, paying customers, it depends on the market. most general purpose embedded systems though are openly documented. the quality varies widely, but the docs, etc are there.
完全取决于您使用的控制器/嵌入式系统。我在游戏开发中使用的 IP 点位于 RAM 中的起始地址。编译器提供的引导代码初始化静态/常量内存,设置堆栈指针,然后跳转执行到某种 main() 例程。较旧的系统也从固定地址启动,但您必须手动设置堆栈、启动向量表以及汇编器中的其他内容。起始汇编程序文件的通用名称是 CRT0.s,代表我所做的事情。
所以 1. 你是对的。微处理器必须从某个固定地址启动。
2. ISR 可以由制造商或编译器创建者提供,也可以您自己编写,具体取决于相关系统的复杂性。
3. 堆栈和初始程序员计数器通常通过某种引导程序例程进行处理,这些例程通常可以用您自己的代码覆盖。见上文。
最后:步骤取决于芯片。如果出现任何类型的电源中断,RAM 可能会被扰乱,所有 ISR 向量表和启动代码都应重写,并且应用程序应像刚刚启动一样运行。但是,请阅读您的文档!我确信那里有特定于平台的东西可以针对您的具体情况回答这些问题。
Depends completely on the controller/embedded system you use. The ones I've used in game development have the IP point at a starting address in RAM. The boot strap code supplied from the compiler initializes static/const memory, sets the stack pointer, and then jumps execution to a main() routine of some sort. Older systems also started at a fixed address, but you manually had to set the stack, starting vector table, and other stuff in assembler. A common name for the starting assembler file is CRT0.s for the stuff I've done.
So 1. You are correct. The microprocessor has to start at some fixed address.
2. The ISR can be supplied by the manufacturer or compiler creator, or you can write one yourself, depending on the complexity of the system in question.
3. The stack and initial programmer counter are usually handled via some sort of bootstrap routine that quite often can be overriden with your own code. See above.
Last: The steps will depend on the chip. If there is a power interruption of any sort, RAM may be scrambled and all ISR vector tables and startup code should be rewritten, and the app should be run as if it just powered up. But, read your documentation! I'm sure there is platform specific stuff there that will answer these for your specific case.