当前虽然编译成功了,但是对于我们自己的目标板并不太适用。还得做一系列得修改。

一、lds 文件分析

  u-boot 中最重要得链接文件即是,u-boot.lds。我们可以查看我们编译出来得 u-boot.lds 文件进行分析,原始文件在 arch/arm/cpu/ 下,编译出来得去掉了不想关得选项。

  u-boot.lds脚本文件告诉链接器linker如何布局代码段、数据段、bss段等,已经配置了u-boot自拷贝(从flash到RAM的copy)的内容。另外,还简要的涉及了动态链接技术等。

 /* 指定输出的可执行文件 elf 格式,32位,小端  */
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/* 指定输出可执行文件的平台为 arm */
OUTPUT_ARCH(arm)
/* 指定输出可执行文件的起始代码段为_start */
ENTRY(_start)
/* 指定可执行文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。
* 必须使编译器知道这个地址 */
SECTIONS
{
/* 从0x0位置开始 */
. = 0x00000000;
/* 代码以4字节对齐 */
. = ALIGN();
/* 代码段 */
.text :
{
/* u-boot将自己copy到RAM,此为需要copy的程序的start */
*(.__image_copy_start)
/* ./arch/arm/lib/vectors.S,异常向量表 */
*(.vectors)
/* ./arch/arm/cpu/arm920t/start.S */
arch/arm/cpu/arm920t/start.o (.text*)
/* 其他的代码段放在这里,即 start.S/vector.S 之后 */
*(.text*)
}
/* 代码段结束后,有可能4bytes不对齐了,此时做好4bytes对齐,以开始后面的.rodata段 */
. = ALIGN();
/* 在代码段之后,存放read only数据段 */
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
/* 4bytes对齐,以开始接下来的.data段 */
. = ALIGN();
/* 可读写数据段 */
.data : {
*(.data*)
}
/* 4字节对齐 */
. = ALIGN();
/* 当前地址为4字节对齐后的地址 */
. = .;
/* 4字节对齐 */
. = ALIGN();
/* .data段结束后,紧接着存放u-boot自有的一些function,例如u-boot command等 */
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN();
/* UEFI支持, */
.__efi_runtime_start : {
*(.__efi_runtime_start)
}
/* */
.efi_runtime : {
*(efi_runtime_text)
*(efi_runtime_data)
}
/* */
.__efi_runtime_stop : {
*(.__efi_runtime_stop)
}
/* */
.efi_runtime_rel_start :
{
*(.__efi_runtime_rel_start)
}
/* */
.efi_runtime_rel : {
*(.relefi_runtime_text)
*(.relefi_runtime_data)
}
/* UEFI结束 */
.efi_runtime_rel_stop :
{
*(.__efi_runtime_rel_stop)
}
/* 4字节对齐 */
. = ALIGN();
/* 至此,u-boot需要自拷贝的内容结束,总结一下,包括代码段,数据段,以及u_boot_list */
.image_copy_end :
{
*(.__image_copy_end)
}
/* 在老的uboot中,如果我们想要uboot启动后把自己拷贝到内存中的某个地方,只要把要拷贝的地址写给TEXT_BASE即可,
* 然后boot启动后就会把自己拷贝到TEXT_BASE内的地址处运行,在拷贝之前的代码都是相对的,不能出现绝对的跳转,否则会跑飞。
* 在新版的uboot里,TEXT_BASE的含义改变了。它表示用户要把这段代码加载到哪里,通常是通过串口等工具。
* 然后搬移的时候由uboot自己计算一个地址来进行搬移。新版的uboot采用了动态链接技术,在lds文件中有__rel_dyn_start和__rel_dyn_end,
* 这两个符号之间的区域存放着动态链接符号,只要给这里面的符号加上一定的偏移,拷贝到内存中代码的后面相应的位置处,
* 就可以在绝对跳转中找到正确的函数。 */
.rel_dyn_start :
{
*(.__rel_dyn_start)
}
/* 动态链接符存放在的段 */
.rel.dyn : {
*(.rel*)
}
/* 动态链接符段结束 */
.rel_dyn_end :
{
*(.__rel_dyn_end)
}
.end :
{
*(.__end)
}
/* bin文件结束 */
_image_binary_end = .;
. = ALIGN();
.mmutable : {
*(.mmutable)
} /* .bss节包含了程序中所有未初始化的全局变量 */
.bss_start __rel_dyn_start (OVERLAY) : {
KEEP(*(.__bss_start));
__bss_base = .;
}
.bss __bss_base (OVERLAY) : {
*(.bss*)
. = ALIGN();
__bss_limit = .;
}
/* bss段结束 */
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
} .dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) }
.plt : { *(.plt*) }
.interp : { *(.interp*) }
.gnu.hash : { *(.gnu.hash) }
.gnu : { *(.gnu*) }
.ARM.exidx : { *(.ARM.exidx*) }
.gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
}

二、norflash 介绍

  ARM的启动都是从0地址开始,所不同的是地址的映射不一样。在 arm 上电的时候,要想让 arm 知道以某种方式(地址映射方式)运行,不可能通过你写的某段程序控制,因为这时候你的程序还没启动,这时候arm会通过引脚的电平来判断。

2.1 硬件

2.1.1 存储器地址

  s3c2440  的存储器控制器为访问外部存储的需要器提供了存储器控制信号。 存储器控制器的地址空间总共有 8 个 bank,每个bank  为128M,总共为1G。除了 BANK0(16/32 位)之外,其它全部 BANK 都可编程访问位宽(8/16/32 位) 。

  • 8 个存储器 Bank

    • 6 个存储器 Bank 为 ROM,SRAM 等
    • 其余 2 个存储器 Bank 为 ROM,SRAM,SDRAM 等
    • 7 个固定的存储器 Bank 起始地址
    • 1 个可变的存储器 Bank 起始地址并 Bank 大小可编程
    • 所有存储器 Bank 的访问周期可编程

  

  • OM管脚是使能NAND Flash 的管脚,当OM=00时,是表示使用  NAND Flash 为引导 ROM。
  • nGCS0 为片选信号控制
  • 0x0000_0000 这些为存储器地址。
  • BANK 6 和 BANK 7 必须为相同的存储器大小

2.1.2 OM管脚

  OM有两个管脚,用来控制存储器。

  

  BANK0(nGCS0)的数据总线应当配置为 16 位或 32 位的宽度。因为 BANK0 是作为引导 ROM 的 bank(映射到 0x0000_0000),应当在第一个 ROM 访问前决定 BANK0 的总线宽度,其依赖于复位时 OM[1:0]的逻辑电平。

2.1.3 存储器概念

  • SDRAM(Synchronous Dynamic Random Access Memory):同步动态随机存取存储器,

    • 同步是指Memory工作需要步时钟,内部的命令的发送与数据的传输都以它为基准;
    • 动态是指存储阵列需要不断的刷新来保证数据不丢失;
    • 随机是指数据不是线性依次存储,而是由指定地址进行数据读写,简单的说,它就是cpu使用的外部内存,即我们常说的内存条。
    • 主要用于程序执行时的程序存储、执行或计算
  • SRAM是英文Static RAM的缩写,它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据,速度比SDRAM快,一般用作高速缓冲存储器(Cache)。
  • norflash:非易失闪存,是一种外部存储介质,芯片内执行(XIP,eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中,
    • 由于它有地址总线,cpu可以直接从norflash中取指,直接从FLASH中运行程序,但是工艺复杂,价格比较贵,容量较小(1~4M),NOR的传输效率很高,擦初和写操作效率很低
  • nandflash:它也是非易失闪存(掉电不丢失)的一种,但是它虽然有数据总线,但是没有地址总线,所以cpu不能直接从nandflash中取指运行,由于它价格便宜,所以常常用来存储大量数据,和我们常说的硬盘类似。

2.2 norflash 启动

  • S3C2440的启动时读取的第一条指令是在0x00上,分别为nand flash和nor flash上启动。
  • Nor flash的有自己的地址线和数据线,可以采用类似于memory的随机访问方式,在nor flash上可以直接运行程序,所以nor flash可以直接用来做 boot,采用 nor flash 启动的时候会把地址映射到 0x00 上。  
  • 任何flash器件的写入操作只能在空或已擦除的单元内进行
    • 擦除NOR器件时是以64~128KB的块进行的,执行一个写入/擦除操作的时间为5s,NORFLASHSECTOR擦除时间视品牌、大小不同而不同,比如,4MFLASH,有的SECTOR擦除时间为60ms,而有的需要最大6S 
  • Nand flash是IO设备,数据、地址、控制线都是共用的,需要软件区控制读取时序,所以不能像nor flash、内存一样随机访问,不能EIP(片上运行),因此不能直接作为boot。
  • 在u-boot 启动中,需要把 程序拷贝到 SDRAM中去运行,也可以不用拷贝。
  • nor 启动的时候,CPU的0地址就指向 norflash

  

2.2.1 norflash 电路

  运行的目标开发板为  JZ2440 开发板。norflash 型号为 MX29LV160DBTI,16M存储空间,

  

2.2.2 代码修改

  

  

  

buildroot构建项目(三)--- u-boot 2017.11 适配开发板修改 1的更多相关文章

  1. buildroot构建项目(八)--- u-boot 2017.11 适配开发板修改 5 ---- 系统启动初始化之五

    执行完 board_init_f 后,跳回到 crt0.S中继续执行汇编语言 ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp, ...

  2. buildroot构建项目(六)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之三

    一.内存控制器 在关闭了MMU和caches 之后 就进入lowlevel_init 函数,对内存控制器进行初始化.lowlevel_init.S (board\samsung\mini2440) 1 ...

  3. buildroot构建项目(五)--- u-boot 2017.11 适配开发板修改 3 ---- 系统启动初始化之二

    一.cpu_init_crit 当执行完时钟初始化后,程序执行: bl    cpu_init_crit 跳转到CPU初始化处进行,在其中主要是执行 caches 的关闭 和 MMU的关闭,之后跳转到 ...

  4. buildroot构建项目(七)--- u-boot 2017.11 适配开发板修改 4 ---- 系统启动初始化之四

    设置完寄存器控制器后,则跳出cpu_init_crit,进入_main 函数.即进入crt0.S (arch\arm\lib)  跟着代码流程慢慢走 一.crt0.S 1.1 第一步执行代码 /* 预 ...

  5. buildroot构建项目(四)--- u-boot 2017.11 适配开发板修改 2 ---- 系统启动初始化之一

    一.代码分析 上一节已经分析了链接文件,知道了首先代码是从 _start 开始,之后设置了中断向量表,然后从 start.s 开始运行. _start:vectors.S (arch\arm\lib) ...

  6. buildroot构建项目(二)--- u-boot 2017.11 建立 2440 开发板

    一.准备工作 在建立之前,先需要将下载的u-boot 拷贝一份出来解压,在此工程下进行更改和创建.同时根据前面搜索到的 mini2440开发板所在的版本,下载一份u-boot 拷贝出 mini2440 ...

  7. buildroot构建项目(一)---buildroot介绍

    1.1 什么是buildroot Buildroot是Linux平台上一个构建嵌入式Linux系统的框架.整个Buildroot是由Makefile脚本和Kconfig配置文件构成的.你可以和编译Li ...

  8. iTOP-IMX6UL 实战项目:ssh 服务器移植到 arm 开发板

    实验环境:迅为提供的Ubuntu12.04.2 以及虚拟机 编译器:arm-2009q3 编译器 开发板系统:QT系统   开发板使用手册中给Windows 系统安装了 ssh 客户端,给 Ubunt ...

  9. 迅为iTOP-4412物联网开发板入门学习高手进阶项目开发超树莓派

    免费视频教程: 为初学者精心录制的整套视频教程全部免费,随IT技术发展而不断增添的视频教程仍然免费!一支有经验的工程师团队会始终成为您的后盾. 项目实战---全开源: 手机远程控制开发板 门禁系统 W ...

随机推荐

  1. 在 Linux 虚拟机中手动安装或升级 VMware Tools

    对于 Linux 虚拟机,您可以使用命令行工具手动安装或升级 VMware Tools. 本次Linux 虚拟机为CentOS6.5 先决条件开启虚拟机.确认客户机操作系统正在运行.由于 VMware ...

  2. codeforces387B

    George and Round CodeForces - 387B George decided to prepare a Codesecrof round, so he has prepared  ...

  3. 机器学习--Logistic回归

    logistic回归 很多时候我们需要基于一些样本数据去预测某个事件是否发生,如预测某事件成功与失败,某人当选总统是否成功等. 这个时候我们希望得到的结果是 bool型的,即 true or fals ...

  4. BZOJ2863[SHOI2012]魔法树——树链剖分+线段树

    题目描述 输入 输出 样例输入 4 0 1 1 2 2 3 4 Add 1 3 1 Query 0 Query 1 Query 2 样例输出 3 3 2   树链剖分模板题,路径修改子树查询,注意节点 ...

  5. MT【16】证明无理数(2)

    证明:$sin10^0$为无理数. 分析:此处用$sin$的三倍角公式,结合多项式有有理根必须满足的系数之间的关系可以证明. 评:证明$sin9^0$为无理数就不那么简单.思路:先利用$sin54^0 ...

  6. Leetcode 283.移动零 By Python

    思路 我们可以用python的list comprehension来取出所以非0的元素,而且这样取出来会保持原有的相对顺序,再统计先后变化的长度,补上相应的0即可 代码 class Solution( ...

  7. 自学Linux Shell11.4-重定向输入输出

    点击返回 自学Linux命令行与Shell脚本之路 11.4-重定向输入输出 Linux 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示.一般情况下,标准输 ...

  8. 自学Zabbix4.2.1 Application介绍

    自学Zabbix4.2.1 Application介绍 Applications应用程序是item的一个组.例如我们要监控MySQL,我们可以将所有和MySQL相关的item放到这个应用程序中.例如M ...

  9. Java 关键字final的一小结

     * final类不能被继承,没有子类,final类中的方法默认是final的.  * final方法不能被子类的方法覆盖,但可以别继承  (方法)  * final 成员变量 表示常量,只能被赋值一 ...

  10. [hgoi#2019/2/16t2]friend

    题目描述 在一个遥远的国度里有n个人,每个人手上写着4个互不相同的数. 这个国度比较奇怪,如果两个人至少有一个数字相同,则他们是一对朋友. 现在这n个人按序号从左到右排成了一排,每个人都想知道在他左边 ...