S3C2440移植uboot之启动过程概述

发布者:梦幻之光最新更新时间:2021-07-16 来源: eefocus关键字:S3C2440  启动过程 手机看文章 扫描二维码
随时随地手机看文章

文章目录

1.分析start.S

2._start会跳转到start_code处

3.然后进入第一个C数:board_init_f()

4.接下来进入重定位

5.清除bss段


移植Uboot其他文章链接:


S3C2440移植uboot之编译烧写uboot


S3C2440移植uboot之新建单板_时钟_SDRAM_串口


S3C2440移植uboot之启动过程概述


S3C2440移植uboot之支持NAND启动


S3C2440移植uboot之支持NORFLASH


S3C2440移植uboot之支持NANDFLASH操作


S3C2440移植uboot之支持DM9000


S3C2440移植uboot之裁剪和修改默认参数


S3C2440移植uboot之支持烧写yaffs映像及制作补丁

下图为编译uboot后显示的最后一条链接命令。

在这里插入图片描述

1.分析start.S

打开uboot.lds,发现链接地址为0,所以新的uboot只能在nor flash运行。运行开始文件为start.o。

在这里插入图片描述

下面我们分析arch/arm/cpu/arm920t/start.S


从start_code开始运行


.globl _start                                //声明_start全局符号,这个符号会被lds链接脚本用到_start:    b     start_code                            //跳转到start_code符号处,0x00   ldr   pc, _undefined_instruction                    //0x04   ldr   pc, _software_interrupt                       //0x08   ldr   pc, _prefetch_abort                           //0x0c   ldr   pc, _data_abort                               //0x10   ldr   pc, _not_used                                 //0x14   ldr   pc, _irq                                      //0x18   ldr   pc, _fiq                                      //0x20_undefined_instruction:  .word undefined_instruction           //定义_undefined_instruction指向undefined_instruction(32位地址)_software_interrupt:      .word software_interrupt

_prefetch_abort:    .word prefetch_abort

_data_abort:          .word data_abort

_not_used:             .word not_used

_irq:               .word irq

_fiq:               .word fiq   .balignl 16,0xdeadbeef        //balignl使用,参考http://www.cnblogs.com/lifexy/p/7171507.html


2._start会跳转到start_code处

start_code:/*设置CPSR寄存器,让CPU进入管理模式*/   mrs  r0, cpsr                 //读出cpsr的值   bic   r0, r0, #0x1f           //清位   orr   r0, r0, #0xd3          //位或   msr  cpsr, r0                 //写入cpsr#if   defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)   /*

        * relocate exception table

        */   ldr   r0, =_start            

       ldr   r1, =0x0                //r1等于异常向量基地址   mov r2, #16copyex:   subs       r2, r2, #1           //减16次,s表示每次减都要更新条件标志位   ldr   r3, [r0], #4       

       str   r3, [r1], #4      //将_start标号后的16个符号存到异常向量基地址0x0~0x3c处   bne  copyex             //直到r2减为0#endif#ifdef CONFIG_S3C24X0   /* 关看门狗*/#  define pWTCON       0x53000000#  define INTMSK 0x4A000008    /* Interrupt-Controller base addresses */#  define INTSUBMSK  0x4A00001C#  define CLKDIVN       0x4C000014    /* clock divisor register */   ldr   r0, =pWTCON       

       mov r1, #0x0        

       str   r1, [r0]           //关看门狗,使WTCON寄存器=0   /*关中断*/   mov r1, #0xffffffff   ldr   r0, =INTMSK

       str   r1, [r0]                  //关闭所有中断# if defined(CONFIG_S3C2410)   ldr   r1, =0x3ff   ldr   r0, =INTSUBMSK

       str   r1, [r0]                  //关闭次级所有中断# endif/* 设置时钟频率, FCLK:HCLK:PCLK = 1:2:4 ,而FCLK默认为120Mhz*/   ldr   r0, =CLKDIVN

       mov r1, #3   str   r1, [r0]


 #ifndef CONFIG_SKIP_LOWLEVEL_INIT   bl    cpu_init_crit                         //关闭mmu,并初始化各个bank#endifcall_board_init_f:   ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR) //CONFIG_SYS_INIT_SP_ADDR=0x30000f80   bic   sp, sp, #7         //sp=0x30000f80   ldr   r0,=0x00000000   bl    board_init_f


上面的CONFIG_SYS_INIT_SP_ADDR =0x30000f80,是通过arm-linux-objdump -D u-boot>u-boot.dis生成反汇编,然后从u-boot.dis得到的。


3.然后进入第一个C数:board_init_f()


该函数主要工作是:


清空gd指向的结构体、通过init_sequence函数数组,来初  始化各个函数以及逐步填充gd结构体,最后划分内存区域,  将数据保存在gd里,然后调用relocate_code()对uboot重定位。

(gd是用来传递给内核的参数)


1)具体代码如下所示:


void board_init_f(ulong bootflag) // bootflag=0x00000000{   bd_t *bd;   init_fnc_t **init_fnc_ptr;         //函数指针   gd_t *id;   ulong addr, addr_sp;#ifdef CONFIG_PRAM   ulong reg;#endif   bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");   /* Pointer is writable since we allocated a register for it */   gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);


其中gd是一个全局变量,用来传递给内核的参数用的,如下图所示,在arch/arn/include/asm/global_data.h中定义,*gd指向r8寄存器,所以r8专门提供给gd使用

在这里插入图片描述

而CONFIG_SYS_INIT_SP_ADDR,在之前得到=0x30000f80,所以gd=0x30000f80


2)继续来看board_init_f():


__asm__ __volatile__("": : :"memory");           //memory:让cpu重新读取内存的数据  memset((void *)gd, 0, sizeof(gd_t));        //将0x30000f80地址上的gd_t结构体清0  gd->mon_len = _bss_end_ofs;  

         // _bss_end_ofs =__bss_end__ - _start,在反汇编找到等于0xae4e0,所以mon_len等于uboot的数据长度  gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob);   for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)//调用init_sequence[]数组里的各个函数  {  if ((*init_fnc_ptr)() != 0)     //执行函数,若函数执行出错,则进入hang() {               hang ();   //打印错误信息,然后一直while }   }

  上面的init_sequence[]数组里存了各个函数,比如有:

  board_early_init_f():设置系统时钟,设置各个GPIO引脚

  timer_init():初始化定时器

  env_init():设置gd的成员变量

  init_baudrate():设置波特率

  dram_init():设置gd->ram_size= 0x04000000(64MB)


3)继续来看board_init_f():


addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;  // addr=0x34000000 // CONFIG_SYS_SDRAM_BASE:  SDRAM基地址,为0X30000000// gd->ram_size:          等于0x04000000 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))   /* reserve TLB table */   addr -= (4096 * 4);        //addr=33FFC000   addr &= ~(0x10000 - 1);  // addr=33FF0000,      gd->tlb_addr = addr;   //将64kB分配给TLB,所以TLB地址为33FF0000~33FFFFFF#endif   /* round down to next 4 kB limit */   addr &= ~(4096 - 1);                    //4kb对齐, addr=33FF0000   debug("Top of RAM usable for U-Boot at: %08lxn", addr);   /*

        * reserve memory for U-Boot code, data & bss

        * round down to next 4 kB limit

        */   addr -= gd->mon_len; // 在前面分析过gd->mon_len=0xae4e0,   //所以addr=33FF0000 -0xae4e0=33F41B20,   addr &= ~(4096 - 1);  //4095=0xfff,4kb对齐, addr=33F41000 //所以分配给uboot各个段的重定位地址为33F41000~33FFFFFF   debug("Reserving %ldk for U-Boot at: %08lxn", gd->mon_len >> 10, addr);#ifndef CONFIG_SPL_BUILD   addr_sp = addr - TOTAL_MALLOC_LEN; //分配一段malloc空间给addr_sp   //TOTAL_MALLOC_LEN=1024*1024*4,所以malloc空间为33BF1000~33F40FFF   addr_sp -= sizeof (bd_t);            //分配一段bd_t结构体大的空间    bd = (bd_t *) addr_sp;               //bd指向刚刚分配出来的bd_t结构体    gd->bd = bd;                         // 0x30000f80处的gd变量的成员bd等于bd_t基地址    addr_sp -= sizeof (gd_t);              //分配一个gd_t结构体大的空间    id = (gd_t *) addr_sp;                 //id指向刚刚分配的gd_t结构体    gd->irq_sp = addr_sp;                 //0x30000f80处的gd变量的成员irq_sp等于gd_t基地址    addr_sp -= 12;    addr_sp &= ~0x07;    ... ...    relocate_code(addr_sp, id, addr);  //进入relocate_code()函数,重定位代码,以及各个符号    // addr_sp: 栈顶,该栈顶向上的位置用来存放gd->irq_sp、id 、gd->bd、malloc、uboot、TLB(64kb),    //id:       存放 gd_t结构体的首地址    // addr:    等于存放uboot重定位地址33F41000}


执行完board_init_f()后,最终内存会划分如下图所示:

在这里插入图片描述

其实此时uboot还在flash中运行,然后会进入start.S的relocate_code()里进行uboot重定位


4.接下来进入重定位

1)start.S的relocate_code()代码如下所示


relocate_code:   mov r4, r0      /* save addr_sp */              // addr_sp栈顶值   mov r5, r1      /* save addr of gd */           // id值   mov r6, r2      /* save addr of destination */  // addr值:uboot重定位地址   /* Set up the stack        */stack_setup:   mov sp, r4                //设置栈addr_sp   adr  r0, _start           //在顶层目录下system.map符号文件中找到_start =0,所以r0=0   cmp r0, r6                //判断_start(uboot重定位之前的地址)和addr(重定位地址)是否一样   beq clear_bss             /* skip relocation */ 

[1] [2]
关键字:S3C2440  启动过程 引用地址:S3C2440移植uboot之启动过程概述

上一篇:S3C2440移植uboot之支持DM9000
下一篇:S3C2440移植uboot之编译烧写uboot

推荐阅读最新更新时间:2024-10-25 20:33

S3C2440移植uboot启动过程概述
文章目录 1.分析start.S 2._start会跳转到start_code处 3.然后进入第一个C数:board_init_f() 4.接下来进入重定位 5.清除bss段 移植Uboot其他文章链接: S3C2440移植uboot之编译烧写uboot S3C2440移植uboot之新建单板_时钟_SDRAM_串口 S3C2440移植uboot之启动过程概述 S3C2440移植uboot之支持NAND启动 S3C2440移植uboot之支持NORFLASH S3C2440移植uboot之支持NANDFLASH操作 S3C2440移植uboot之支持DM9000 S3C2440移植uboot之裁
[单片机]
<font color='red'>S3C2440</font><font color='red'>移植</font><font color='red'>uboot</font>之<font color='red'>启动</font><font color='red'>过程</font>概述
S3C2440移植uboot之支持NAND启动
上一节S3C2440移植uboot之新建单板_时钟_SDRAM_串口移植uboot初始化了时钟,配置了支持串口,这一节我们继续修改uboot支持NAND启动。 目录 1.去掉 -pie 选项 2.修改之前的init.c 3.修改start.s重定位部分 4.修改链接脚本 5.报错修改 6.重新修改链接地址 1.去掉 -pie 选项   参考之前uboot使用的start.S, init.c来修改uboot代码新的uboot链接地址位于0,且在arm-linux-ld时加了 -pie 选项, 使得u-boot.bin里多了 *(.rel*) , *(.dynsym) ,从而程序非常大,不利于从NAND启动(重定位之前的
[单片机]
<font color='red'>S3C2440</font><font color='red'>移植</font><font color='red'>uboot</font>之支持NAND<font color='red'>启动</font>
06-S3C2440学习之移植2012u-boot到S3C2440(移植过程二)支持NAND启动
说明: 原来的代码在链接时加了 -pie 选项, 使得u-boot.bin里多了 *(.rel*) , *(.dynsym) (*(.rel*) , *(.dynsym)这些地址信息用于实现UBOOT可以被拷贝到任何地方,更新地址信息),但使得程序非常大,结构复杂,不利于从NAND启动(重定位之前的启动代码应该少于4K)。所提去掉了pie功能。 (1)使用一下之前写的init.c 拷贝到2440单板下: 修改init内容为: /* NAND FLASH控制器 */ #define NFCONF (*((volatile unsigned long *)0x4E000000)) #define
[单片机]
06-S3C2440学习之<font color='red'>移植</font>2012u-boot到<font color='red'>S3C2440</font>(<font color='red'>移植</font><font color='red'>过程</font>二)支持NAND<font color='red'>启动</font>
uboots3c2440上的移植(6)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 10)u-boot利用tftp服务下载内核和利用nfs服务挂载nfs文件系统。 知识点: tftp服务的安装与配置及测试; nfs服务的安装与配置及测试; u-boot到kernel的参数传递(重点)。 我们知道使用tftp下载内核和使用nfs挂载文件系统的好处是,当我们重新编译内核或文件系统后不用重新把这些镜像文件再烧录到flash上,而是把
[单片机]
<font color='red'>uboot</font>在<font color='red'>s3c2440</font>上的<font color='red'>移植</font>(6)
uboots3c2440上的移植(4)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 在这一篇中,我们首先让开发板对CS8900或者DM9000X网卡的支持,然后再分析实现u-boot怎样来引导Linux内核启动。因为测试u-boot引导内核我们要用到网络下载功能。 7)u-boot对CS8900或者DM9000X网卡的支持。 u-boot-2009.08版本已经对CS8900和DM9000X网卡有比较完善的代码支持(代码在drivers/ne
[单片机]
<font color='red'>uboot</font>在<font color='red'>s3c2440</font>上的<font color='red'>移植</font>(4)
uboots3c2440上的移植(1)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 本次移植的功能特点包括: 支持Nand Flash读写 支持从Nor/Nand Flash启动 支持CS8900或者DM9000网卡 支持Yaffs文件系统 支持USB下载(还未实现) 1. 了解u-boot主要的目录结构和启动流程,如下图。 u-boot的stage1代码通常放在cpu/xxxx/start.S文件中,他用汇编语言写成
[单片机]
<font color='red'>uboot</font>在<font color='red'>s3c2440</font>上的<font color='red'>移植</font>(1)
uboots3c2440上的移植(3)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 5)准备进入u-boot的第二阶段(在u-boot中添加对我们开发板上Nand Flash的支持)。 目前u-boot中还没有对2440上Nand Flash的支持,也就是说要想u-boot从Nand Flash上启动得自己去实现了。 首先,在include/configs/my2440.h头文件中定义Nand要用到的宏和寄存器,如下: #gedit in
[单片机]
<font color='red'>uboot</font>在<font color='red'>s3c2440</font>上的<font color='red'>移植</font>(3)
uboots3c2440上的移植(5)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 9)实现u-boot对yaffs/yaffs2文件系统下载的支持。 注意:此篇对Nand的操作是基于MTD架构方式,在“u-boot-2009.08在2440上的移植详解(三)”中讲到过。 通常一个Nnad Flash存储设备由若干块组成,1个块由若干页组成。一般128MB以下容量的Nand Flash芯片,一页大小为528B,被依次分为2个256B的主数据区
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved