[IMX6Q]flash_header.S分析

来源:互联网 发布:db2创建数据库 编辑:程序博客网 时间:2024/06/07 02:35

u-boot版本: v2009.08


在分析代码前,我们需要先了解两个知识点。

1. 链接脚本

路径: uboot-imx/board/freescale/mx6q_sabresd/u-boot.lds

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{. = 0x00000000;. = ALIGN(4);.text   :{  /* WARNING - the following is hand-optimized to fit within*/  /* the sector layout of our flash chips!XXX FIXME XXX*/  board/freescale/mx6q_sabresd/flash_header.o(.text.flasheader)  cpu/arm_cortexa8/start.o  board/freescale/mx6q_sabresd/libmx6q_sabresd.a(.text)  lib_arm/libarm.a(.text)  net/libnet.a(.text)  drivers/mtd/libmtd.a(.text)  drivers/mmc/libmmc.a(.text)  . = DEFINED(env_offset) ? env_offset : .;  common/env_embedded.o(.text)  *(.text)}......}

有看到flash_header.S被作为u-boot运行的第一个文件,而不是start.S,请注意这点。


2. Program Image

听标题名字有点抽象,其实就是IMX平台内部自带ROM, 然后CPU从ROM开始运行,接着ROM会读取u-boot,

它需要知道当前u-boot的信息,所以默认规定了编译出来都需要一个所谓的Program Image, 由以下几部分组成:




Program Image的布局格式如下:


格式说明如下:


从上面第一条分析可知,ROM会先去执行flash_header.S里,来看flash_header.S.

#include <config.h>#include <asm/arch/mx6.h>#ifdefCONFIG_FLASH_HEADER#ifndef CONFIG_FLASH_HEADER_OFFSET# error "Must define the offset of flash header"#endif#define CPU_2_BE_32(l) \       ((((l) & 0x000000FF) << 24) | \(((l) & 0x0000FF00) << 8)  | \(((l) & 0x00FF0000) >> 8)  | \(((l) & 0xFF000000) >> 24))/*.word可以理解成c语言中的 addr = val,后面ddr操作寄存器会用它。*/#define MXC_DCD_ITEM(i, addr, val)   \dcd_node_##i:                        \        .word CPU_2_BE_32(addr) ;     \        .word CPU_2_BE_32(val)  ;     \/*定义一个段名*/.section ".text.flasheader", "x"    /*跳转到_start,后面展开。*/b_start/*.org表示后面的代码将会被放到CONFIG_FLASH_HEADER_OFFSET,注意此命令只是链接时候起作用,不是一条伪指令。#define CONFIG_FLASH_HEADER_OFFSET 0x400也就是说code会被放到当前偏移1K的地方,uboot-imx/board/freescale/mx6q_sabresd/config.mk中有TEXT_BASE = 0x27800000所以flash_header.s的text base是0x2780000,而从System.map中也可以看到:27800400 t ivt_header确实如此。*/.orgCONFIG_FLASH_HEADER_OFFSET/*Tag: A single byte field set to 0xD1Length: a two byte field in big endian format containing the overall length of the IVT,in bytes, including the header. (the length is fixed and must have a value of32 bytes)Version: A single byte field set to 0x40 or 0x41*/ivt_header:       .word 0x402000D1 /* Tag=0xD1, Len=0x0020, Ver=0x40 *//*即上面的entry标签,第一条指令的地址,u-boot的执行就从这里开始的了,也就是start.S中的第一条指令。*/app_code_jump_v:  .word _startreserv1:          .word 0x0/*dcd的地址*/dcd_ptr:          .word dcd_hdr/*u-boot加载到哪个ram地址。*/boot_data_ptr:  .word boot_data/*保存自己的开始地址*/self_ptr:         .word ivt_header#ifdef CONFIG_SECURE_BOOTapp_code_csf:     .word __hab_data#elseapp_code_csf:     .word 0x0#endifreserv2:          .word 0x0/*加载到0x27800000*/boot_data:        .word TEXT_BASE#ifdef CONFIG_SECURE_BOOTimage_len:        .word __hab_data_end - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET#else/*整个image长度,扣除掉前1k.*/image_len:        .word _end_of_copy  - TEXT_BASE + CONFIG_FLASH_HEADER_OFFSET#endifplugin:           .word 0x0#if defined CONFIG_MX6DL_DDR3......#else  /* i.MX6Q *//*DCD不仅可以配置ddr,还可以配置其他外设,参考文档注释:Upon reset, the Chip uses the default register values for all peripherals in the system.However, these settings typically are not ideal for achieving optimal system performanceand there are even some peripherals that must be configured before they can be used.The DCD is configuration information contained in a Program Image, external to theROM, that the ROM interprets to configure various peripherals on the Chip.For example, the EIM default settings allow the core to interface to a NOR flash deviceimmediately out of reset. This allows the Chip to interface with any NOR flash device,but has the cost of slow performance. Additionally, some components such as DDRrequire some sequence of register programming as part of configuration before it is readyto be used. The DCD feature can be used to program the EIM registers and MMDCregisters to the optimal settings.*//*Tag: A single byte field set to 0xD2Length: a two byte field in big endian format containing the overall length of the DCD,in bytes, including the headerVersion: A single byte field set to 0x41*/dcd_hdr:          .word 0x40a002D2 /* Tag=0xD2, Len=83*8 + 4 + 4, Ver=0x40 *//*Tag: A single byte field set to 0xCCLength: A two byte field in big endian format containing the length of the Write DataCommand, in bytes, including the headerParameters: is a single byte divided into bitfields as flags and bytes:bytes: width of target locations in bytes. Either 1, 2 or 4flags: control flags for command behavior.Data Mask = bit 3: if set, only specific bits may be overwritten at target address(otherwise all bits may be overwritten)Data Set = bit 4: if set, bits at the target address overwritten with this flag(otherwise it is ignored)*/write_dcd_cmd:    .word 0x049c02CC /* Tag=0xCC, Len=83*8 + 4, Param=0x04 *//*Kris, 20151224, Change to 2GB configuration. {*/#if 0......#else<pre name="code" class="cpp">/*下面开始就是对ddr的配置参数了,参考ddr spec来定制。*//* DCD *//* DDR3 initialization based on the MX6Q Auto Reference Design (ARD) *//* DDR IO TYPE: */MXC_DCD_ITEM(1, IOMUXC_BASE_ADDR + 0x798, 0x000C0000)MXC_DCD_ITEM(2, IOMUXC_BASE_ADDR + 0x758, 0x00000000)/* CLOCK: */MXC_DCD_ITEM(3, IOMUXC_BASE_ADDR + 0x588, 0x00000030)MXC_DCD_ITEM(4, IOMUXC_BASE_ADDR + 0x594, 0x00000030)/* ADDRESS: */MXC_DCD_ITEM(5, IOMUXC_BASE_ADDR + 0x56c, 0x00000030)MXC_DCD_ITEM(6, IOMUXC_BASE_ADDR + 0x578, 0x00000030)MXC_DCD_ITEM(7, IOMUXC_BASE_ADDR + 0x74c, 0x00000030)/* CONTROL: */MXC_DCD_ITEM(8, IOMUXC_BASE_ADDR + 0x57c, 0x00000030)MXC_DCD_ITEM(9, IOMUXC_BASE_ADDR + 0x58c, 0x00000000)/* configured using Group Control Register: IOMUXC_SW_PAD_CTL_GRP_CTLDS */MXC_DCD_ITEM(10, IOMUXC_BASE_ADDR + 0x59c, 0x00000030)MXC_DCD_ITEM(11, IOMUXC_BASE_ADDR + 0x5a0, 0x00000030)MXC_DCD_ITEM(12, IOMUXC_BASE_ADDR + 0x78c, 0x00000030)/* DATA STROBE: */MXC_DCD_ITEM(13, IOMUXC_BASE_ADDR + 0x750, 0x00020000)MXC_DCD_ITEM(14, IOMUXC_BASE_ADDR + 0x5a8, 0x00000028)MXC_DCD_ITEM(15, IOMUXC_BASE_ADDR + 0x5b0, 0x00000028)MXC_DCD_ITEM(16, IOMUXC_BASE_ADDR + 0x524, 0x00000028)MXC_DCD_ITEM(17, IOMUXC_BASE_ADDR + 0x51c, 0x00000028)MXC_DCD_ITEM(18, IOMUXC_BASE_ADDR + 0x518, 0x00000028)MXC_DCD_ITEM(19, IOMUXC_BASE_ADDR + 0x50c, 0x00000028)MXC_DCD_ITEM(20, IOMUXC_BASE_ADDR + 0x5b8, 0x00000028)MXC_DCD_ITEM(21, IOMUXC_BASE_ADDR + 0x5c0, 0x00000028)/* DATA: */MXC_DCD_ITEM(22, IOMUXC_BASE_ADDR + 0x774, 0x00020000)MXC_DCD_ITEM(23, IOMUXC_BASE_ADDR + 0x784, 0x00000028)MXC_DCD_ITEM(24, IOMUXC_BASE_ADDR + 0x788, 0x00000028)MXC_DCD_ITEM(25, IOMUXC_BASE_ADDR + 0x794, 0x00000028)MXC_DCD_ITEM(26, IOMUXC_BASE_ADDR + 0x79c, 0x00000028)MXC_DCD_ITEM(27, IOMUXC_BASE_ADDR + 0x7a0, 0x00000028)MXC_DCD_ITEM(28, IOMUXC_BASE_ADDR + 0x7a4, 0x00000028)MXC_DCD_ITEM(29, IOMUXC_BASE_ADDR + 0x7a8, 0x00000028)MXC_DCD_ITEM(30, IOMUXC_BASE_ADDR + 0x748, 0x00000028)MXC_DCD_ITEM(31, IOMUXC_BASE_ADDR + 0x5ac, 0x00000028)MXC_DCD_ITEM(32, IOMUXC_BASE_ADDR + 0x5b4, 0x00000028)MXC_DCD_ITEM(33, IOMUXC_BASE_ADDR + 0x528, 0x00000028)MXC_DCD_ITEM(34, IOMUXC_BASE_ADDR + 0x520, 0x00000028)MXC_DCD_ITEM(35, IOMUXC_BASE_ADDR + 0x514, 0x00000028)MXC_DCD_ITEM(36, IOMUXC_BASE_ADDR + 0x510, 0x00000028)MXC_DCD_ITEM(37, IOMUXC_BASE_ADDR + 0x5bc, 0x00000028)MXC_DCD_ITEM(38, IOMUXC_BASE_ADDR + 0x5c4, 0x00000028)MXC_DCD_ITEM(39, MMDC_P0_BASE_ADDR + 0x800, 0xA1390003)MXC_DCD_ITEM(40, MMDC_P0_BASE_ADDR + 0x80c, 0x001F001F)MXC_DCD_ITEM(41, MMDC_P0_BASE_ADDR + 0x810, 0x001F001F)MXC_DCD_ITEM(42, MMDC_P1_BASE_ADDR + 0x80c, 0x001F001F)MXC_DCD_ITEM(43, MMDC_P1_BASE_ADDR + 0x810, 0x001F001F)/* Read DQS Gating calibration */MXC_DCD_ITEM(44, MMDC_P0_BASE_ADDR + 0x83c, 0x4302030B)MXC_DCD_ITEM(45, MMDC_P0_BASE_ADDR + 0x840, 0x0275026A)MXC_DCD_ITEM(46, MMDC_P1_BASE_ADDR + 0x83c, 0x4302031A)MXC_DCD_ITEM(47, MMDC_P1_BASE_ADDR + 0x840, 0x027B0249)/* Read calibration */MXC_DCD_ITEM(48, MMDC_P0_BASE_ADDR + 0x848, 0x3F343534)MXC_DCD_ITEM(49, MMDC_P1_BASE_ADDR + 0x848, 0x3A373345)/* Write calibration */MXC_DCD_ITEM(50, MMDC_P0_BASE_ADDR + 0x850, 0x31424732)MXC_DCD_ITEM(51, MMDC_P1_BASE_ADDR + 0x850, 0x48334736)/* read data bit delay: (3 is the reccommended default value, although out of reset value is 0): */MXC_DCD_ITEM(52, MMDC_P0_BASE_ADDR + 0x81c, 0x33333333)MXC_DCD_ITEM(53, MMDC_P0_BASE_ADDR + 0x820, 0x33333333)MXC_DCD_ITEM(54, MMDC_P0_BASE_ADDR + 0x824, 0x33333333)MXC_DCD_ITEM(55, MMDC_P0_BASE_ADDR + 0x828, 0x33333333)MXC_DCD_ITEM(56, MMDC_P1_BASE_ADDR + 0x81c, 0x33333333)MXC_DCD_ITEM(57, MMDC_P1_BASE_ADDR + 0x820, 0x33333333)MXC_DCD_ITEM(58, MMDC_P1_BASE_ADDR + 0x824, 0x33333333)MXC_DCD_ITEM(59, MMDC_P1_BASE_ADDR + 0x828, 0x33333333)/* Complete calibration by forced measurement: */MXC_DCD_ITEM(60, MMDC_P0_BASE_ADDR + 0x8b8, 0x00000800)MXC_DCD_ITEM(61, MMDC_P1_BASE_ADDR + 0x8b8, 0x00000800)/* MMDC init: */MXC_DCD_ITEM(62, MMDC_P0_BASE_ADDR + 0x004, 0x00020036)MXC_DCD_ITEM(63, MMDC_P0_BASE_ADDR + 0x008, 0x09444040)MXC_DCD_ITEM(64, MMDC_P0_BASE_ADDR + 0x00c, 0x8A8F7955)MXC_DCD_ITEM(65, MMDC_P0_BASE_ADDR + 0x010, 0xFF328F64)MXC_DCD_ITEM(66, MMDC_P0_BASE_ADDR + 0x014, 0x01FF00DB)MXC_DCD_ITEM(67, MMDC_P0_BASE_ADDR + 0x018, 0x00001740)MXC_DCD_ITEM(68, MMDC_P0_BASE_ADDR + 0x01c, 0x00008000)/* t during MMDC set up */MXC_DCD_ITEM(69, MMDC_P0_BASE_ADDR + 0x02c, 0x000026D2)/* t values */MXC_DCD_ITEM(70, MMDC_P0_BASE_ADDR + 0x030, 0x008F1023)MXC_DCD_ITEM(71, MMDC_P0_BASE_ADDR + 0x040, 0x00000047)MXC_DCD_ITEM(72, MMDC_P0_BASE_ADDR + 0x000, 0x841A0000)/* Mode register writes */MXC_DCD_ITEM(73, MMDC_P0_BASE_ADDR + 0x01c, 0x04088032)MXC_DCD_ITEM(74, MMDC_P0_BASE_ADDR + 0x01c, 0x00008033)MXC_DCD_ITEM(75, MMDC_P0_BASE_ADDR + 0x01c, 0x00048031)MXC_DCD_ITEM(76, MMDC_P0_BASE_ADDR + 0x01c, 0x09408030)MXC_DCD_ITEM(77, MMDC_P0_BASE_ADDR + 0x01c, 0x04008040)MXC_DCD_ITEM(78, MMDC_P0_BASE_ADDR + 0x020, 0x00005800)MXC_DCD_ITEM(79, MMDC_P0_BASE_ADDR + 0x818, 0x00011117)MXC_DCD_ITEM(80, MMDC_P1_BASE_ADDR + 0x818, 0x00011117)MXC_DCD_ITEM(81, MMDC_P0_BASE_ADDR + 0x004, 0x00025576)MXC_DCD_ITEM(82, MMDC_P0_BASE_ADDR + 0x404, 0x00011006)MXC_DCD_ITEM(83, MMDC_P0_BASE_ADDR + 0x01c, 0x00000000)#endif/*Kris, 20151224, Change to 2GB configuration. }*/#endif#endif

 所以系统加载的流程是这样的:

系统上电运行内部ROM, ROM读取u-boot前面的一段数据到内部ram, 即读取flash_header.S中的配置,并初始化ddr,然后将整个u-boot copy到ddr, 最终执行权交给u-boot,即start.S的_start从而执行u-boot的初始化...

因为无rom的code,所以这只是推断,不一定准确。


不过我有试着修改过TEXT_BASE,发现改掉后系统还能正常运行,所以我猜是rom读取了boot_data_ptr,

而里面正是保存着u-boot.bin要运行的地址。

1 0
原创粉丝点击