In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces "what is the second stage startup process of u-boot". In daily operation, I believe that many people have doubts about what the second stage startup process of u-boot is. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "what is the second stage startup process of u-boot?" Next, please follow the editor to study!
Tq2440's uboot directory is a bit cumbersome. You can use tftp to download uboot to nand with uboot in nor. 1. Connect the development board with pc 2. Select tftp to download
3. Set pc to the same network segment as the development board
After that, install the tftp server software on pc. Then enter 1. 0 in uboot's tftp download mode. Because the uboot source code of tq2440 is so dead that the name of the uboot file downloaded through tftp is u-boot.bin, so rename the uboot provided by Tianjia to u-boot.bin and put it in the sibling directory of the tftp tool to automatically complete the download, it is best to format nand before downloading.
I feel that the first stage of uboot is to ensure the lowest running requirements for the chip to run, and the second stage is the real working code.
General overview of the second phase
The second phase of the process initiated by uboot is roughly shown in the figure:
After entering start_armboot, first arrange the storage space for gd, gd- > bd, and then clear the space by 0. 5%.
Function 1. Board_initint board_init (void) {S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO (); / / get the base address of S3C24X0_GPIO_BASE, GPIO register / * set up the I ports O ports * / gpio- > GPACON = 0x007FFFF;. Gpio- > GPJUP = 0x00001fff; / * arch number of TQ2440-Board * / gd- > bd- > bi_arch_number = MACH_TYPE_S3C2440; / * adress of boot parameters * / gd- > bd- > bi_boot_params = 0x30000100 / the base address of taglist in machine ID and ram is passed to kernel as a parameter in do_boot_linux, [theKernel (0, machid, bd- > bi_boot_params)] / * enable instruction / data cache*/ icache_enable (); dcache_enable (); return 0;} 2. Interrupt_initint interrupt_init (void) {S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS () / * use PWM Timer 4 because it has no output * / / * prescaler for Timer 4 is 16 * / timers- > TCFG0 = 0x0f00; if (timer_load_val = = 0) {/ * for 10 ms clock period @ PCLK with 4 bit divider = 1 default 2 (default) and prescaler = 16. Should be 10390 @ 33.25MHz and 15625 @ 50 MHz * / timer_load_val = get_PCLK () / (2 * 16 * 100) } / * load value for 10 ms timeout * / lastdec = timers- > TCNTB4 = timer_load_val; / * auto load, manual update of Timer 4 * / timers- > TCON = (timers- > TCON & ~ 0x0700000) | 0x600000; / * auto load, start Timer 4, automatic reloading * / timers- > TCON = (timers- > TCON & ~ 0x0700000) | 0x500000; timestamp = 0; return (0);}
(1) calculation of pre-division value
Here use no output pin timer TIM4, timing 10ms, automatic reinstall.
TCFG0 Bit Description Prescaler 1 [15:8] These 8 bits determine prescaler value for Timer 2, 3 and 4. Prescaler 0 [7:0] These 8 bits determine prescaler value for Timer 0 and 1. 0x00
TCFG0=0x0F00, pre-division value Prescaler 1 = 1pm 16
TCFG1=0x0000, with a frequency division value of 1 stroke 2 (default 0000 is 2 frequency division)
(2) calculate the initial value of timer timer_load_val = get_PCLK () / (2 * 16 * 100)
Get_PCLK () is located in cpu/arm920t/s3c24x0/speed.c, and the process of getting pclk is as follows
FCLK = > HCLK = FCLK / 2 = > PCLK = HCLK / 2, FCLK: HCLK: PCLK = 4: 2: 1
That is, FCLK is calculated by the value of MPLLCON, and then HCLK and PCLK are obtained according to the frequency ratio of CLKDIVN. To make a 10ms timer, so calculate the initial value here. Above prescaler1 = 16, and TCFG1 is not set here, so TCFG1 is the default value of 0, then divider chooses 1max 2; 1s = 10ms * 100
As a result, all three parameters are needed. After frequency division, the frequency is (clk/ (2 * 16)), that is, to do (clk/ (2 * 16)) subtraction per second, then 10ms has to do clk/ (2 * 16 * 100) subtraction.
(3) TCNTB4lastdec = timers- > TCNTB4 = timer_load_val
Save the initial value of timer count in TCNTB4, and automatically assign TCNTB4 to TCNT4 when the subtraction count is completed.
(4) TCONtimers- > TCON = (timers- > TCON & ~ 0x0700000) | 0x600000; / / = > bit [22:20] = 110 auto reload mode, update TCNTB4timers- > TCON = (timers- > TCON & ~ 0x0700000) | 0x500000; / / = > bit [22:20] = 101 auto reload mode, start for timer4 at this time, really start timer 4
Interrupt_init in a later version of uboot seems to have been updated to timer_init.
3. Env_init
Environment variables should be if there are environment variables in flash, then use flash, if not, use the default environment variables.
This function is defined in multiple files, but there is a macro definition at the beginning of each file to include the entire file, as in env_nand.c
# if defined (CFG_ENV_IS_IN_NAND) / * Environment is in Nand Flash * /
If CFG_ENV_IS_IN_NAND is defined in include/configs/smdk2440.h (EmbedSky.h), it means that the parameters are stored in nand.
Int env_init () {gd- > env_addr = (ulong) & default_environment [0]; gd- > env_valid = 1;}
Assign the default environment variable array address to gd- > env_addr
Default_environment [] is defined in common/env_common.c
4. Init_baudrate
Getenv_r ("baudrate", tmp, sizeof (tmp)); here is the env_init corresponding to the previous step. If the environment variable is set, look for "baudrate" > according to env_ptr.
5. Serial_init/* * initializes the serial port with the given baud rate. Always set to 8 data bits without check, 1 stop bit without start bit * / int serial_init (void) {serial_setbrg (); return (0);} void serial_setbrg (void) {S3C24X0_UART * const uart = S3C24X0_GetBase_UART (UART_NR); int i; unsigned int reg = 0 / * value is calculated so: (int) (PCLK/16./baudrate)-1, this is to calculate the value of the baud rate register: RBRDIV*/ reg = get_PCLK () / (16 * gd- > baudrate)-1; / * FIFO enable, Tx/Rx FIFO clear * / uart- > UFCON = 0x07; uart- > UMCON = 0x0 / * Normal,No parity,1 stop,8 bit * / uart- > ULCON = 0x3; / * tx=level,rx=edge,disable timeout int.,enable rx error int., * normal,interrupt or polling * / uart- > UCON = 0x245; uart- > UBRDIV = reg;#ifdef CONFIG_HWFLOW uart- > UMCON = 0x1; / * RTS up * / # endif for (I = 0; I
< 100; i++);} 使用上一步获取到的波特率来初始化串口, 串口默认设置为 8 N 1 无. 6. console_init_f gd->Have_console = 1; equals to setting a flag bit, indicating that uboot uses command terminals.
7. Display_banner & print_cpuinfo
Both of these functions are used for debugging. They print out debugging information. Note here that the print function, printf, calls puts in / common/console.c to implement the output.
Void puts (const char * s) {/ / GD_FLG_DEVINIT indicates whether to output if (gd- > flags & GD_FLG_DEVINIT) {/ * Send to the standard output * / fputs (stdout, s) to oneself or serial port;} else {/ * Send directly to the handler * / serial_puts (s) } 8. Dram_init must first be defined in / include/configs/smdk2440.h (embedsky.h): # define CONFIG_NR_DRAM_BANKS 1 / * there is only one sdram * / # define PHYS_SDRAM_1 0x30000000 / * SDRAM Bank # 1 starting address * / # define PHYS_SDRAM_1_SIZE 0x08000000 / * 128 MB * / int dram_init (void) ) {gd- > bd- > bi_dram [0] .start = PHYS_SDRAM_1 / / bi_dram [0] indicates the dram starting address and size gd- > bd- > bi_dram [0] .size = PHYS_SDRAM_1_SIZE; return 0;}
Finally, let's summarize the two most important structures:
(1) gd_t in / include/asm-arm/global_data.h, where the configuration information of u-boot is saved
Typedef struct global_data {bd_t * bd; unsigned long flags; unsigned long baudrate; unsigned long have_console; / * serial_init () was called * / unsigned long reloc_off; / * Relocation Offset * / unsigned long env_addr; / * Address of Environment struct * / unsigned long env_valid / * Checksum of Environment valid? * / unsigned long fb_base; / * base address of frame buffer * / void * * jt; / * jump table * /} gd_t
(2) bd_t in / include/asm-arm/u-boot.h
Typedef struct bd_info {int bi_baudrate; / * serial console baudrate * / unsigned long bi_ip_addr; / * IP Address * / unsigned char bi_enetaddr [6]; / * Ethernet adress * / struct environment_s * bi_env; / / the following two parameters are passed to the kernel startup function ulong bi_arch_number as arguments R1 R2 when entering the kernel / * unique id for this board, destination board id * / ulong bi_boot_params; / * where this board expects params, address of taglist * / struct / * RAM configuration * / {ulong start; ulong size;} bi_ dram [config _ NR_DRAM_BANKS];} bd_t
The CFG_GBL_DATA_SIZE defined in / include / configs/smdk2440.h (embedsky.h) is 128, and both gd_t and bd_t are stored in this area.
The functions above are functions in init_sequence. The following is the parsing of the next code in start_armboot: flash_init
From the internal code, we can see that this is the initialization of norflash.
# define PHYS_FLASH_1 0x00000000flashbase = PHYS_FLASH_1; / / because cpu executes code at address 0, and 2440 can only have nor-flash and internal 4k sram at address 0, so there is no doubt about the initialization of nor-flash
This function initializes the starting address and size of each sector of nor-flash, and prints out the configuration information of flash in display_flash_config.
Display configuration
Addr = (_ bss_end + (PAGE_SIZE-1)) & ~ (PAGE_SIZE-1); / / calculate framebuffer memory address size = lcd_setmem (addr); / / set framebuffer size GD-> fb_base = addr; / / set framebuffer starting address mem_malloc_init (_ armboot_start-CFG_MALLOC_LEN) / / initialize nand by clearing all the zeros of the malloc
Note to turn on CONFIG_COMMANDS and CFG_CMD_NAND 's support for nand in / include/configs/smdk2440.h (embedsky.h)
Nand_init (); initialize environment variable parameters
/ * initialize environment * / env_relocate (); / / initialize environment variable to set ip address
Gd- > bd- > bi_ip_addr = getenv_IPaddr ("ipaddr"); read the mac address from the network card
/ * MAC Address * / / read the mac address int i; ulong reg; char * s from the network card register, * e; char tmp [64] I = getenv_r ("ethaddr", tmp, sizeof (tmp); s = (I > 0)? Tmp: NULL; for (reg = 0; reg)
< 6; ++reg) { gd->Bd- > bi_ enetaddr [Reg] = s? Simple_strtoul (s & e, 16): 0 / / here the question mark expression takes precedence over =, that is, first determine whether s is true, and then assign the value if (s) s = (* e) according to the result? E + 1: e;} initialize the device on the development board devices_init (); / / initialize the device initialization jump table such as iic/lcd/video/logbuff/system/serial
Jumptable_init (); / / initialize the jump table
Initialize the console
Console_init_r ()
Turn on interrupt
Enable_interrupt ()
Save load address
/ * Initialize from environment * / if ((s = getenv ("loadaddr"))! = NULL) {load_addr = simple_strtoul (s, NULL, 16);}
Find out if the environment variable contains load_addr, and if so, write his value to load_addr, he is the load address, and you will see him in bootm. He indicates the address where uboot loads kernel into memory.
Save framebufferif ((s = getenv ("bootfile"))! = NULL) {copy_filename (BootFile, s, sizeof (BootFile)); / / Save framebuffer} development board initialization
Board_late_init (); / / because each board is different, the special initialization of the board can be written in this function to print the network card information.
Eth_initialize
Main_loop
/ * main_loop () can return to retry autoboot, if so just run it again. * / for (;;) {main_loop (); / enter the main loop}
So far, there is no talk about how uboot starts linux, and the most critical part of the code is in main_loop.
In main_loop, 1. 5% was completed. Set startup times, some items need to detect the number of startup times of the device, if it is greater than a certain value, do not start 2. Modem function 3. Uboot version number 4. Command auto-completion function (similar to shell auto-complete command) 5. Enable countdown start function 6. Enter the endless loop to execute read_line (), and read the commands entered by the console (usually serial port). Execute the command run_command (). If you want to know how to parse the command, you can trace the run_command () function 7. Start linux
We can see the importance of the main_loop function. We will continue to analyze the main_loop function in the next article.
At this point, the study on "what is the start-up process of the second phase of u-boot" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.