Address space is more important, 0-0X2FFFFFFF SDRAM peripherals, 0X3C000000-0X3C00DFFF embedded SRAM 0xffff0000
0xFFFFFFFF 16K Internal boot ROM, this I certainly do not need, I use the off-chip NAND start, there is a mapping address and related considerations the original old code inside
Let's speed up. Enable the PLL.
Ldr r0, =clk_sel
ldr R1, =0xfff
str R1, [r0]//Select external CLK as CPU clock
ldr r0, =clk_div
LDR R1, =0x05000000
str R1, [r0]//CPU:AHB:APB = 1:2:4
ldr r0, =pll_con0
ldr R1, =0x4f24
str R1, [r0]//-MHz
I can't find Clksel this register, the official manual in Nuc970 No, and I found this sentence
Pa.2
system clock Source Selection
NUC970 TECHNICAL REFERENCE MANUAL
0 = System clock is from-MHz crystal .
PWRON[2]
1 = System clock is from UPLL output:
Finally, my lowlevelinit. S decided to be a very simple #include <config.h>
#define AIC_MDCR 0xb8002138//AIC Mask Disable Command Register
#define AIC_MDCRH 0xb800213c//AIC mask Disable Comm and (high) Register
. Globl lowlevel_init
lowlevel_init:
//Disable Interrupt, the is for safe ...
Ldr r0, =AIC_MDCR
ldr R1, =0xffffffff
str R1, [r0]
ldr r0, =AIC_MDCRH
str R1, [R0]
Mrs R0, CPSR
o RR R0, R0, #0xC0
msr cpsr_c, r0
mov pc, LR
The following is going to determine cort0, in the
ENTRY (_main)
/
* * Set up initial C runtime environment and call Board_init_f (0).
*/
#if defined (config_spl_build) && defined (config_spl_stack)
Ldr sp, = (config_spl_stack)
#else
Ldr sp, = (config_sys_init_sp_addr)
#endif
#if defined (config_cpu_v7m)/* v7m forbids using SP as BIC Destina tion */
mov r3, SP
BIC R3, R3, #7
mov sp, r3
#else
Bic sp, SP, #7/* 8-byte alignment for ABI comp Liance */
#endif
mov r0, sp
bl board_init_f_alloc_reserve
mov sp, r0/
* Set up GD here, outside a NY C Code */
mov r9, r0
bl board_init_f_init_reserve
mov r0, #0
bl Board_init_f
Involved in the two large knowledge, SPL mode, to know in recent years uboot have the SPL, on the above know Board_init_f before the code.
The above pile is to determine the SP pointer, to know that the call C function does not stack can not, the specific location will be analyzed,
Look at Board_init_f_alloc_reserve First,
* Allocate reserved space for use as ' globals ' from ' top ' address and * return ' bottom ' address of allocated space * * not ES: * * Actual reservation cannot be do from within this function as * it requires altering the C stack pointer
would be do by * the caller upon return from this function. * * * IMPORTANT: * * Alignment constraints may differ for each ' chunk ' allocated. For now: * *-GD was aligned down on a 16-byte boundary *-The early malloc arena was not aligned, therefore it follows th
e stack * Alignment constraint of the architecture for which we is bulding. * *-GD is allocated last, so then the return value of this functions are * both the bottom of the reserved area and the A Ddress of GD, should * The calling context need It.ulong Board_init_f_alloc_reserve (ulong top) {/* Reserve early malloc a
Rena */#if defined (config_sys_malloc_f) top-= Config_sys_malloc_f_len; #endif/* Last:reserve GD (rounded up to a multiple of bytes) */top = RoundDown (Top-sizeof (sTruct global_data), 16);
return top; }
It is necessary to emphasize that the Assembly calls the C function parameter transfer problem, R0 is the parameter one, is the caller layer defined SP (has been sent to R0)
Preserve the GD and Sys_malloc regions, 16-byte aligned. Location of SP changes at this time
The second function is a bit of a hassle.
void Board_init_f_init_reserve (ULONG base)
{
struct global_data *gd_ptr;
#ifndef _use_memcpy
int *ptr;
#endif
/
* * Clear GD entirely and set it up.
* Use Gd_ptr, as GD could not properly set yet.
*
/gd_ptr = (struct global_data *) base;
/* Zero the area *
/#ifdef _use_memcpy
memset (gd_ptr, ' + ', sizeof (*GD));
#else for
(ptr = (int *) gd_ptr; ptr < (int *) (gd_ptr + 1);)
*ptr++ = 0;
#endif
/* Set GD unless architecture did it already *
/#if!defined (config_arm)
arch_setup_gd (gd_ptr); # endif
/* Next alloc'll be higher by one GD plus 16-byte alignment */
base + roundup (sizeof (struct global_data ), (+);
/
* * Record early malloc arena start.
* Use GD as it's now properly set for all architectures.
*
/#if defined (config_sys_malloc_f)/
* Go down one ' early MALLOC arena ' */
gd->malloc_base = base;
/* Next alloc'll be higher by one ' early malloc arena ' size */
base + = Config_sys_malloc_f_len;
#endif
}
First look at the code is very interesting, in fact, I think the big function is clear 0 of the last reservation area, but the implementation is also very interesting, first gd_ptr = (struct global_data *) base; Bottom for (ptr = (int *) gd_ptr; ptr < (int *) (gd_ptr + 1) specified GD is the only reserved address
*ptr++ = 0;
The two clear 0 way, this is very interesting to see the *++ statement, although the same sibling operation but the change of PTR to the overall expression after the result of * (ptr++), but the PTR itself changes to a slower step
MOV r9,r0 R9 for pre-occupied registers, storage GD, of course, this does not matter.
Ask a question: What is the storage structure that this code divides into? SP pointer, GD pointer, malloc area.
Next, learn what SPL is.