2171 views|0 replies

2014

Posts

0

Resources
The OP

Talk about the ARM startup code problem [Copy link]

/********************************************************************** * ARM startup code. ** If no memory initialization is done, only the stack is created and the code is relocated to the RAM location. * Then you can jump to the second stage code to run. **********************************************************************/ /* Data area to save variables*/ _TEXT_BASE: .word TEXT_BASE .globl _ARMboot_start _ARMboot_start: .word _start /** These are defined in the board-specific linker script.*/ .globl _bss_start _bss_start: .word __bss_start .globl _bss_end _bss_end: .word _end ARM #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START ARM IRQ_STACK_START: .word 0x0badc0de /* IRQ stack memory (calculated at run-time) */ .globl FIQ_STACK_START FIQ_STACK_START: .word 0x0badc0de #endif String 5 The above code mainly saves some global variables, which are used to copy the BOOT program from FLASH to RAM, or for other uses. The lengths of some variables are obtained from the link script, which are actually calculated by the compiler. String 4 After looking at the data area, this time we need to see what is running when jumping from the boot to here. /** The reset code that actually runs. The code that runs from the beginning jumps here to run. */ reset: /* * Set the cpu to run in SVC32 mode. */ mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0x13 msr cpsr,r0 51soc Embedded SOC Development Forum Specific analysis is as follows: /** The reset code that actually runs. The code that runs from the beginning jumps here to run. */ ARM reset: /** Set the cpu to run in SVC32 mode. S3C44B0 has a total of 7 modes. */ mrs r0,cpsr Get the current program status register cpsr to r0. bic r0,r0,#0x1f Here, the bit clear instruction is used to clear all interrupts and only set the mode control bit. orr r0,r0,#0x13 Calculate to super protection mode. msr cpsr,r0 Set cpsr to super protection mode. By setting the CPSR register of ARM, the CPU runs in the operating system mode, preparing for other operations later. The following code is as follows: /* * When starting from FLASH, memory test must be performed. When * starting from RAM, it is generally when developing the original source program, * it can be skipped. * */ #ifdef CONFIG_INIT_CRITICAL bl cpu_init_crit /* * Before relocation, RAM access time test must be performed, because each development * is different. * You can see its description in the file memsetup.S. */ bl memsetup #endif /* Relocate */ relocate: /* Relocate Boot code to RAM memory, for example, from FLASH to RAM */ adr r0, _start /* Move the relative address of _start to r0 */ ldr r1, _TEXT_BASE /* The _TEXT_BASE address is the address where BOOT runs in RAM */ cmp r0, r1 /* Compare the two addresses to see if they are the same. If they are the same, it is running in RAM, otherwise it is running in FLASH. */ beq stack_setup M Development Forum /* It runs in FLASH. Move the BOOT code in FLASH to RAM and then run it. */ ldr r2, _ARMboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 saves the size of the boot code*/ add r2, r0, r2 /* r2 saves the last address of the boot code*/ copy_loop: ldmia r0!, {r3-r10} /* Read 8 bytes from source address [r0] to the register. Each time one is read, the r0 address is updated 5 times*/ stmia r1!, {r3-r10} /* Copy the value of register r3-r10 and save it to the address specified by [r1]. Each time a byte is written, it increases by 1. */ cmp r0, r2 /* Determine whether to copy to the [r2] address, which is the end position of the boot code. */ ble copy_loop /* Loop copy */ /*Copy the interrupt vector table, which actually builds a secondary interrupt vector table. When the CPU is interrupted, the FLASH interrupt is run first, and then it is transferred to the actual table to execute the ARM interrupt program. */ adr r0, real_vectors add r2, r0, #1024 ldr r1, =0x0c000000 add r1, r1, #0x08 vector_copy_loop: ldmia r0!, {r3-r10} stmia r1!, {r3-r10} cmp r0, r2 ble vector_copy_loop /* Establish a stack*/ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ CONFIG_STACKSIZE_FIQ) #endif sub sp, r0, #12 /* leave 3 words for abort-stack */ ldr pc, _start_armboot /* The stack is ready, so you can jump to the code written in C. Since my code is ARM, it jumps to lib_arm\board.c(208):void start_ARMboot (void) to run. */ string 5 _start_armboot: .word start_ARMboot string 5 In this way, the startup code of an ARM is written! /************************************************************************** * CPU_init_critical critical section registers* Set some important registers,And do a memory test. ************************************************************************* */ #define INTCON (0x01c00000 0x200000) /* Interrupt controller*/ #define INTMSK (0x01c00000 0x20000c) /* Interrupt control mask register*/ #define LOCKTIME (0x01c00000 0x18000c) #define PLLCON (0x01c00000 0x180000) #define CLKCON (0x01c00000 0x180004) #define WTCON (0x01c00000 0x130000) ARM cpu_init_crit: string 8 /* Turn off watchdog*/ ldr r0, =WTCON ldr r1, =0x0 str r1, [r0] ARM /** Clear all interrupt bits and set INTMRs to implement. */ ldr r1,=INTMSK ldr r0, =0x03fffeff str r0, [r1] ldr r1, =INTCON ldr r0, =0x05 str r0, [r1] ARM Development Forum /* Set the clock control register*/ ldr r1, =LOCKTIME ldrb r0, =800 strb r0, [r1] String 4 /* Set the phase-locked loop to control the CPU running speed. /* 66MHz (Quartz=11MHz) */ #elif CONFIG_S3C44B0_CLOCK_SPEED==75 ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */ #else 字弦4 # error CONFIG_S3C44B0_CLOCK_SPEED undefined #endif str r0, [r1] ldr r1,=CLKCON ldr r0, =0x7ff8 str r0, [r1] ARM /* Return from calling subroutine*/ mov pc, lr 字弦8 /*****************************************************/ /* String 8 not_used: /* we *should* never reach this */ mov r6, #7 b reset irq: mov r6, #8 b reset fiq: mov r6, #9 b reset ARM String 9 not_used: /* we *should* never reach this */ mov r6, #7 b reset irq: mov r6, #8 b reset fiq: mov r6, #9 b reset ARM After reading the boot assembly, the C runtime environment has been prepared. Now start to learn the C source code, from the start.S file to the file lib_ARM\board.c to run the string 5 lines. /* The boot program jumps from the assembly start.S to here for execution. Cai Junsheng 2005/07/19*/ void start_ARMboot (void) { /* Declare a global pointer, which points to a data structure for storing parameters. And it occupies the r8 register, which is used to store memory addresses for global use. */ DECLARE_GLOBAL_DATA_PTR; ulong size; init_fnc_t **init_fnc_ptr; char *s; ARM #if defined(CONFIG_VFD) defined(CONFIG_LCD) unsigned long addr; string 4 #endif /* The gd pointer can be written because a register has been assigned to it as a variable. This is equivalent to saving the address calculated later to the r8 register. */ gd = (gd_t*)(_ARMboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); /* The following sentence prevents GCC versions above 3.4 from performing code optimization and deletes the following code. */ 字弦4 __asm__ __volatile__("": : :"memory"); 字弦8 /* Clear the structure pointed to by gd*/ memset ((void*)gd, 0, sizeof (gd_t)); /* */ gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); monitor_flash_len = _bss_start - _ARMboot_start; 字弦5 This section prepares the global variable area for storing parameters. The following is a series of initializations and obtaining the correct parameters. 字弦4 /* Call all initialization functions in a loop*/ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { /* When each function fails to initialize, it will hang here. */ hang(); } } Last time, we talked about calling all initialization functions for initialization in the function pointer array. Now let's analyze carefully what ARM they are doing, what kind of initialization they are doing, and how to prepare for the subsequent operation. The first initialization function is CPU initialization (cpu_init). This function is in cpu\s3c44b0\cpu.c. Its function is to initialize S3C44B0. The content of this function is as follows: String 5 /* CPU initialization. Cai Junsheng 2005/07/23*/ int cpu_init (void) { /* Clear the buffer*/ icache_enable(); return 0; } It calls the function icache_enable(), which is used to initialize the buffer of S3C44B0 and enable the CPU buffer. Because after the CPU is powered on, its initialization value is not to enable the internal 8K buffer,It must be set by the program. Next, let's see how the called function initializes the internal buffer area? /* Initialize the CPU memory buffer. Cai Junsheng 2005/07/23*/ void icache_enable (void) { ulong reg; /* Clear the memory buffer. */ s3c44b0_flush_cache(); /* Initialize the buffer and set the start and end addresses of the non-buffer. The first register indicates that the following address should not be cached. The lower 16 bits are the start address and the upper 16 bits are the end address. And the space size is bounded by 4K. 0x0000:0000 - 0x0C00:0000*/ M Development Forum NCACHBE0 = 0xC0000000; NCACHBE1 = 0x00000000; ARM /* Set the SYSCFG register to enable the 8K buffer. */ M Development Forum reg = SYSCFG; reg = 0x00000006; /* 8kB */ String 8 SYSCFG = reg; } String 4 In this function, the first function called is to clear the buffer, which has some special features

This post is from ARM Technology

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Related articles more>>

    EEWorld
    subscription
    account

    EEWorld
    service
    account

    Automotive
    development
    circle

    Robot
    development
    community

    Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
    快速回复 返回顶部 Return list