u-boot执行顺序start_armboot
2017-08-04 15:48
274 查看
start_armboot
init_fnc_t **init_fnc_ptr; /* Pointer is writable since we allocated a register for it */ gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); memset ((void*)gd, 0, sizeof (gd_t)); gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); memset (gd->bd, 0, sizeof (bd_t)); gd->flags |= GD_FLG_RELOC; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } } 1/init_fnc_t typedef int (init_fnc_t) (void); //这是一个函数类型,但是我们一般定义 是要这么定义的 //typedef int (*init_fnc_t) (void); 2/ init_fnc_t **init_fnc_ptr; //定义了一个二级指针. //init_fnc_t * 是个函数地址类型的指针. //那么 init_fnc_t ** 类型是个函数地址类型的指针的地址类型. //对应于 init_fnc_t *init_sequence[];中的 init_sequence(元素首地址),元素为 init_fnc_t * ,那么地址是 init_fnc_t **,对元素的引用是 (*init_sequence)() 3/_armboot_start //这玩意的出处是 arch/arm/cpu/hi3531a/start.S 中的 .globl _armboot_start _armboot_start: 在汇编中, 这仅仅是一个地址而已.也就是说将该地址标号为_armboot_start,以便后面使用,而这个地方的地址究竟为多少,则由链接器决定. 4/CONFIG_SYS_MALLOC_LEN //这玩意的处处是 include/configs/hi3531a.h ,值为 0x40000 + 128 * 1024 = 384KB 5/sizeof(gd_t) gt_t 是一个结构体类型.求所占字节数的时候要考虑对齐 6/gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); //这里只是一个赋值,那么这个变量的定义在哪呢? //在 arch/arm/lib/board.c中的 DECLARE_GLOBAL_DATA_PTR; //#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8") //这里定义了一个变量,这个变量的值在 寄存器 r8中, 在赋值后,(gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)) 的值放在 r8 中. //求得的地址是在哪呢?这是虚拟地址还是什么地址? 80801054 <_armboot_start>: 80801054: 80800000 addhi r0, r0, r0 2056MB //这个 _armboot_start 为 0x80801054,大约2GB左右.肯定不是物理地址.因为我的ram没有2GB. /* * The following data structure is placed in some memory wich is * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or * some locked parts of the data cache) to allow for a minimum set of * global variables during system initialization (until we have set * up the memory controller so that we can use RAM). * * Keep it *SMALL* and remember to set (128) CONFIG_SYS_GBL_DATA_SIZE > sizeof(gd_t) */ //这个结构体不在RAM中,那么在哪里? 7/__asm__ __volatile__("": : :"memory"); //memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作 废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。 8/memset ((void*)gd, 0, sizeof (gd_t)); 清gd 9/gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); 赋值成员bd 10/memset (gd->bd, 0, sizeof (bd_t)); 清bd 11/gd->flags |= GD_FLG_RELOC; 赋值成员flags 12/然后就是序列初始化 init_fnc_t *init_sequence[] = { timer_init, /* initialize timer before usb init */ board_init, /* basic board dependent setup */ // timer_init, /* initialize timer */ env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ display_banner, /* say that we are here */ dram_init, /* configure available RAM banks */ /* display_dram_config */ NULL, }; 12.1/timer_init 步骤: 1/设置时钟频率(系统控制器) 2/设置控制器(清空) 3/装载计数值 4/设置控制器(启动) 12.2/board_init 步骤: 1/选择晶振 2/设置bd 3/boot_flag_init//查到是spi 还是 nand 12.3/env_init 步骤: 1/判断是spi还是nand 2/并调用相应的函数. 3/设置gd->env_addr为环境变量数组第一个元素的地址 12.4/init_baudrate 步骤: 1/从环境变量中取值,得到波特率. 2/将波特率存入gd->baudrate gd->bd->bi_baudrate 12.5/serial_init 步骤: 1/dsiable 2/设置波特率 3/enable 12.6/console_init_f 步骤: 1/gd->have_console = 1 12.7/display_banner 步骤: 打印信息 printf//不知道现在能不能打印出来 debug//不知道打印到哪里 12.8/dram_init 步骤: 设置 gd->bd->bi_dram[0]
.text 0x40800000 0x387a8 0x40800000 __text_start = . arch/arm/cpu/hi3531a/start.o(.text) .text 0x40800000 0x28c0 arch/arm/cpu/hi3531a/start.o 0x40800000 _start 0x40802040 _blank_zone_start 0x40802044 _blank_zone_end 0x40802054 _armboot_start 0x40802058 _bss_start 0x4080205c _bss_end 0x408025e0 v7_flush_dcache_all 0x4080268c init_registers
13/mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,CONFIG_SYS_MALLOC_LEN); //将 _armboot_start - CONFIG_SYS_MALLOC_LEN 到 _armboot_start 清空 ,设置为内存,由全局变量存储 14/display_flash_config (flash_init ()); //没找到flash_init 函数 //display_flash_config为打印信息函数 15/spi_flash_probe(0, 0, 0, 0); //spiflash = hifmc100_spi_nor_probe(&spiinfo_ex); //drivers/mtd/spi/spi_compatible.c //这里主要是填充一个spiflash 结构体变量 //里面做了 //1/和芯片交互,得到ids(很多身份验证码) //2/然后和写好的表进行比较,比较之后,将读写擦除,赋值.但是只是验证是否表里有没有相应的flash //3/填充对应的读写函数.(不根据芯片来区分)(好怪,那为什么第二步要遍历,并且赋值) /* it is not needed in A7 in A17-A7 */ 16/nand_init(); /* go init the NAND */ /* initialize environment */ 17/env_relocate (); //从flash里面读,读出来的值更新环境变量,更新gd->env_addr /* IP Address */ 18/gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); //得到ip 19/stdio_init (); /* get the devices list going. */ //这是一个链表,只要是在这个链表里面的,都会被发送字符. //新建一个stdio_init链表,并且将一些设备加入到链表里面. 20/jumptable_init (); //gd->jt 申请内存,并填充 一些函数指针 ,填充getc 到 gd->jt[XF_getc] //但是这些 XF_getc 是什么,并不知道 20/console_init_r (); /* fully init console as a device */ //设置一些跟串口有关的 gd->jt[XF_getc] //设置 inputdev outputdev errdev ,并将其装进 stdio_devices /* miscellaneous platform dependent initialisations */ 21/misc_init_r (); //setenv("verify", "n"); /* enable exceptions */ 22/enable_interrupts (); /* enable IRQ interrupts */ void enable_interrupts (void) { unsigned long temp; __asm__ __volatile__("mrs %0, cpsr\n" "bic %0, %0, #0x80\n" "msr cpsr_c, %0" : "=r" (temp) : : "memory"); } /* Perform network card initialisation if necessary */ /* Initialize from environment */ 23/if ((s = getenv ("loadaddr")) != NULL) { load_addr = simple_strtoul (s, NULL, 16); } 24/if ((s = getenv ("bootfile")) != NULL) { copy_filename (BootFile, s, sizeof (BootFile)); } //一般情况下这两个环境变量不设置 25/eth_initialize(gd->bd); // 1/新建一个链表头,mii_devs extern void download_boot(const int (*handle)(void)); download_boot(NULL); product_control();
参考资料
_armboot_start 内容的疑问相关文章推荐
- OK6410 uboot1.1.16/lib.arm的board.c相关函数分析(C语言执行的第一个函数start_armboot)
- GDB单步调试uboot时程序执行顺序混乱
- u-boot中代码的疑问(_armboot_start与_start?) (转)
- Unity3d中的Awake()、OnEnable()、Start()等默认函数的执行顺序和生命周期
- Unity3d中的Awake()、OnEnable()、Start()等默认函数的执行顺序和生命周期
- u-boot: _start, _armboot_start, .word等概念的理解
- uboot 中的 start_armboot (void)
- 脚本Awake,Enable,Start执行顺序
- Unity3d中的Awake()、OnEnable()、Start()等默认函数的执行顺序和生命周期
- u-boot中 _start, _armboot_start, .word等概念的理解
- u-boot中代码的疑问(_armboot_start与_start?)
- Unity3d - Awake()、OnEnable()、Start()等默认函数的执行顺序和生命周期
- u-boot的执行流程分析start.s
- spring boot Junit 执行顺序
- 一篇鸡肋似得,关于u-boot中 _start 和 _armboot_start关系的帖子
- uboot中C语言代码入口函数(start_armboot)的注释
- 第1阶段——uboot分析之硬件初始化start_armboot函数(5)
- S5PV210-uboot解析(三)-start_armboot解析
- Tip8:Unity中诸如 Awake() Start() Update()等函数的 执行顺序
- DECLARE_GLOBAL_DATA_PTR、gd_t、bd_t及uboot中 start_armboot 代码分析