Reprinted from: http://blogs.msdn.com/yunxu/archive/2007/10/09/bootloader.aspx
Embedded operating systems are becoming more and more important in embedded software development. When it comes to embedded operating systems, boot loader is an indispensable topic, whether it is Windows CE, embedded Linux, or other embedded operating systems. Most of them require boot loader to load the operating system. When we get a new board and want to run an embedded operating system on it, the first thing we need to do is to port the boot loader corresponding to the operating system. Data-relatedArticleAnalysis: In embedded development, Boot Loader usually consumes a lot of time manpower and material resources.
Why is the development of bootloader so complicated? Why does the bootloader, which is used as an aid of the embedded operating system, occupy so much development time? What is the complexity of bootloader? How can we overcome these difficulties to develop bootloader faster and better? This article takes Windows CE, a widely used embedded operating system, as an example to analyze and solve the problems mentioned above. This article will not introduce the structure function and Startup Process of the bootloader. If you do not know much about the bootloader of Windows CE, you can refer to other books to learn more about this.
1. Analysis of bootloader development difficulties
(1) hardware initialization:
after the hardware is powered on, the first command to run is the Code of bootloader (if all kinds of BIOs are ignored ). Bootloader requires hardware initialization. Then you can enter the normal logic, such as loading the OS image. Hardware initialization is tedious for software engineers. Read the specification of various types of hardware in detail. Then there is a series of operations on registers. Although the bootloader does not need to initialize all the hardware on the board, it only needs to initialize the most basic hardware that can make the loader work normally. Some Peripherals can be placed at the OS startup, it is not too late to initialize the driver during loading. Even so, there are not a few hardware to be initialized. For a typical arm system, you may need to initialize the memory controller, initialize the MMU, configure the gpio port, and configure the debugging serial port, for reading and writing RTC, if you want to download it over Ethernet, you also need to drive the network interface ...... None of these jobs are physical. Careful consideration is required. It is very likely that careless settings of a bit in the register will make the entire bootloader unable to work. Therefore, this part of content is usually sloppy and requires patience.
(2) coding and building:
because bootloader is the bottom-layer code, the assembly language must be indispensable. Even those who call "assembly dead" all day long cannot deny that the piece of code started by the system still needs the assembly language. However, assembly languages are often the "hard bones" that software engineers do not want to touch ". This also increases the difficulty of compiling bootloader.
after writing the code, of course, it is necessary to compile the machine code to run on the board. Currently, most compilers only compile code into some popular executable file formats, such as PE on Windows and elf on * nix. These executable files in the format cannot be directly run on the target device. Therefore, the operating system usually provides some tools to convert these executable files to a pure binary format before they can run on the target device. For example, fromelf tools provided by ads and romimage tools provided by Windows CE do this. Generally, we need to configure such tools, such as telling them where the code segment is placed and what the starting address is. If these parameters are not correctly configured, it is very likely that the final generated bootloader image is unavailable. Then, it cannot run if it is written to the target device. Similarly, the configuration of these parameters also needs to be carefully checked and checked step by step.
(3) development efficiency:
another difficulty in developing bootloader is its development efficiency. After some code modifications, we usually need to write the modified binary file to the flash of the target device using a burning tool, whether it is NAND or nor flash, the write process is not satisfactory. Therefore, even if you change a line of code, you need to compile the code and run the complete process. Generally, it takes about 10 minutes to get faster. In this case, you can modify the code five times in an hour and 50 times a day. The mechanical repetition of this process often makes developers feel that development efficiency is low, resulting in resentment and resistance. This is also a major disadvantage of bootloader development. One solution is to use the hardware debugging tool to directly inject the bootloader image into RAM and run it. Filling in Ram is usually faster than burning flash. However, this requires a debugging tool to initialize ram, and there are many other logical and detailed tasks to be done.
(4) debugging
The problems mentioned above are actually insurmountable. In my opinion, the biggest problem with developing bootloader is debugging. Imagine: No matter how difficult the compilation is, I still wrote it, no matter how annoying it is, I wrote it down, but when I press the reset key with excitement, the entire hardware device has no response. How do I know whether my code is correctly written or incorrect? If not, how can I locate my error? In current software development, both compiled languages and scripts usually provide corresponding Debugger for developers to locate code errors. Writing code is the most frightening thing for software engineers. If there is a problem with the code, if there is no effective means to locate the problem, the project will be "shelled" in ". If the positioning is accurate, the problem will be solved by more than half. So in the final analysis, it is still the methodology of debugging. It is difficult to debug the bootloader because there are few and unusual methods to use. Develop applications under OSProgramThe debugging methods used are usually not used in the development of bootloader. Debugging requires "extraordinary" means. The following topic describes some common debugging methods for Bootloader.
2. Some debugging skills
(1) hardware debugger
I believe many developers who have come from application development will miss debugging methods such as Set breakpoint, step into, and step over. But those things are full of debuggers. On the bare board, there is no debugger to help us. What should we do? Fortunately, we have a hardware debugger. Many CPU architectures provide corresponding hardware debuggers, such as arm cpu simulators. With the help of the hardware debugger, we can perform assembly-Level Set breakpoint, step into, and step over operations. This is very important for debugging bootloader. At least we can see whether the code we burned is correct and whether it is running. This is very precious for the first piece of code after debugging reset.
however, the hardware debugger has many disadvantages: first, they are generally expensive. If you don't need to use your own d in China, it's worth a few thousand. Secondly, most hardware simulators only support assembly-level debugging. When the Code enters the C language, the hardware debugger cannot help. Third, an inferior simulator cannot simulate the virtual memory opened by MMU. Therefore, there are many restrictions.
(2) flashing and shining-LED lights
if we cannot afford hardware simulators, or there is no such thing at hand. So we have to output some information through some hardware output ports to let us know where the code is running. Among the many ports, the simplest is probably LED light. Generally, you can use a few compilations to make the LEDs flash. In this way, we can install the LED flashing statement in the code. Let's see where our code runs or fails. It is a pity that led and so on can only Flash, it is very difficult to get more messages through the LED. For example, if we want to know the value of a variable and express it with LED flashes, I am afraid it will be a headache. It is a feasible solution to use led to flash out the moles code, but in addition to joking, I am afraid the people who actually practice it do not exist ......
(3) now printf is available -- debug the serial port
so far, during the development of Bootloader and even the entire OS, the serial port may be the most widely used debug port. Its device is simple but not simple. Connect the PC to the target device using a serial line, so that we can output some characters through the serial port and receive them at one end of the PC. Finally, the most traditional and original debugging method printf can be used in application development with OS. In the development of bootloader, if debugging information can be output through the serial port, the debugging method is a huge step forward. At least we can use printf to track the function in which the current code is located, the process in which the branch statement goes, and whether the value of a variable is what we want ...... The world is beautiful. The problem with the serial port is that it is not used as needed by LED, and still needs to be initialized. Many embedded CPUs integrate the serial controller into it, and some even automatically initialize the serial port when the CPU is powered on, which makes the serial port initialization relatively simple. However, if some serial ports are plug-in controllers, it may take you half a day to initialize a serial port.
(4) entering the new era-kernel debugger
As the development becomes more complex, I am afraid that the Serial Output debugging information cannot meet our requirements. First, the output information is too much, so it is easy to confuse. Second, it takes time to output the information industry. It is still unwise to use Serial Output in time-sensitive scenarios such as interrupt processing functions. If you can connect the remote debugger, there will be no difference between the bootloader debugging and the application debugging (source code-level breakpoint setting, step by step, to view the values of some data structures at any time, ). Linux provides GDB and Windows CE provides kD. However, this requires a lot of work to implement some debugger stub. GDB may be accessible through the serial port. However, Ce KD usually uses kitl over Ethernet. Although complicated, it is still necessary in the long run. Therefore, when you feel that other means are insufficient, you can consider enabling a more advanced debugger.
(5) other tricks
What should I do if I have no hardware debugger, no LEDs, and no serial port, let alone the kernel debugger? Don't worry, as long as your hardware has an input/output device, we can come up with a solution. As long as we can try to output something to the output device and obtain the output information through some means, we can achieve the purpose of debugging. For example, output a piece of noise to the speaker, write a sector to the block device, and draw some messy things on the screen ...... After the code is run, debugging can be implemented as long as it is not a blind man. When there is no way to go, consider these methods.
3. Make bootloader more perfect
I have read an article about developing a good bootloader, the workload may be compared with the development of a simple operating system. So far, we have just begun, and there is still a long way to go.