1, u-boot process
1.1 u-boot flow chart drawing
In previous blogs, we have analyzed the source code of u-boot. So let's try to connect what we introduced in the previous sections. Draw a u-boot startup flowchart:
2, Steps of u-boot migration
Since we want to transplant u-boot, we first need to understand the startup process of u-boot. U-boot migration can be divided into the following steps:
- Kernel level configuration and initialization;
- SOC level configuration and initialization;
- board_init_f;
- u-boot relocation;
- board_init_r;
- Start the kernel or process user commands;
two point one Kernel level configuration and initialization
This is mainly the assembly code in the start.S file, mainly including:
- Turn on SVC mode, turn off FIQ and IRQ interrupt;
- Close the watchdog
- Mask all interrupts;
- Set the system clock;
- Execution cpu_init_crit function;
- Close MMU and cache;
- lowlevel_init function;
This part is the code closely related to the kernel. The configuration of this part is slightly different according to different kernels.
two point two SOC level configuration and initialization
There are a lot of contents in this part, and it can be said that it runs through the whole u-boot, but it is basically necessary to focus on the low level_ Init, the rest depends on whether you want to use some hardware resources in the u-boot phase.
For example, the network card is on the board_init_r is already in the back position. Some boards may not even use the network in the u-boot stage. Naturally, initialization is not required.
This part is modified a lot during the migration process, and assembly coding is basically used. As long as this part is completed, the u-boot can be started successfully.
2.3 board_init_f
This stage is mainly for memory planning after u-boot relocation. Although there are many sub functions, they are not complex. Less transplant content.
two point four u-boot relocation
This part of the code basically does not need to be changed.
2.5 board_init_r
The main task in this stage is to prepare the terminal and initialize the hardware resources needed. If a new driver model is used, the hardware should be abstracted like the kernel. According to their own needs, we should change what we use.
two point six Start the kernel or process user commands
The biggest mission of u-boot is to start the kernel, so this part is also the core content. board_init_r finally calls run_main_loop enters a loop, either directly starts the kernel or enters the terminal to process user commands and user interaction. It can also be said that there is no need to change. It is almost done by pure software.
3, Add board
Since u-boot-2016.05 supports S3C2410 development board, we can directly copy the relevant files of S3C2410 board to S3C2440.
three point one Create a board directory in board (board / sampling / smdk2440)
cd board/samsung/
cp smdk2410 -r smdk2440
Enter smdk2440 path:
Modify the file Kconfig:
if TARGET_SMDK2440 config SYS_BOARD default "smdk2440" config SYS_VENDOR default "samsung" config SYS_SOC default "s3c24x0" config SYS_CONFIG_NAME default "smdk2440" endif
Modify MAINTAINERS file:
SMDK2440 BOARD M: David Müller <d.mueller@elsoft.ch> S: Maintained F: board/samsung/smdk2440/ F: include/configs/smdk2440.h F: configs/smdk2440_defconfig
As you can see from here, we also need to create include / configurations / smdk2440. H and configs/smdk2440_defconfig.
Modify Makefile file:
# # (C) Copyright 2000-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # SPDX-License-Identifier: GPL-2.0+ # obj-y := smdk2440.o obj-y += lowlevel_init.o
smdk2410.c renamed smdk2440.c
mv smdk2410.c smdk2440.c
three point two Create a board related header file (include / configure / smdk2440. H)
Similarly, we copy the smdk2410.h file in the include / configurations / directory as smdk2440.h:
cd include/configs cp smdk2410.h smdk2440.h
This file is very important. It is mainly used to configure whether to enable some functions when compiling u-boot, such as network card, LCD, etc. if defined, the code of relevant modules will be compiled.
Modify string 2410 - > 2440 in smdk2440.h:
#define CONFIG_S3C2440 /* specifically a SAMSUNG S3C2440 SoC */ #define CONFIG_SMDK2440 /* on a SAMSUNG SMDK2440 Board */
/* * NAND configuration */ #ifdef CONFIG_CMD_NAND #define CONFIG_NAND_S3C2440 #define CONFIG_SYS_S3C2440_NAND_HWECC #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x4E000000 #endif
three point three Create defconfig file
Executing make smdk2440_defconfig, which depends on configs/smdk2440_defconfig file, so we will also smdk2410_ Copy defconfig:
cd configs cp smdk2410_defconfig smdk2440_defconfig
Modify smdk2440_defconfig:
CONFIG_ARM=y CONFIG_TARGET_SMDK2440=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="SMDK2440 # " CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_DHCP=y CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y CONFIG_CMD_EXT2=y CONFIG_CMD_FAT=y
3.4 modify arch/arm/Kconfig file
vim arch/arm/Kconfig
Add the following:
config TARGET_SMDK2440 bool "Support smdk2440" select CPU_ARM920T source "board/samsung/smdk2440/Kconfig"
three point five Try configuring and compiling
After completing the above steps, we have completed the addition of S3C2440 board. Although S3C2410 is copied, we only need to modify it based on the S3C2410 configuration file.
make smdk2440_config make ARCH=arm CROSS_COMPILE=arm-linux- V=1
The first step can be compiled successfully, and the second step will fail, mainly because we configured NAND in include / configurations / smdk2440. H, but we did not migrate the relevant code.
IV Kernel level configuration and initialization (arch/arm/cpu/arm920t/start.S)
Let's first analyze the arch/arm/cpu/arm920t/start.S file to see if there are any changes that need to be made.
The first thing we need to change is the clock system setting. Initialize the system clock FCLK = 400MHz,HCLK = 100MHz, PCLK = 50MHz, UPLL=48MHz.
#ifdef CONFIG_S3C24X0 /* turn off the watchdog */ # if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ # define CLKDIVN 0x14800014 /* clock divisor register */ #else # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C /* Initialize the system clock FCLK = 400MHz,HCLK = 100MHz, PCLK = 50MHz, UPLL=48MHz */ # define LOCKTIME 0x4c000000 # define MPLLCON 0x4c000004 # define EQU UPLLCON 0x4c000008 # define CLKDIVN 0x4c000014 # define M_MDIV 92 /* Fin=12M UPLL=400M */ # define M_PDIV 1 # define M_SDIV 1 # define U_MDIV 56 /* Fin=12M UPLL=48M */ # define U_PDIV 2 # define U_SDIV 2 # define DIVN_UPLL 0 /* FCLK:HCLK:PCLK=1:4:8 */ # define HDIVN 2 # define PDIVN 1 # endif ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif /* Set Lock Time */ ldr r0, =LOCKTIME ldr r1, =0xffffffff str r1, [r0] /* Set frequency division coefficient */ ldr r0, =CLKDIVN ldr r1, =((DIVN_UPLL<<3) | HDIVN <<1 | PDIVN) str r1, [r0] /* CPU Change to asynchronous bus mode */ mrc p15,0,r1,c1,c0,0 orr r1, r1,#0xC0000000 mcr p15,0,r1,c1,c0,0 /* Set UPLL */ ldr r0, =UPLLCON ldr r1, =((U_MDIV<<12) | (U_PDIV<<4) | U_SDIV) str r1, [r0] nop nop nop nop nop nop nop /* Set MPLL */ ldr r0, =MPLLCON ldr r1, =((M_MDIV << 12) | (M_PDIV << 4) | M_SDIV) str r1, [r0] #endif /* CONFIG_S3C24X0 */
5, SOC level configuration and initialization (board / sampling / smdk2440 / low level_init. S)
In lowlevel_ The init. S file mainly contains the code for initializing SDRAM. The initialization of SDRAM depends on our external SDRAM chip.
Take the Mini2440 development board as an example: two pieces of 32MB, 16 bit wide SDRAM memory (model HY57V561620FTP) are welded to Bank6 to form 64M, 32-bit memory in parallel. Therefore, here we mainly focus on the configuration related to Bandk6.
We will the configuration and Memory controller for Mini2440 bare metal development To compare the codes in, we need to modify the following:
#define REFCNT 1269 /* period=7.8125us, HCLK=60Mhz, (2048+1-7.8125*100) */
Change BANKSIZE to 0xB1:
SMRDATA: .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) .word 0xB1 .word 0x30 .word 0x30
Vi board_init_f
We will not modify this piece of code.
7, u-boot relocation
We don't modify this piece of code.
Reference articles
[1]1. Transplant uboot - analyze uboot startup process (detailed explanation)