@ what head.S does(this is the stage1 of bootloader): @ 1. disable watch dog timer( watch dog timer is enable when reset) @ 2. disable all interrupts, using register INTMSK and INTSUBMSK @ 3. initialise system clocks: @ FCLK for CPU = 200MHz, HCLK for the AHB bus peripherals = 100MHz, and PCLK for the APB bus peripherals = 50MHz. @ Asynchronous @ 4. initialise the static memory---set memory control registers @ 5. check whether waked up from PWR_OFF mode, if do, call WakeupStart. @ 6. ALL LED on @ 7. set GPIO for UART @ 8. copy vivi to ram(copy_myself): @ a. set nand flash control registers @ b. set the stack pointer @ c. set parameters for C function nand_read_ll(arch/s3c2410/nand_read.c) @ d. call nand_read_ll to copy vivi from nand flash to ram @ e. verify the first 4k bytes data, compare between address range 0x00000000-0x00001000 and 0x33f00000-0x33f01000 @ 9. jump to ram(when execute arm-gcc-ld, it uses arch/vivi.lds to define that the base address is 0x33f00000, which is VIVI_RAM_BASE) : @ a. set the stack pointer @ b. set the parameters for C function main(init/main.c) @ c. call main 第二步: 进入main函数: /* * Step 1: * */ reset_handler(); /* include/reset_handle.h, do nothing */
/* * Step 3: * */ mem_map_init(); /*arch/s3c2410/mmu.c line194*/ /*1. call mem_map_nand_boot in arch/s3c2410/mmu.c this function call mem_mapping_linear immediately mem_mapping_linear(arch/s3c2410/mmu.c): initialize the mmu translation table, Make DRAM section cacheable 2. call cache_clean_invalidate in arch/s3c2410/mmu.c: clean and invalidate all cache lines 3. call tlb_invalidate in arch/s3c2410/mmu.c: invalidate I & D TLBs */ mmu_init(); /*arch/s3c2410/mmu.c line120*/ /*call arm920_setup in arch/s3c2410/mmu.c: 1. invalidate I,D caches 2. drain write buffer 3. invalidate I,D TLBs 4. load page table pointer(has been initialized at mmm_mapping_linear upside) 5. set MMU control registers: a. base location of exception = 0 (exception vectors' start address is 0x00000000) b. RS=0b00 (RS is not used as AP=0b11 which means all access types permitted in both supervisor and user mode) c. set little-endian d. mmu enable */ /* * Now, vivi is running on the ram. MMU is enabled. */ /* * Step 4: * */ /* initialize the heap area*/ ret = heap_init(); /*lib/heap.c*/ /*heap is a memory from which the function mmalloc require a memory block it calls mmalloc_init in lib/heap.c to initialize the heap */
/* add by thisway.diy */ usb_init();
/* Step 5: */ ret = mtd_dev_init(); /*drivers/mtd/mtdcore.c*/ /*it calls the functions mtd_init at drivers/mtd/maps/s3c2410_flash.c: calls smc_init at the same file: a. mmalloc memory for strcut mymtd b. initialize (struct nand_chip *)(&mymtd[1]) for NAND FLASH c. call smc_insert at the same file: call the functions smc_scan at drivers/mtd/nand/smc_core.c: read the ID of NAND FLASH, compare it with the pre-defined infomation of some usually types of NAND FLASH, and then set the NAND FLASH's data struct (struct nand_chip *)(&mymtd[1]). */ /* Step 6: * */ init_priv_data(); /*lib/priv_data/rw.c*/ /*there are two sets of vivi's parameters, one are the default parameters and the other are the saved parameters. init_priv_data load the default parameters on the memory, and then load the saved parameters and overwrite the corespointing part of the default parameters if the saved parameters is validate. The saved parameters were stored at the param partion of nand flash. 1. get_default_data(lib/priv_data/rw.c): a. get_default_param_tlb, defined at struct default_vivi_parameters at arch/s3c2410/smdk.c b. get_default_linux_cmd, copy linux command "char linux_cmd[] = "noinitrd root=/dev/mtdblock/0 init=/linuxrc console=ttyS0" "(arch/s3c2410/smdk.c) c. get_default_mtd_partition, defined at struct default_mtd_partitions at arch/s3c2410/smdk.c 2. load_saved_priv_data(lib/priv_data/rw.c): a. read_saved_priv_data_blk(at the same file), read the saved vivi parameters from the param part of nand flash to DRAM_BASE b. copy the saved tlb parameters from DRAM_BASE to overwrite what 1.a stores c. copy the saved linux command from DRAM_BASE to overwrite what 1.b stores d. copy the saved part parameters from DRAM_BASE to overwrite what 1.c stores */ /* Step 7: * */ misc(); /*arch/s3c2410/smdk.c*/ /*call the function add_command(&cpu_cmd) defined at lib/command.c, to add the cpu command to the command chain this command is used to change the cpu's clock */
/* Step 8: * */ boot_or_vivi(); /*call vivi_shell() or run_autoboot. 1. run_autoboot: exec_string("boot") (lib/command.c): parse the sting "boot", and then call the function execcmd: use the execcmd's parameter to find the boot_cmd's function and executive it: the boot_cmd was defined at lib/boot_kernel.c(see follow): user_command_t boot_cmd = { "boot", command_boot, NULL, "boot [{cmds}] \t\t\t-- Booting linux kernel" }; so, we call the function command_boot(lib/boot_kernel.c): a. media_type = get_param_value("media_type", &ret) (lib/priv_data/param.c), media_type=3 b. kernel_part = get_mtd_partition("kernel") (lib/priv_data/mtdpart.c), see also arch/s3c2410/smdk.c name: "kernel", offset: 0x00030000, size: 0x00100000, flag: 0 c. boot_kernel(from, size, media_type) (lib/boot_kernel.c): i. copy the kernel image from the kernel partion on nand flash to ram(boot_mem_base + LINUX_KERNEL_OFFSET, 0x30008000)using the copy_kernel_img. ii.setup_linux_param, set the linux parameters at boot_mem_base + LINUX_PARAM_OFFSET(0x30000100), these parameters were stored as a struct param_struct, which contains the command line parameter. iii.call_linux(0, mach_type, to) (boot_mem_base + LINUX_KERNEL_OFFSET=0x30008000) (1). cache_clean_invalidate (2). tlb_invalidate (3). use the inline asm to jump to linux kernel: define the p15 corprocessor: zero PID invalidate I,D caches drain write buffer invalidate I,D TLBs get control register disable MMU write control register set the PC register as the kernel address: mov pc, r2 2. vivi_shell: call the function serial_term at drivers/serial/term.c: a. printk("%s> ", prompt), display the string "vivi>" b. getcmd(cmd_buf, MAX_CMDBUF_SIZE) at drivers/serial/getcmd.c, wait for the command send from serial port by user c. exec_string(cmd_buf) at lib/command.c: parseargs execcmd */ /******************************************************************************************* Now, the DRAM is seperated to these parts; +-----------------------------------------------+ 0x33ff_ffff = 0x3000_0000+64M-1 + + + + + 1M VIVI + + + + + +-----------------------------------------------+ 0x33f0_0000 = VIVI_RAM_BASE + + + + + 1M HEAP + + + + + +-----------------------------------------------+ 0x33e0_0000 = HEAP_BASE + 16k MMU_TABLE + +-----------------------------------------------+ 0x33df_c000 = MMU_TABLE_BASE (used at the stage2 of bootloader) + 16k LINUX_CMD + + + LINUX_CMD_OFFSET = 16 k + 16k PARAMETER_TLB + + + PARAMETER_TLB_OFFSET = 16k + 16k PARAMETER_PART + +-----------------------------------------------+ 0x33df_0000 = VIVI_PRIV_RAM_BASE (PARAMETER_PART_OFFSET = 0) + + + 32k STACK + + + +-----------------------------------------------+ 0x33de_8000 = STACK_BASE + . + + . + + . + + . + + . + + . + +-----------------------------------------------+ + + + + + 1M LINUX KERNEL + + + + + +-----------------------------------------------+ 0x3000_8000 = the kernel image is placed begin this address + + + LINUX PAREMETER + +-----------------------------------------------+ LINUX_PARAM_OFFSET = 0x100 +-----------------------------------------------+ 0x3000_0000 = RAM_BASE
文章评论(0条评论)
登录后参与讨论