Bootloader code is a piece of code executed before the chip enters the operating system after reset. It is mainly used to complete the transition from hardware startup to operating system startup, thereby providing a basic operating environment for the operating system, such as initializing the CPU, stack, memory system, etc. Bootloader code is related to factors such as the core structure of the CPU chip, the specific model, the configuration of the application system, and the operating system used. Its function is similar to the BIOS program of a PC. Since the bootloader is related to the configuration of the CPU and the circuit board, it is impossible to have a universal bootloader. During development, users need to transplant according to specific circumstances. Commonly used bootloaders in embedded Linux systems include armboot, redboot, blob, u-boot, etc. Among them, u-boot is currently a more popular and powerful bootloader that can support multiple architectures, but it is also relatively complex. The implementation of the bootloader depends on the CPU architecture. Most bootloaders are divided into two parts: stage 1 and stage 2. The basic principles of the bootloader can be found in the references. u-boot is an open source project on the sourceforge website. It can support PowerPC MPC5XX, MPC8XX, MPC82XX, MPC7XX, MPC74XX, ARM (ARM7, ARM9, StrongARM, VxWorks, NetBSD, QNX, RTEMS, ARTOS, LynxOS, etc. It is mainly used to develop embedded system initialization code bootloader. The main site of the software is http://sourceforge.net/projects/u-boot . U-boot was originally developed from denx's PPC-boot. It has the most complete support for PowerPC series processors and the best support for Linux operating system. The open source U-boot software project is frequently updated.
The latest version is U-boot-1.1.6 of NOV.2.2006 Update.
2 u-boot system startup process
Most bootloaders are divided into two parts: stage 1 and stage 2, and u-boot is no exception. Codes that depend on the CPU architecture (such as device initialization code, etc.) are usually placed in stage 1 and can be implemented in assembly language, while stage 2 is usually implemented in C language, which can implement complex functions and has better readability and portability.
2.1 stage1 (start.s code structure)
The stage1 code of u-boot is usually placed in the start.s file, which is written in assembly language. The main code parts are as follows:
(1) Define the entry point. Since an executable image must have an entry point and there can only be one global entry point, this entry point is usually placed at address 0x00 of ROM (Flash) for an ARM-structured CPU (0xBFC00000 for MIPS). Therefore, the compiler must be informed of this entry point, which can be accomplished by modifying the linker script.
(2) Set the exception vector.
(3) Set the CPU speed, clock frequency and interrupt control register.
(4) Initialize the memory controller.
(5) Copy the program in ROM to RAM.
(6) Initialize the stack.
(7) Transfer to RAM for execution. This task can be completed using the ldrpc instruction.
2.2 stage2 C language code part
start_armboot in lib_arm/board.c is the C language start function, and is also the main C language function in the entire startup code, and is also the main function of the entire u-boot (armboot). This function mainly completes the following operations: (Line236)
(1) Call a series of initialization functions.
(2) Initialize the Flash device.
(3) Initialize the system memory allocation function.
(4) If the target system has a NAND device, initialize the NAND device.
(5) If the target system has a display device, initialize the device.
(6) Initialize relevant network devices and fill in IP, MAC addresses, etc.
(7) Enter the command loop (i.e. the entire boot working loop), accept the commands entered by the user through the serial port, and then perform the corresponding work.
3. Transplantation Examples
Friendly Arm QQ2440V3 Development Board
The system development board is mainly composed of S3C2440 embedded microprocessor, 16MB Flash (AM29LV160), 64MB Nand Flash (K9F1208U0), 64MB SDRAM (Hy57v561620), network card driver IC (CS8900A) and ARM JTAG interface.
3.1 u-boot file download
There are two ways to download u-boot files. The first is to download the latest files through CVS in Linux environment. The method is:
$cvs-dpserver anonymous@cvs.sourceforge.net/cvsroot/u-boot login
When asked to enter the anonymous login password, just press the Enter key
$cvs-z6-dpserver anonymous@cvs.sourceforge.net/cvsroot/u-boot\co.Pmodulename
The second is to download the officially released compressed file through ftp //ftp.denx.de/pub/u-boot/.
3.2 u-boot file structure
There are many files downloaded for the first time. After decompression, they are stored in the u-boot file directory. The specific contents have been described in detail in the readme file. The main folders related to the transplantation are:
(1) Each subfolder of the CPU contains the following files:
Makefile
config.mk
cpu.c and processor-related code
interrupts.c interrupt handling code
serial.c serial port initialization code
start.s global start startup code
(2) Each subfolder of Board contains the following files:
Makefile
config.mk
smdk2410.c and board-related codes (taking smdk2410 as an example)
flash.c Flash operation code
memsetup.s initializes SDRAM code
u-boot.lds corresponding connection file
(3) Relevant implementation codes under the lib_arm architecture, such as the optimized implementation of memcpy in assembly language.
3.3 Establishing a cross-compilation environment
To get the u-boot binary boot code downloaded to the target board, you also need to compile the downloaded u-boot-1.1.6. The compilation of u-boot is generally performed under the Linux system, and can be compiled using arm-linux-gcc. It is usually complicated to establish a cross-compilation environment step by step. The easiest way is to use the cross-compilation tool compiled by others, as follows:
(1) Download arm-linux-gcc-3.4.5.tar.bz2 from http://handhelds.org/download/toolchai
(2) Log in as user root and unzip arm-linux-gcc-3.4.5.tar.bz2 to the /root directory
#tar jxvf arm-linux-gcc-3.4.5.tar.bz2
(3) Download arm-linux-toolchain-post-2.2.13.tar.gz from http://handhelds.org/download/toolchai and only use its header files, mainly from kernel/linux-xx/include
(4) Unzip arm-linux-toolchain-post-2.2.13.tar.gz to /skiff/local/
#tar zxvf arm-linux-toolchain-post-2.2.13.tar.gz
(5) Copy the header file to /root/usr/3.4.5/arm-linux/ and delete /skiff
#cp –dR/skiff/local/arm-linux/include/root/usr/3.3.2/arm-linux #rm -fr/skiff
This establishes the arm-linux cross-compilation environment.
(6) Add /root/usr/local/arm/3.4.5/bin to the path environment variable
Path=$path:/root/usr/local/arm/3.4.5/bin can check whether the path variable is set correctly. #echo $path
3.4 Pre-compilation of migration
To port u-boot to a new development board, you only need to modify the hardware-related parts. There are mainly two levels of porting, the first level is for the CPU, and the second level is for the Board. Since u-boot-1.1.6 already contains the porting of S3C2410, and the registers of S3C2410 and S3C2440 are basically the same, my porting of the QQ2440 board is mainly for the board. Before porting, you need to carefully read the readme file in the u-boot directory, which briefly introduces how to port. In order to reduce the workload of porting, you can select a development board similar to the hardware to be ported in the include/config directory, so that the parameters of the QQ2440V3 development board I have basically match. I chose the smdk2410 development board. The specific steps are as follows:
3.4.1 The CPU folder under u-boot-1.1.6 already includes the directory /arm920t/s3c24x0, which already contains several files such as start.s, interrupts.c, cpu.c, and serial.c. Therefore, there is no need to create a directory related to the CPU.
When setting the serial port baud rate later, you need to get the system clock. In the second stage of U-Boot, when the start_armboot function in lib_arm/board.c calls the serial_init function, it will call the get_PCLK, get_HCLK, get_PLLCLK and other functions defined in cpu/arm920t/s3c24x0/speed.c, so you need to modify speed.c. (Process omitted)
3.4.2 Create the QQ2440 directory and files such as QQ2440.c, flash.c, memsetup.s and u-boot.lds in the board directory. You don't need to create them from scratch. Just select a similar directory (smdk2410) and copy it directly, then modify the file name and content. I chose the u-boot-1.1.6/board/smdk2410 directory when porting u-boot.
3.4.2_1 Modify the target file name of makefile (/board/QQ2440/makefile)
line28:COBJS := smdk2410.o flash.o
to:
line28:COBJS := QQ2440.o flash.o //intermediate code file name
3.4.2_2 Modify lowlevel_init.s(/board/QQ2440/lowlevel_init.s)
line126: #define REFCNT 1113
to:
line126: #define REFCNT 0x4f4 //SDRAM clock frequency is different
3.4.2_3 Modify the board_init function in QQ2440.c (/board/QQ2440/QQ2440.c)
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
#define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
#define S3C2440_CLKDIV 0x05
#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
#define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02))
#define S3C2410_CLKDIV 0x03
so:
Solution 1: Modify the register address and corresponding formula directly based on the original one.
Solution 2: Determine the current SOC by reading the value of GSTATUS1 and call the conditional subroutine at the same time. (Recommended, process omitted)
3.4.2_4 Because the nor flash of the QQ2440V3 board is AM29LV160DB, and the /board/QQ2440/flash.c of u-boot1.1.6 only supports AM29LV400DB and AM29LV800DB, if you want to increase the flash capacity, you will inevitably have to make some small modifications to the flash.c file. (Modify ID, shell output information, CFG_MAX_FLASH_BANKS, etc.)
3.4.3 Add QQ2440.h in the include/configs directory. You can put global macro definitions here without creating them from scratch. You can find similar CPU header files in the include/configs directory and copy them. Here I use the smdk2410.h file to make relevant modifications.
3.4.3_1 Modify /include/configs/QQ2440.h to call 3.4.2_4. Here, simply change the parameters of AM29LV400DB to those of AM29LV160, and make corresponding changes in flash.c.
Note: There are corresponding macro definitions to be modified in /include/flash.h; there are settings for some specific parameters (sector, ID, address) such as CONFIG_AMD_LV400 in /include/configs/QQ2440.h
3.4.4 Modify the makefile in the u-boot root directory and add the board declaration.
Line1881:QQ2440_config: unconfig
@./(MKCONFIG) $(@:_config=) arm arm920t QQ2440 NULL s3c24x0
Corresponding relationship: ARCH cpu development board Vendor SOC
3.4.5 Run make clobber and delete the wrong depend file.
3.4.6 Run make QQ2440 config.
3.4.7 Executing to this point means that the makefile of the entire software has been created. At this time, you can modify the cross-compilation options in the generated makefile, then open the makefile and find the statement in it:
Ifeq($ARCH),arm)
CROSS_COMPILE=arm-linux-endif
Then change it to
Ifeq($ARCH),arm)
CROSS_COMPILE=/root/usr/local/3.4.5/bin/arm-linux-endif
You only need to do one of this step and the above environment variable setting.
Execute make and an error is reported. Modify #include "../commond/flash.c" in myboard/flash.c to "#u-boot/board/dave/common/flash.c" and recompile to pass.
4. Specific modification points during transplantation
If there are no errors in the pre-compilation, you can start the porting of hardware-related codes. First, you must have a clear understanding of the ported hardware, such as the CPU, CPU control registers, and the layout of the startup programs in Flash SDRAM.
During the transplantation process, I first modified most of the parameters in the /include/config/my-board.h header file (most of the macro definitions are set here), and then gradually modified them according to the u-boot startup process. When modifying, you should be familiar with ARM assembly language and C language, and you should also have a deep understanding of the u-boot startup process code. The CPU frequency of the QQ2440 board is 400MHz, the Nor Flash is 16Mbit, the SDRAM is 64Mbit, the serial port baud rate is 115200bit/s, and the environment variables are placed in EEPROM. According to the differences between the two development boards, the following need to be modified: CPU frequency, Flash and SDRAM capacity, location of environment variables, etc. Since the reference board already has most of the code, it is only necessary to make corresponding modifications to my-board.
The relevant files are
/include/config/myboard.h (most of the macro definitions are set here),
/board/myboard/flash.c Flash driver sequence,
/board/myboard/myboard.c (SDRAM driver),
/CPU/S3C2440/serial.c (the serial port driver enable part), etc.
/include/config/myboard.h is where the global macros are defined. The main modifications are:
Change #definitionCONFIG QQ2440 CLOKSKSPEEED 75 to
#defineCONFIG QQ2440 CLOCK SPEED 400;
Change #define PHYS SDRAM 1 SIZE 0x01000000 to
#define PHYS SDRAM 1 SIZE 0x00800000;
Change #define PHYS FLASH 1 SIZE 0x00400000 to
#define PHYS FLASH 1 SIZE 0x00200000;
Change #define CFG MAX FLASH SECT 256 to
#define CFG MAX FLASH SECT 35;
Change #define CFG ENV IS EEPROM 1 to
#define CFG ENV IS IN FLASH 1
Others (such as stack size, etc.) can be modified as needed.
Since the capacity of Flash and SDRAM will change, the location of the program in Flash and SDRAM during the startup phase should be rearranged. The author puts the u-boot code in Flash at the beginning of 0x0, and arranges the u-boot code copied to SDRAM at the beginning of 0xc700000.
The modification of Flash is not only related to the capacity, but also to the specific model. The burning and erasing of Flash memory is generally not universal. You should check the manufacturer's instruction manual and make corresponding modifications for different models of memory. During the modification process, you need to understand the write address, data command, and sector size and location of the specific register of Flash erasing in order to make correct settings.
The main part of SDRAM that needs to be modified is the initialization of the memory controller. The CPUcache is set by cpuinitcrit in the start.s file, and the SDRAM is initialized by memsetup in board/myboard/memsetup.s. QQ2440 provides an SDRAM controller. Compared with some CPUs that require UPM table programming, it only needs to modify the settings of related registers, thus reducing the difficulty of development.
The serial port baud rate does not need to be modified (all 115200 bit/s), just use the serial port driver of the QQ2440 board. The serial port settings mainly include initializing the serial port. It is worth noting that the baud rate of the serial port is closely related to the clock MCLK, see the CPU user manual for details.
After configuration, you can recompile the u-boot code. After downloading the obtained u-boot.bin to the target board through the JTAG port, if the correct startup information can be output from the serial port, it means that the transplantation is basically successful. In the actual process, multiple modifications will be required due to inconsideration. After the transplantation is successful, some other functions (such as LCD driver, etc.) can also be added. It is relatively easy to add functions on this basis.
5. Conclusion
u-boot is a powerful bootloader development software, which is applicable to many CPU platforms and supports many embedded operating systems. This article is the author's exploration of relevant materials in the actual development process, and is summarized on the basis of successfully transplanting u-boot. For different CPUs and development boards, the basic methods and steps are the same, and I hope it can be helpful to designers of related embedded systems
Previous article:ARM processor 9 basic addressing modes
Next article:Touch screen transplantation (s3c2410)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Please recommend a microcontroller with 5V IO port output
- PowerBox
- I2C bus controls RDA5807M to achieve high-fidelity reception of FM signals
- I would like to ask you how to use timequest to analyze the delay time of the delay chain in FPGA.
- [Qinheng Trial] Experience of CH549 capacitive touch function
- RS485 communication issues in MSP430F169
- Raspberry Pi PICO low-resolution thermal imager
- Reversible USB port
- Why does the power consumption of stm32L0 increase after it enters STOP mode again after being woken up by an external interrupt in STOP mode?
- [TI millimeter wave radar evaluation]_4_boost board evaluation encountered problems 2