• u-boot(三)启动文件



    title: u-boot(三)启动文件
    tags: linux
    date: 2018-09-24 20:56:05

    u-boot(三)启动文件

    汇编

    cpu/arm920t/start.S

    u-boot也是一个牛逼的单片机程序,所以也就需要:

    1. 硬件相关初始化
      1. 看门狗
      2. 时钟
      3. sdram
      4. nand copy程序
    2. 设置sp
    3. 接下去就是读取内核,启动内核等

    程序实际的步骤是:

    1.set the cpu to SVC32 mode
    2.turn off the watchdog
    3.mask all IRQs
    4.判断是不是从内部ram启动还是仿真直接烧写到链接地址,如果不在正确的加载地址的话,执行cpu_init_crit
      cpu_init_crit执行SDRAM初始化
    	flush v4 I/D caches,
    	disable MMU stuff and caches,
    	lowlevel_init 这个会去初始化sdram,这个函数在lowlevel_init.S in your board directory
    					也就是board100ask24x0lowlevel_init.S
    5.Set up the stack
    6.clock_init		board100ask24x0oot_init.c
    7.relocate			 自动识别当前是nor还是nand启动,nand启动时自动cp到内部ram中运行,所以可写
    8.bss段清零
    9.调用C函数 _start_armboot
    

    堆栈设置如下

    0x33F80000 uboot程序
    ·=-CFG_MALLOC_LEN malloc area
    .=-CFG_GBL_DATA_SIZE bdinfo
    .=-CONFIG_STACKSIZE_IRQ IRQ 的栈
    .=-CONFIG_STACKSIZE_FIQ FRQ的栈
    .=-12 leave 3 words for abort-stack
    sp的初始位置

    内存图:

    mark

    C:_start_armboot

    文件路径:lib_armoard.c,这里就是u-boot执行C代码的地方了.

    • 分配了一个gd的结构体内存

      gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
      
      //在这里,_armboot_start=_start,根据链接脚本,这也就是代码段的起始=0x33F80000
      //也就是指向了内存图128的地方了
      
    • init_sequence这里执行一些初始化

      • board_init中设置了gd->bd->bi_arch_number = MACH_TYPE_S3C2440;,设置了一个参数gd->bd->bi_boot_params = 0x30000100;这个就是启动内核参数的地址
    • flash/nand 初始化

    • 堆栈初始化

    • 环境变量的设置存储(一种是代码写死,一种在FLASH上保存)

    • 进入主循环main_loop

    代码摘要

    void start_armboot (void)
    {
    //-----
    	/* Pointer is writable since we allocated a register for it */
    	gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));    
    //-----    
        //函数指针,初始化设备
    	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
    		if ((*init_fnc_ptr)() != 0) {
    			hang ();
    		}
    	}
    //----  flash初始化,识别    
    #ifndef CFG_NO_FLASH
    	/* configure available FLASH banks */
    	size = flash_init ();
    	display_flash_config (size);
    #endif /* CFG_NO_FLASH */    
    ////----  nand初始化   
    #if (CONFIG_COMMANDS & CFG_CMD_NAND)
    	puts ("NAND:  ");
    	nand_init();		/* go init the NAND */
    #endif
    //------
        //分配堆
    	/* armboot_start is defined in the board-specific linker script */
    	mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
    //-----
        //uboot的环境变量
    	/* initialize environment */
    	env_relocate ();
    //-----
        //经过一系列的初始化
    	/* main_loop() can return to retry autoboot, if so just run it again. */
    	for (;;) {
    		main_loop ();
    
    }
    
    
    init_fnc_t *init_sequence[] = {
    	cpu_init,		/* basic cpu dependent setup */
    	board_init,		/* basic board dependent setup */
    	interrupt_init,		/* set up exceptions */
    	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 */
    #if defined(CONFIG_DISPLAY_CPUINFO)
    	print_cpuinfo,		/* display cpu info (and speed) */
    #endif
    #if defined(CONFIG_DISPLAY_BOARDINFO)
    	checkboard,		/* display board info */
    #endif
    	dram_init,		/* configure available RAM banks */
    	display_dram_config,
    	NULL,
    };
    
    int board_init (void)
    {
        ---
        /* support both of S3C2410 and S3C2440, by www.100ask.net */
        if (isS3C2410)
        {
            /* arch number of SMDK2410-Board */
            gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
        }
        else
        {
            /* arch number of SMDK2440-Board */
            gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
        }
    
        /* adress of boot parameters */
        gd->bd->bi_boot_params = 0x30000100;
    
    }
    

    C:main_loop

    common/main.c

    内核启动

    这里实现了u-boot的倒计时,有打印命令,获取环境变量等,最关键的代码是

    s = getenv ("bootcmd");    
    if(倒计时结束)
    {
        printf("Booting Linux ...
    ");            
        run_command (s, 0);
     }
    

    实际的环境变量是bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0,读取内核,启动内核

    菜单处理(自定义实现)

    如果倒计时结束前输入了空格,进入命令模式run_command("menu", 0);

    命令处理

    1. 死循环
    2. 读取串口输入len = readline (CFG_PROMPT);
    3. 执行命令rc = run_command (lastcommand, flag);
  • 相关阅读:
    合格linux运维人员必会的30道shell编程实践题及讲解
    合格linux运维人员必会的30道shell编程实践题及讲解-13
    合格linux运维人员必会的30道shell编程实践题及讲解-12
    合格linux运维人员必会的30道shell编程实践题及讲解-11
    合格linux运维人员必会的30道shell编程实践题及讲解-10
    合格linux运维人员必会的30道shell编程实践题及讲解-09
    学习Vim的四周计划
    Linux shell 逻辑运算符、逻辑表达式详解
    60个DevOps开源工具,你在用哪些?
    误删重要文件怎么办?学会Linux 救援模式再也不担心
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10023676.html
Copyright © 2020-2023  润新知