Chinaunix首页 | 论坛 | 博客
  • 博客访问: 284818
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 600
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-27 08:37
个人简介

从linux了解世界

文章分类
文章存档

2017年(5)

2016年(51)

2015年(2)

我的朋友

分类: 嵌入式

2015-11-30 11:11:33

bootloader中最难懂的就是代码的重定向,各种教程都是用的arm-linux工具链或者老套的ads来讲解,我通过对重定向在mdk上的实现,搞懂了很多之前的困惑。
想明白重定向,首先要明白程序有两种状态:存储静止状态、加载运行状态(就是执行不执行的区别)。
mdk的scatter文件(分散加载文件)可以设置两种程序地址:加载地址和运行地址arm-linux工具链的链接地址)。其 中加载地址就是程序在存储静止状态的地址,这个地址指示mdk自身的download功能把程序烧到什么位置。运行地址说明了把程序加载之后放在哪里运 行。而且arm映像文件(就是编译好的程序)的入口点所在的域必须是固定域(加载地址等于运行地址),程序刚开始不可能瞬间完成代码从加载地址复制到运行 地址所以只能是固定域,这一点要想明白。
程序运行时也有两个地址:相对地址,绝对地址。相对地址就是相对于当前正在——取址的程序的地址——的地址,绝对地址就是在运行地址范围内的真实地址。
这两个地址主要和程序跳转有关,和相对地址有关的BL、adr,和绝对地址有关的ldr。
想要实现代码的重定向一定要理解映像文件的组成(域、段)、各种地址之间的关系。我实现的代码的重定向就是从上电的在flash中运行重定位到sdram中,通过led灯的变化目测程序运行最少快了五倍
                 PRESERVE8
                AREA RESET,CODE,READONLY
                ARM
                IMPORT main
START
SDRAM_BASE        EQU        0x30000000
                B         Reset_Addr
Reset_Addr 
                 ADR        R0, START                ;复制代码到sdram
                LDR     R1, =SDRAM_BASE
                CMP        R0, R1
                BEQ        STACKSET
                MOV     R2, #0x1000               
LOOP   
                LDMIA    R0!,{R3-R6}
                STMIA    R1!,{R3-R6}
                SUBS    R2,    #1    
                BNE     LOOP  
STACKSET                                   
                MSR     CPSR_C, #0xd3 
                LDR        SP,    =0x34000000         ;set supervisor_sp

                LDR        LR,    =HALT
                LDR        PC,    =main
HALT
                B        HALT
                END   
重定位部分的汇编代码如上,异常向量表的第一条reset(reset也是一种异常)  指令只能用相对跳转,绝对跳转就去运行地址的头地址了,在这个时候别说头地址里什么都没有,连头地址指向的sdram都没有初始化无法访问。完成代码重定向之前只能用相对跳转。
ADR        R0, START;
LDR     R1, =SDRAM_BASE;
CMP        R0, R1
可以判断程序运行在flash还是sdram。这段代码在 LDR        PC,    =main之前都在flash中运行,之后就在sdram中运行了 。

为了便于在mdk中进行硬件调试,将加载地址和运行地址都设 为adram的头地址0x30000000,以这段代码作为启动代码的一部分的程序肯定不能用mdk的自带下载功能,选择用jlink下载程序到0地址。 当然也可以选择加载地址和运行地址都设为0是用mdk下载程序,跳转到sdram用ldr pc 0x30000000,但是这之后就没有办法用标号完成大于32m的跳转了(如果这句话不明白为什么就说明关于地址这个问题还有很多盲点)。第三种方法是 单独写一个程序完成重定向其加载和运行地址为0,被重定位的程序加载地址紧接着上一个地址,运行地址为sdram(scatter文件需要两个域)。三种 方法13都可以,但3在编程时要考量的细节多容易出错,最不好的是不能进行硬件调试,所以第一种方法比较好(第一种方法程序在没跳转前其实相当于骗程序在 flash中运行)。  
有了以上积累就可以在mdk中自己编写bootloader了          
flash中0x60000开始存放linux uimage镜像文件,抛去前64字节的头信息,内核实际加载地址为0x60040.把flash中0x60000开始的0x500000大小的数据 (uimage镜像为2.2M,读5m是为了取个整数)读到sdram0x30008000开始的空间,从0x30008040开始执行。
大体上的思路很好理解,难点为驱动flash,设置内核加载信息供内核读取。加载信息按照内核要求的数据结构存放在连续空间,引导内核时把首地址传递给内核,内核就自动按照双方约定好的数据结构去找信息。
收获:彻底吃透arm最小系统架构。驱动flash过程中,按照K9F2G08U0C-SCB0数据手册和s3c2440数据手册进行配置,培养了自主开发的能力

moved.rar(scatter文件和ini文件是配合硬件调试的)
阅读(1865) | 评论(0) | 转发(0) |
1

上一篇:没有了

下一篇:配置linux3.18.24支持yaffs、busybox1.22.1到mini2440

给主人留下些什么吧!~~