Uboot Analysis of Start.s 2

Source: Internet
Author: User
Note: This article is to learn the notes of teacher Zhu's course collation, based on uboot-1.3.4 and s5pc11x analysis.

Analysis of the former part of uboot analysis of Start.s 1 lowlevel_init

/* Go Setup Memory and board specific bits prior
    to relocation.*/Ldr sp, =0xd0036000/        * End of SRAM dedicated to U-boot */
    Sub sp, SP, #12/           * Set stack */
    mov fp, #0

    bl  lowlevel_init/   * Go Setup pll,mux,memory * /

This time the stack is set in SRAM because the current entire code is still running in SRAM, and the DDR is not initialized yet. Stack address 0xd0036000 is its own designation, the principle is to specify that this space is only for the stack, not be occupied by others.

Before calling the function to initialize the stack, the main reason is that BL only stores the return address in LR, but we only have one LR, so the second layer before calling the function to the stack, or the function returns, the first layer of the return address is lost.

Analysis on the Lowlevel_init function see the Lowlevel_init analysis of Start.s power latch

    /* to hold max8698 output before releasing power on switch,
     * Set Ps_hold signal
     to High */
    LDR r0, =0xe010e81 C/  * Ps_hold_control Register */
    LDR R1, =0x00005301/  * ps_hold Output high */
    str r1, [R0]

Power latches have been set up in the Lowlevel_init. Set up the stack again

/* Get ready to call C functions */
    LDR sp, _text_phy_base/  * Setup TEMP stack pointer */
    sub sp, SP, #12 
  mov FP, #0/          * No previous frame, so fp=0 */

Prior to the call to the Lowlevel_init program set 1 times before the stack, because the DDR has not been initialized, so program execution is in SRAM, so in SRAM allocated a portion of memory as a stack.

This stack is set because the DDR has been initialized, so to move the stack into the DDR, so you want to reset the stack; the address of the stack actually set here is 33E00000, just next to the Uboot code snippet.

Why put it under the Uboot code. Because arm is a full-stack, it will not overwrite the Uboot code below.

Why do you want to set the stack again? DDR has been initialized, there is already a large amount of memory can be used, there is no need to put the stack in the SRAM, stack placed there to be careful not to use too many stacks or the stack will overflow, we are in time to move the stack into the DDR is to avoid the use of the stack as much as possible. Re-determine whether to reposition

    Ldr r0, =0xff000fff
    bic r1, PC, R0/      * R0 <-Current Base addr of code */
    LDR R2, _text_base/      * R1 <- Original base addr in RAM */
    BIC R2, R2, R0/      * R0 <-Current Base addr of code */
    CMP     R1, R2/                  * CO Mpare r0, R1                  */
    beq     after_copy/      * r0 = R1 then skip flash copy   */

In the lowlevel_init to determine the relocation, here again with the same code to determine whether the running address is in SRAM or DDR, but the purpose of this judgment is different, the last Judgment is to determine if you want to execute the initialization of the clock and DDR code, This judgment is to decide whether to carry out the uboot relocate.

Cold start, the current situation is uboot (16kb or 8KB), the boot automatically from the SD card loaded into the SRAM run, the second part of Uboot (in fact, the second section is the entire uboot) is also lying on the SD card in the beginning of a sector of n sectors.

At this point the first phase of uboot is about to end, and the second part is loaded into the DDR at the link address (33e00000), and this loading process is called relocation. Re-location

/* SD/MMC BOOT */
    CMP     R2, #0xc
    moveq   R3, #BOOT_MMCSD
... /* The #boot_mmcsd is written to the INF_REG3 register stored in the */
    LDR r0, =inf_reg_base
    str R3, [R0, #INF_REG3_OFFSET] ...
/* Then read out the Inf_reg3_offset, and then compare with #boot_mmcsd, OK is starting from MMCSD */
    LDR r0, =inf_reg_base
    ldr R1, [R0, #INF_REG3_OFFSET ]
    cmp R1, #BOOT_MMCSD
    beq mmcsd_boot
BL   movi_bl2_copy

The real relocation is done by calling the Movi_bl2_copy function, which is a C-language function in UBOOT/CPU/S5PC11X/MOVI.C

CH = * (Volatile u32 *) (0xd0037488);
    Copy_sd_mmc_to_mem copy_bl2 =
        (Copy_sd_mmc_to_mem) (* (U32 *) (0xd0037f98));
... if (ch = = 0xeb000000) {
        ret = copy_bl2 (0, Movi_bl2_pos, movi_bl2_blkcnt,
            cfg_phy_uboot_base, 0);
... if (ch = = 0xeb200000) {
        ret = COPY_BL2 (2, Movi_bl2_pos, movi_bl2_blkcnt,
            cfg_phy_uboot_base, 0);

0xd0037488 This memory address is in SRAM, and the value in this address is automatically set by the hardware. Depending on which channel the SD card is in in our actual circuit, the value in this address will be set to the corresponding number. For example, when we start from the SD0 channel, this value is 0xeb000000; When starting from the SD2 channel, this value is 0xeb200000.

COPY_BL2 (2, Movi_bl2_pos, movi_bl2_blkcnt,cfg_phy_uboot_base, 0);

Analysis Parameters:
2: Indicates channel 2;
Movi_bl2_pos: Is the second part of the Uboot in the SD card in the beginning sector, this sector number must be burned with the same location as burning uboot;
MOVI_BL2_BLKCNT: Is the number of sectors occupied by the length of the uboot;
Cfg_phy_uboot_base: is a relocation when the second part of UBOOT is copied to the start address in the DDR (33E00000). Enable domain access (CP15 C3 Register)

After_copy:

#if defined (CONFIG_ENABLE_MMU)
Enable_mmu:/
    * ENABLE Domain Access */
    LDR R5, =0X0000FFFF
    MCR P15, 0, R5, C3, C0, 0       @load Domain Access register

The CP15 coprocessor has a total of 16 registers inside the C0 to C15, each of which has its own role. We access these registers through the MRC and MCR directives. The so-called operation of the CP Coprocessor is actually the operation of these registers of CP15.
The role of the C3 Register in the MMU is to control domain access. Domain access is related to the access control of the MMU. Set TTB (C2 Register for CP15)

/* Set the TTB Register */
    LDR r0, _mmu_table_base
    ldr R1, =cfg_phy_uboot_base
    ldr R2, =0xfff00000
    Bic r0, R0, R2
    Orr R1, R0, R1
    MCR P15, 0, R1, C2, C0, 0

The conversion table is placed in memory, which requires the start address to be aligned in memory with XX bits. The conversion table does not require the software to interfere with the use, but the base address TTB is set to the CP15 C2 Register, and the MMU will automatically check the conversion table when working.
About _mmu_table_base point of view lowlevel_init mmu_table analysis enable MMU unit (CP15 C1 Register)

/* Enable the MMU *
/mmu_on:
    MRC p15, 0, R0, C1, C0, 0
    Orr r0, R0, #1
    mcr p15, 0, R0, C1, C0, 0

The bit0 of the CP15 C1 register controls the MMU switch. Just set this bit 1 to open the MMU. After opening the MMU, the address of the upper software layer must be transformed by TT to be sent to the underlying physical layer for execution.

The MMU is the memory management unit, the RAM management cell. The MMU is actually a hardware unit in the SOC, and its main function is to implement the mapping of virtual address to physical address.

The MMU controls the CP15 coprocessor, which means to manipulate the MMU for virtual address mapping by programming the registers of the CP15 coprocessor.

on the address map access control is: in the management of the memory block, and then each block of independent virtual address mapping, and then in each block of the mapping relationship also implemented access control (The block is readable, writable, read-only, write-only, inaccessible, etc. control). The segment error (segmentation fault) is actually related to the access control implemented by the MMU. The current program can only manipulate the range of addresses (blocks of memory) that it has permission to manipulate, and if the current program pointer errors access a block of memory that should not be accessed, a segment error is triggered.

The work of the cache is related to the virtual address mapping.
Cache is fast caching, which means slower than CPU but more than a DDR block. The CPU is too slow to DDR, so the content used in some DDR is cached in advance, and the CPU is found in the cache each time it needs to find something. If it is in the cache, it will be used directly in the cache, or if it is not in the cache, look for it in the DDR.

An analysis of the MMU see arm MMU

Set up the stack again

Stack_setup:
#if defined (config_memory_upper_code)
    Ldr sp, = (cfg_uboot_base + cfg_uboot_size-0x1000)
# else
    Ldr r0, _text_base/      * Upper kib:relocated uboot   */
    Sub r0, R0, #CFG_MALLOC_LEN/* MALLOC Area
  */
    Sub R0, R0, #CFG_GBL_DATA_SIZE/* bdinfo                        *
/#if defined (CONFIG_USE_IRQ)
    Sub R0, R0, # (Config_ Stacksize_irq+config_stacksize_fiq)
#endif
    Sub sp, r0, #12/     * Leave 3 words for abort-stack    */

#endif

This time the stack is still in the DDR, although it has already been set up once in the DDR, but the purpose of this stack is to place the stack in a more appropriate (secure, compact without wasting memory).

We actually set the stack at 2MB above the Uboot start address, so that the safe stack space is: 2mb-uboot size -0x1000=1.8mb around. This space is neither too wasteful of memory nor secure enough. Clearing BSS

CLEAR_BSS:
    ldr r0, _bss_start/      * Find start of BSS segment        */
    LDR R1, _bss_end/        * Stop here                        */
  mov     R2, #0x00000000     /* Clear                            *

/clbss_l:
    str R2, [r0]/        * Clear loop ...                    */
    add r0, R0, #4
    cmp r0, R1
    ble clbss_l

The symbol for the beginning and end addresses of the BSS segment is derived from the link script u-boot.lds. Skip to Phase two

Ldr pc, _start_armboot

_start_armboot:
    . Word start_armboot

Start_armboot is in the UBOOT/LIB_ARM/BOARD.C.

This is a C language implementation of the function. This function is the second phase of Uboot. The function of this code is to pass the address of the function of the second stage of Uboot to the PC, which is actually using a far jump to jump directly to the second stage start address in the DDR.

The meaning of a far jump is that the address loaded is irrelevant to the current run address, and to the link address. So this far jump can be achieved by jumping from the first phase of SRAM to the second stage in the DDR.

To this uboot start the first phase of code analysis is complete.

Summary : What was done in the first phase of Uboot
(1) Constructing the anomaly vector table
(2) Setting the CPU to SVC mode
(3) Off-guard dog
(4) Development Board supply lock
(5) Clock initialization
(6) DDR initialization
(7) Serial port initialization and printing "OK"
(8) Reposition
(9) Create a mapping table and open the MMU
(10) Jump to the second stage

The second stage code analysis see Uboot's Start_armboot Analysis 1

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.