What is the basic significance of bootloader and startup code in the embedded systems? What is the difference?
Where are these placed?? And an overview of the flow from power on reset to the application start. Considering any platform in general.
What is the basic significance of bootloader and startup code in the embedded systems? What is the difference?
Where are these placed?? And an overview of the flow from power on reset to the application start. Considering any platform in general.
All processors have some processor-specific way of starting. Usually there is some address in the processors address space, let’s say 0xFFFF0000 for example, where the processor reads that memory. The value it finds it uses as an address to code and starts executing code at that address.
What the hardware either chip or board designers would do is make sure that a flash or some other form of non volatile memory (ROM) is mapped into that address space, so that the processor's boot code and that address to the boot code at that special address, will be there for the processor to read when the power is turned on and reset is released (RAM is volatile, turn off the power and you lose the data, turn it back on and you get some random data until such time as the RAM is written with something else).
So the first code a processor runs is often called the bootloader, and some may debate that the latter half of the word loader implies that this code can both "boot" the operating system or whatever application is to be run, and also as a second function provide a "loader" capability for developers. If you have ever used U-Boot or even GRUB or many other bootloaders you might understand that if you don't touch anything it will boot the default whatever, embedded application or operating system, whatever.
But if you interrupt the boot process, and interrupting that process is very specific to the platform and software, sometimes you have to push a button or short two pins together or send an escape or some other character in on a serial/UART port, etc., and then it goes into the loader mode where you might be able to change what it boots and/or instead of the bootloader loading the default program from flash/ROM it might let you for example use XMODEM or ZMODEM or an Ethernet port and protocol to load a test program into RAM, then let you run that program instead of the default program.
Some folks call the boot software a bootloader even if it doesn't allow you to interrupt the process and load some alternate program, because that boot code might be "loading" the application into RAM from non-volative storage anyway.
Not all bootloaders need to copy the application from non-volatile storage (flash/ROM, hard disk, CD-ROM, etc.) to RAM. Some systems and some applications run from the flash/ROM. A PC for example: The real bootloader in a PC is the BIOS which is a program that lives in and runs from flash/ROM. For systems with DRAM like a PC, you have to bring up the DRAM system anyway. There is a lot of code required to configure the hardware such that DRAM works, and sometimes you can see some status of this on the monitor as a PC boots. If you have SRAM in your system then it may also require some initialization, but usually not nearly as complicated as DRAM, and often it is instantly up and ready to use with little or no configuration, different processors and different systems are...different.
So the processor is out of reset, in some manner hardcoded in the processor hardware. It has found the entry point to the boot code and started executing that code. That code then in general needs to get the peripherals and RAM up and running and then run the main application. Or at least as much hardware is needed before starting that application.
Loading Linux in an embedded system can be as simple as getting RAM up, and copying the kernel from ROM to RAM, maybe preparing some registers and maybe filling in a few memory locations that the kernel looks at with maybe memory size and an alternate command line for example, then branch to the start of the kernel. You don't have to copy the kernel on some systems; you can just branch to ROM where it lives. Then Linux will bring up the rest of the system. On a PC the BIOS does a lot of stuff, like bring up video, DRAM, enumerate the PCI(e) bus peripherals, bring up the hard disk or other filesystem like devices, then using the defined by user in the BIOS hard disk or like peripheral (USB thumb drive or CD-ROM, etc.). The beginning of the file system will contain some sort of how to boot the operating system based on the rules of the BIOS code. And that may be yet another bootloader (GRUB, U-Boot, etc.), which ultimately copies the kernel or operating system startup code to RAM and then branches to it...
The terms bootloader and startup code can be used interchangeably. Some folks may get picky about them being different or subtle differences, but it usually has to do with complexity, a bootloader like U-Boot which has Ethernet drivers and file system drivers, etc. is to some extent an operating system in and of it self, either way U-Boot is very complicated.
Startup code for a microcontroller, for example, may be as simple as a few lines of code, set stack pointer, and branch to main. And the startup code/bootloader can be any level of complexity in between. As mentioned already, some embedded systems boot from and run their applications from ROM so no copy and run is needed. Others require the copy and run for the main application.
Sometimes the hardware or some other scheme gets involved. It is possible, for example, many FPGA-based solutions, where the hardware reads stuff on power up from a ROM and copies it. Then when the processor or other logic is released, your program or other data is magically there in RAM, ready to use. Even though when the power is off it lives in a ROM that you don't normally touch. The Raspberry Pi has yet another solution. The chip has two processors, one is the ARM and the other is a GPU, graphics processor, completely different instruction set, designed for math operations, etc. There is in some form, burned into the chip (likely a ROM on the chip) a small bootloader that is just enough to bring up and read the SD card. This is GPU BTW; the ARM is in reset. The GPU then reads its first bootloader file from the SD card, copies that to RAM and runs it.
That bootloader does more things, like bring up DRAM, and then copies the more complicated second (third?)-stage bootloader from the SD card to DRAM then runs that. That code likely contains the GPU application for doing the screen/display functions for the system. It also, once video and everything is ready, reads the SD card one more time and copies the ARM application from SD card to DRAM, fills in a few items in RAM (boot vector in the exception table (a branch to the kernel)) and some other items at known locations that the Linux kernel boot code wants. Then it releases reset on the ARM. The ARM at this point wakes up with its application, the kernel, magically in RAM...