blob学习备忘

 

为阅读BLOB首先阅读了杜云海的ARM学习报告,对在ADS调试时生成的AXFBIN文件以及GNU编译生成的ELF文件和可执行文件有了一些了解。

对于ARM学习报告1关键要理解加载域和运行时域的概念,加载域即下载到FLASH中的BIN文件的地址分配,运行时域就是在程序运行时把BIN文件的各个段拷贝到RAM中的地址分配情况。对于学习报告中给的启动代码,在ARM启动时,flash地址为0 -2M RAM地址为 2M -18M ,启动时从FLASH中运行BOOT程序,在运行BOOT程序的过程中先将BOOT程序本身拷贝到 2M 后的地址空间(以地址0x200000开始的地址空间),然后将RAM的地址映射为0 -16M 的,将FLASH地址映射为 16M -18M 。即可实现代码的连接。

对于ARM学习报告3关键要理解SECTION的概念,ELF+.ld文件通过LD工具重定位连接就会生成可执行文件,要能读懂LD文件,其中的地址是指的可执行文件在内存中运行时相应的段所处的位置。即运行时域的地址分配情况。

 

BLOB的阅读:

/* First, mask **ALL** interrupts */

/* switch CPU to correct speed */

/* init LED */

/* setup memory */

对于SA1100来说是对地址为0xa000 0000开始的几个寄存器进行配置MDCNFGMDCAS0MDCAS1MDCAS2MCS0

 

 

/* check the first 1MB of BLOB_START in increments of 4k */

/* relocate the second stage loader */

relocate:

       adr   r0, _start

       add  r2, r0, #(64 * 1024)       /* blob maximum size is 64kB */

       add  r0, r0, #0x400        /* skip first 1024 bytes */

       ldr   r1, BLOB_START

       /* r0 = source address

        * r1 = target address

        * r2 = source end address

        */

source addressFLASH0x00000000位置,target addressBLOB_START

BLOB_START:   .word      BLOB_ABS_BASE_ADDR可以看出BLOB_ABS_BASE_ADDRBLOB_START是相等的。

BLOB_ABS_BASE_ADDRblob- 2.0.5 -pre2/include/blob/arch下定义,和具体的芯片有关。

/src/blob/rest-ld-script.in文件为

 

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_trampoline)

SECTIONS

{

         . = BLOB_ABS_BASE_ADDR;

 

         . = ALIGN(4);

         .text : {

                   __text_start = .;

                   *(.text)

                   __text_end = .;

         }

……

}

BLOB_ABS_BASE_ADDRSECTIONS段在内存中映射的地址,可以看到以_trampoline开始的STAGE2 的代码在内存中的映射确实是从BLOB_ABS_BASE_ADDR开始的,它和relocate的代码是一致的

 

 

变量BLOB_START就是blob复制到内存中的起始地址。开始看这段代码,其中令人不解的地方就是常数0x400,为什么_start地址加上0x400就是第二阶段blob-reset的代码呢?这里稍做重复:dd if=blob-rest of=$@ bs=1k seek=1./src/blob/Makefile.am)这一行命令中seek=1 表示从第1 个数据块后开始写输出数据。这一行的作用实际是将blob-rest 文件写入到blob 文件的第1024 字节开始处,也就是0x400的地方。

/* blob is copied to ram, so jump to it */

下一步跳到BLOB_ABS_BASE_ADDR处,从ENTRY(_trampoline)看出BLOB_ABS_BASE_ADDR处是以_trampoline为入口的,trampoline.c对堆栈进行了清空,然后跳到main函数去执行。

 

 

Main()函数解读

init_subsystems()

首先执行函数init_subsystems(),按照优先级从小到大调用各个初始化函数。call_funcs是调用初始化函数的函数。具体的初始化函数如下表所列:

src/lib/command.c:78:__initlist(init_commands, INIT_LEVEL_OTHER_STUFF);
src/blob/flash.c:165:__initlist(init_flash, INIT_LEVEL_OTHER_STUFF + 1);
src/blob/initcalls.c:49:__initlist(serial_default_init, INIT_LEVEL_INITIAL_HARDWARE);
src/blob/initcalls.c:50:__initlist(enable_icache, INIT_LEVEL_INITIAL_HARDWARE);
src/blob/initcalls.c:51:__initlist(led_init, INIT_LEVEL_INITIAL_HARDWARE);
src/blob/initcalls.c:52:__initlist(TimerInit, INIT_LEVEL_OTHER_HARDWARE);
src/blob/assabet.c:58:__initlist(init_assabet_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/assabet.c:78:__initlist(assabet_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/brutus.c:55:__initlist(init_brutus_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/brutus.c:66:__initlist(brutus_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/badge4.c:65:__initlist(init_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/badge4.c:82:__initlist(init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/clart.c:58:__initlist(init_clart_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/clart.c:69:__initlist(clart_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/h3600.c:118:__initlist(init_h3600_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/h3600.c:133:__initlist(h3600_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/idr.c:52:__initlist(init_idr_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/idr.c:61:__initlist(idr_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/jornada720.c:78:__initlist(init_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/jornada720.c:103:__initlist(init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/lart.c:67:__initlist(init_lart_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/lart.c:78:__initlist(lart_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/nesa.c:62:__initlist(init_nesa_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/nesa.c:73:__initlist(nesa_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/pleb.c:48:__initlist(lock_pleb_led, INIT_LEVEL_INITIAL_HARDWARE + 1);
src/blob/pleb.c:72:__initlist(init_pleb_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/pleb.c:83:__initlist(pleb_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/shannon.c:61:__initlist(init_shannon_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/shannon.c:72:__initlist(shannon_init_hardware, INIT_LEVEL_DRIVER_selectION);
src/blob/system3.c:99:__initlist(init_system3_flash_driver, INIT_LEVEL_DRIVER_selectION);
src/blob/system3.c:110:__initlist(system3_init_hardware, INIT_LEVEL_DRIVER_selectION);

参数(initlist_t *)&__initlist_start和参数(initlist_t *)&__initlist_end,分别为内存中initlist段的开始地址和结束地址。rest-ld-script.in中有如下定义:

. = ALIGN(4);
.initlist : {
//
在文件include/blob/init.h中第43行有
:
//#define __init __attribute__((unused, __section__(".initlist")))
__initlist_start = .;
*(.initlist)
__initlist_end = .;

在这个段中存放着若干个下面这种结构体:

typedef void(*initfunc_t)(void);
typedef struct {
u32 magic;
initfunc_t callback;
int level;
} initlist_t;

 

call_funcs()函数的作用就是在这若干个结构体中找出需要执行的函数运行。

上面列表中的函数都是call_funcs()可能执行的,但具体会做哪几个,由编译时的配置决定。
一般执行最前面的(公共的)6个和后面两个和体系结构相关的:***_flash_driver
***_init_hardware
。移植BLOB时只需要将要执行的那些初始化函数编译进initlist段即可。

下面分析前面六个初始化函数:

commands(void)函数负责初始化全局变量commandlist_t *commands,将内存commandlist段中的所有commandlist_t结构体组成一个以*commands为头的链表。

init_flash

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值