i.MX6系列SD卡烧写原理分析及源码讲解

最近用i.MX6ULL的时候,发现LCD刷新率跟不上(不知道是自己能力不行还是RGB本身就是慢),研究了NXP官方的一些资料后,发现6D系列支持MIPI的屏幕,而且是两路,主频也比6U快,双核结构,支持OpenGL3.1,简直是爽的不要不要的!可惜,火哥家没有,某宝中找到了飞凌嵌入式的OKMX6DL-C这个型号的板子,但用6ULL的烧写器烧写裸机程序无法启动,我想可能是启动地址问题导致的,这个后期可以找原理图确认一下。飞凌比火哥还懒,下载器只有官方提供的那个好几百M的,每次烧写必须把u-boot到根文件系统都搞一遍,反正我研究了好久也没搞明白他这个怎么烧裸机程序。于是想用正点原子的下载器改一版,但竟然找不到他源码放哪了!明明记得当初教程中他们说有源码的,而且我印象中还看过,用的时候找不到了!

还是自己写吧!顺便把自己写下载器的心得整理出来分享给大家。

这个烧录器我再6U和6D、6Q上都测试过,都能使用,其他型号和系列的芯片没做试验,有条件的自己做吧,我看NXP官方文档的启动过程都差不多。

  • i.MXSD卡启动分析

在烧录U-Boot的时候,U-Boot交叉编译生成了u-boot.bin文件,但是这文件直接烧录到SD卡或者eMMC中是启动不了的,需要添加一个启动头信息,头信息中包含IVT、BootData、DCD三部分数据,然后下面才是我们用户编译的bin文件信息。

我参考的是NXP官方提供的IMX6 processor ref manual.pdf这个文件(像老太太的裹脚布一样——又臭又长,而且还是纯英文的,像我这种小本毕业的,读起来真费劲!)。

文件Chapter8:System Boot -> Program image 8.6一节中说明了镜像文件应该包含的内容:

 

英文能力好的大神们直接阅读原文吧,这里简单介绍一下各项。

IVT(Image vector table)

这是个镜像启动的向量表,可以参照STM32和8051的中断向量表理解(但这个不是中断向量表),这个向量表一共包含8项内容,每项内容占用4个字节的空间:

 

header:IVT的头信息,包含1字节的Tag、2字节的Length、1字节的Version,及其中Tag固定为0XD1,Version为0x40或者0x41,Length表示IVT的大小,采用大端模式存放数据,长度是固定为32字节(两个字节,大端模式表示为0x0020)。

enter:镜像执行第一条指令的绝对地址,就是代码和数据区的起始地址,实际设置为0x87800000。

dcd:镜像DCD段的绝对地址,如果不需要DCD,这一段设置为NULL。

boot data:Boot Data段的绝对地址,

self:本身的绝对起始地址,也就是IVT段的起始地址。

csf:HAB库使用的命令序列文件(CSF)的绝对地址,不执行安全引导时,此字段必须设置为NULL。

另外还有两个预留的空位。

 

Boot Data

启动数据段,包含了镜像要拷贝到那个地址,拷贝大小是多少等信息。

 

镜像文件的其实质:start = entry - 0x1000

镜像文件的大小:length,这个值可以随便给,只要比实际的镜像头文件大就可以了,但最大不能超过0x200000,也就是2Mbyte。

 

DCD(Device configuration data)

设备配置表,用来初始化系统时钟,DDR等设备信息,总体不能超过1786字节,其中重要的两项内容是header和cmd。

head是DCD头信息,包含1字节的Tag(0xD2)、2字节的Length(大端模式)和1字节的Version(0x41)。

cmd为命令区域支持多种命令,每个CMD也有头部信息。

官方文档中举了Write data 这个命令,在文档中Chapter8:System Boot -> Program image 8.6.2.1章节。

DCD CMD命令格式如下表所示:

 

Tag:1字节,固定为0XCC。

Length:2字节,包含header在内的写入命令的总体长度,采用大端模式存储。

Parameter:1字节,bytes表示目标位置宽度,可选1、2、4字节,flags是命令控制标志位。

 

DCD就是所有这些命令的一个集合。

  • .imx文件头分析

因为关于头文件的资料极少,我参考了正点原子关于i.MX6ULL的文档、NXP官方文档和网上大牛写的一些东西,并且找到了i.XM6DL所生成的U-Boot烧录.imx文件进行综合分析,给大家填填坑。

 

以上内容是i.MX6DL生成的U-Boot.imx文件的十六进制格式片段。

我还分析了正点原子的i.MX6ULL的.imx文件,启动地址略有不同(这就是为啥一开始我用正点原子提供的下载器下载不启动的原因吧),我们以i.MX6DL这个为例详细解说一下,也当自己回顾了。

前面32个字节是IVT部分大端模式存储,分别是:

数据

解释

header

D1 00 20 40

tag:0xD1,length:0x2000,version:0x40

enter

00 00 80 17

也就是起始地址为0x17800000

保留

00 00 00 00

 

dcd

2C F4 7F 17

实际DCD起始地址为:0x177FF42C,我们镜像地址是0x17800000,IVT + Boot Data + DCD整个大小是3Kbyte,所以load.imx的起始地址就是0x17800000 - 0xC00=0x177FF400。因此,DCD起始地址相对于load.imx起始地址偏移就是0x177FF42C - 177FF400 = 0x2C,就是说从,0x2C这个地址开始就是DCD的所有数据(图中第三行D2 02 F0 40的位置)。

boot data

20 F4 7F 17

Boot Data实际起始地址:0x177FF420,镜像起始地址是0x17800000,IVT + Boot Data + DCD整个大小是3Kbyte,所以load.imx的起始地址就是0x17800000 - 0xC00=0x177FF400。Boot Data段是紧随在IVT之后的,所以0x177FF400 + 32字节就是Boot Data实际起始地址。0x177FF400 + 0x20 = 0x177FF420。

sefl

00 F4 7F 17  

IVT复制到DDR以后的首地址。

csf

00 00 00 00

CSF地址,没用到

保留

00 00 00 00

00 00 00 00

下面紧随的12字节是BootData段:

数据

解释

start

00 F0 7F 17

整个.imx文件的起始地址,包含前面的1Kbyte的偏移地址,entry - 0x1000=0x17800000 - 0x1000 = 0x177FF000

length

00 90 07 00 

镜像的大小,按理说不能超过2Mbyte就可以,这里设置的是0x79000,也就是484K,这个值后面我想能定设置为0x00200000。

plugin

00 00 00 00

插件,没用

下面分析DCD段的内容:

前面一段中已经说过,DCD段也是以header开头的,然后紧随其后的是Address表示要初始化寄存器的地址,Value/Mask是相应的寄存器初始化值,这些采用的都是大端模式。

数据

解释

header

D2 02 F0 40

tag:0xD2,version:0x40,length:0x02F0(752字节),这里的长度用的是小段模式的

Write Data Commadn

CC 02 EC 04

tag:0xCC,parameter:0x04,第二三个字节大端模式表示这条指令的长度0x02EC(784字节),这里的长度用的也是小段模式的

Address

02 0E 07 74

0x74070E02,寄存器地址(具体是啥没查,大概也就是CCGR一类的寄存器)

Value

00 0C 00 00

写入寄存器的内容

Address

02 0E 07 54

0x54070E02

Value

00 00 00 00

写入寄存器的内容

……

 

 

基本上后面跟的都是这些指令,DCD段长度是0xF002(61442字节),但实际上后面大部分内容都是空的,一直到0xC00开始,才是真正的U-Boot的.bin文件内容。

  • 编写imxdownload命令

我们编写的imxdownload命令共需要完成两个任务:

1. 添加头文件信息,生成.imx文件

2. 将文件烧入到SD卡中

i.MX支持多种设备启动,以下是各种启动方式IVT的偏移。

 

表中SD卡、eMMC等设备的偏移地址是1Kbyte,初始化加载区域的的总大小是4Kbyte,根绝这段话可以得出,IVT+Boot的总大小实际为3Kbyte(4Kbyte-3Kbyte),加入SD卡每个扇区为512字节,那么最后我们烧入系统的启动文件应该从第三个扇区开始烧,一共要烧写6个分区,从第九个分区(也就是烧录文件的第3Kbyte)开始才是真正要烧入的.bin文件。

 

烧录命令在Linux下直接使用dd命令烧写

sudo dd iflag=dsync oflag=dsync if=load.imx of=/dev/sdb bs=512 seek=2

关于dd命令

Linux dd 命令用于读取、转换并输出数据,dd 可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。

参数说明:

  1. if=文件名:输入文件名,默认为标准输入。即指定源文件
  2. of=文件名:输出文件名,默认为标准输出。即指定目的文件
  3. ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节
  4. obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节
  5. bs=bytes:同时设置读入/输出的块大小为bytes个字节
  6. cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小
  7. skip=blocks:从输入文件开头跳过blocks个块后再开始复制
  8. seek=blocks:从输出文件开头跳过blocks个块后再开始复制
  9. count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数
  10. conv=<关键字>
    1. conversion:用指定的参数转换文件
    2. ascii:转换ebcdic为ascii
    3. ebcdic:转换ascii为ebcdic
    4. ibm:转换ascii为alternate ebcdic
    5. block:把每一行转换为长度为cbs,不足部分用空格填充
    6. unblock:使每一行的长度都为cbs,不足部分用空格填充
    7. lcase:把大写字符转换为小写字符
    8. ucase:把小写字符转换为大写字符
    9. swap:交换输入的每对字节
    10. noerror:出错时不停止
    11. notrunc:不截短输出文件
    12. sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐
  1. iflag/oflag=<关键字>
    1. append:追加模式(仅对输出有意义,隐含了conv=notrunc)
    2. direct:使用直接I/O 存取模式
    3. directory:除非是目录,否则 directory 失败
    4. dsync:使用同步I/O 存取模式
    5. sync:使用同步I/O 存取模式,但同时也对元数据生效
    6. fullblock:为输入积累完整块(仅iflag)
    7. nonblock:使用无阻塞I/O 存取模式
    8. noatime:不更新存取时间
    9. nocache:丢弃缓存数据
    10. noctty:不根据文件指派控制终端
    11. nofollow:不跟随链接文件
  1. –help:显示帮助信息
  2. –version:显示版本信息

 

  • 代码

婚前理论都清楚了,拖鞋上炕吧,开始撸码。

这个下载器我打算分两部分写,一部分是读取官方标准.imx文件头信息的,把这部分头信息转换为.h文件,另外一部分是下载器。这样方便在各个不同类型芯片中移植。

imxdownload.c

/****************************************************************
 * i.MX系列芯片裸机程序烧录器
 * Copyright (C) 2021 Mars.CN suolong123@126.com
 * 
 * 改程序用于i.MX6系列芯片的程序烧录,
 * 只在i.MX6ULL和6DL、6Q的芯片中测试过,i.MX其他型号芯片未经测试,
 * 但按照NXP官方文档的描述,只需要修改本IVT、BootData和DCD部分一样可用。
 * 
 * 源代码分为两部分,.c文件包含了原始imx文件头读取和SD卡烧录两个功能,
 * 但其中需要用到一个.h文件,这个文件中记录了IMX头信息及相关地址,
 * .h文件可以通过调用imxdownload -r u-boot.imx imx6dl.h这样的命令生成
 * 经过测试,6U、6D、6Q等芯片的启动地址不一样,并且不同内存大小的DCD部分
 * 也有所不同,所以头文件不能通用,最好的办法就是找到官方提供对应原始imx文件,
 * 通过上面的命令将头信息反出来。
 * 
 * 无论是U-Boot,还是自己写的裸机程序,生成原始bin文件后,都可以通过:
 * imxdownload u-boot.bin /dev/sdb
 * 的命令进行SD卡烧写。
 * 
 * 烧录SD代码分为两部分:
 * 第一部分是根据头文件生成imx_load.imx文件,这个文件是加入IMX头信息的,
 * 包含32字节的IVT、3字节的Boot Data,以及不固定长度的DCD部分。
 * 第二部分是将imx_load.imx文件烧录到SD卡中,用的是Linux的dd命令
 * sudo dd iflag=dsync oflag=dsync if=%s of=%s bs=512 seek=2
 * 根据NXP官方文档中描述,烧写SD卡要偏移1Kbyte,bs=512 seek=2用于偏移
 * 
 * 注意:野火和正点原子的板子用的是TF卡(小卡)启动,
 * 飞凌的板子虽然也有个差TF卡的位置,但他用的是SD卡(大卡)启动,
 * 所以位置搞错了肯定起不来,在此耗费2天时间,大意了……
 * 
 * PS:英文提示纯属机翻,如有异议请憋回去!
 * 
 * 该下载器参考资料:
 * NXP官方,i.MX6DL文档 《IMX6 processor ref manual.pdf》
 * 正点原子《I.MX6U嵌入式Linux驱动开发指南V1.5.pdf》
 * njcy写的《i.MX6ULL下载工具imxdownload分析》
 * https://blog.csdn.net/weixin_39869569/article/details/113390184
 * 
 * 
 * @file    imxdownload.c
 * @brief   i.MX烧录程序
 * @author  Mars.CN
 * @email   suolong123@126.com
 * @version 1.0.0.1
 * @license GNU General Public License (GPL)
 * 
 *---------------------------------------------------------------
 * Change History :
 * <Date>     | <Version>     | <Author>    | <Description>
 *---------------------------------------------------------------
 * 2021/02/25 | 1.0.0.1       | Mars.CN     | Create file
 *---------------------------------------------------------------
 *
 ****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "imx6dl.h"     // 要生成对应芯片的头文件信息

#define LOG_D(...)      \
do \
{ \
    printf(__VA_ARGS__); \
    printf("\r\n"); \
} while(0);

#define IVT_SIZE 32
#define BTD_SIZE 12
#define IMX_FILE "imx_load.imx"

void help();
void make_header(char *imx, char *h);
void bind_imx(char *b);
void write_sd(char *device);

int main( int argc, char *argv[] )
{
    if(argc > 2){
        if(0 == strcmp(argv[1], "-r")){
            // 读取imx头信息,并生成.h文件
            if(4 == argc){
                make_header(argv[2], argv[3]);
                goto __exit;
            }
        }else{
            // 判断设备是否存在
            if(0 == access(argv[2], F_OK)){
                bind_imx(argv[1]);
                write_sd(argv[2]);
            }else{
                LOG_D("Can't open sd device : %s!\n", argv[2]);
            }
            goto __exit;
        }
    }
    help();
__exit:
    return 0;
}

/**
 * @brief   根据.imx文件生成头文件
 * @param   [in] *imx   原始的.imx文件
 * @param   [in] *h     要生成的C语言头文件存放地址
 * 
 * @remarks
 * 该函数用于辅助工具生成C语言用到的.h头文件,
 * 文件中包含了生成.imx文件所用到的IVT、Boot Data和DCD段信息
 * 该函数是为了方便开发人员制作针对性的下载器,
 * 所以生成的头文件不能单独使用,需要修改imxdownload.c中引用,
 * 并重新编译imxdownload.c文件才可使用。
 */ 
void make_header(char *imx, char *h)
{
// 判断.imx文件是否存在
    int i=0;
    FILE *s_fp = NULL;
    FILE *d_fp = NULL;
    unsigned char *r_ivt = NULL;    // 存放读出的IVT数据
    unsigned char *r_btd = NULL;    // 存放读出的BootData数据
    unsigned char *r_dcd = NULL;    // 存放读出的DCD数据
    unsigned int r_dcd_length = 0;
    unsigned int tab_size = 0;      // 头文件需要写入大小(sizeof(int))
    s_fp = fopen(imx, "rb");
    if(NULL != s_fp){
        LOG_D("Start constructing header file...\n");
        // LOG_D("File size : %ld\n", ftell(fp));
        r_ivt = calloc(IVT_SIZE,1);   // IVT大小32字节
        r_btd = calloc(BTD_SIZE,1);   // BootData大小12字节

        LOG_D("Read IMX header file information...\n");
        // printf("大小: %ld , %ld , %d\n", sizeof(r_ivt), sizeof(char), IVT_SIZE);
        // 读出IVT信息
        fgets(r_ivt, IVT_SIZE+1, (FILE*)s_fp);
        // 读出BootData信息
        fgets(r_btd, BTD_SIZE+1, (FILE*)s_fp);

        // 读取DCD数据,先从后面第2,3字节中获得长度,然后创建固定位大小的DCD区域
        // 向后移动一个指针,并读取
        fseek(s_fp,1,SEEK_CUR);
        r_dcd_length = fgetc(s_fp);
        r_dcd_length <<= 8;
        r_dcd_length |= fgetc(s_fp);
        r_dcd = calloc(r_dcd_length, 1);
        fseek(s_fp, -3, SEEK_CUR);
        fgets(r_dcd, r_dcd_length+1, (FILE*)s_fp);
        tab_size = (IVT_SIZE + BTD_SIZE + r_dcd_length)/4;
        // 开始制作头文件
        d_fp = fopen(h, "w");
        // 写入头信息
        fputs("#ifndef __IMX_HEADER_\n", d_fp);
        fputs("#define __IMX_HEADER_\n\n", d_fp);
        
        fputs("#define ADDR_ENTRY\t\t", d_fp);
        fprintf(d_fp, "(0x%02X%02X%02X%02X)\n", r_ivt[7], r_ivt[6], r_ivt[5], r_ivt[4]);
        fputs("#define ADDR_SELF\t\t(ADDR_ENTRY - 3*1024)\n", d_fp);
        fputs("#define ADDR_START\t\t(ADDR_ENTRY - 4*1024)\n", d_fp);
        fputs("#define ADDR_DCD\t\t(ADDR_SELF + 0x2C)\n", d_fp);
        fputs("#define ADDR_BOOT\t\t(ADDR_SELF + 0x20)\n", d_fp);
        fputs("#define IMAGE_SIZE\t\t(0x00200000)\n", d_fp);             // 这个值随便写,比镜像文件大就行,但最大不能超过2Mbyte
        fprintf(d_fp, "#define TAB_SIZE\t\t%d\n\n", tab_size);
        fputs("const int _h_imx6_ivt_dcd_tbl[TAB_SIZE] =\n{\n", d_fp);
        fputs("\t0X402000D1,ADDR_ENTRY,0X00000000,ADDR_DCD,  ADDR_BOOT, ADDR_SELF, 0X00000000,0X00000000,\n", d_fp);
        fputs("\tADDR_START,IMAGE_SIZE,0X00000000,\n\t", d_fp);
        for(i=0; i<r_dcd_length; i+=4){
            fprintf(d_fp, "0x%02X%02X%02X%02X,", r_dcd[i+3], r_dcd[i+2], r_dcd[i+1], r_dcd[i]);
            if(28 == i%32){fputs("\n\t", d_fp);}
        }
        fputs("\n};\n", d_fp);
        
        fputs("\n#endif /* __IMX_HEADER_ */\n", d_fp);
        fclose(d_fp);

        LOG_D("Entry address : 0x%02X%02X%02X%02X\n", r_ivt[7], r_ivt[6], r_ivt[5], r_ivt[4]);
        LOG_D("Header file generation complete!\n\nfile path : %s \n", h);
        // 清理残渣
        free(r_ivt);
        free(r_btd);
        free(r_dcd);
    }else{
        LOG_D("IMX source file does not exist!");
    }
    fclose(s_fp);
}

/**
 * @brief   构造用于烧写的.imx文件
 * @param   [in] *b     原始的.bin格式文件
 * 
 * @remarks 
 * 该函数会生成一个供i.MX平台烧写的.imx文件(名称无所谓,强迫症可以修改IMX_FILE),
 * 文件中前3Kbyte的内容是IVT + Boot Data + DCD内容,
 * 从0xC00开始为正式的bin文件内容,
 * 生成后的.imx文件可以直接烧到SD卡或eMMC中,SD卡烧写需要偏移1Kbyte
 */
void bind_imx(char *b){
    
    FILE *s_fp;
    FILE *d_fp;
    int s_fle_length = 0;    // bin文件长度
    unsigned int offset = 1024*3;   // bin 文件写入偏移
    unsigned char *buf;
    s_fp = fopen(b, "rb");
    if(NULL != s_fp){
        LOG_D("Read bin file content...\n");
        fseek(s_fp, 0, SEEK_END);
        // 获取文件长度
        s_fle_length = ftell(s_fp);
        LOG_D("Bin file size: %d Bytes\n", s_fle_length);
        // 构建输出
        buf = calloc(s_fle_length + offset,1);
        memset(buf, 0, s_fle_length + offset);
        fseek(s_fp, 0, SEEK_SET);
        fread(&buf[offset], 1, s_fle_length, s_fp);
        // 合并数组
        memcpy(buf, _h_imx6_ivt_dcd_tbl, sizeof(_h_imx6_ivt_dcd_tbl));
        LOG_D("Create new IMX file...\n");
        d_fp = fopen(IMX_FILE, "wb");
        if(NULL != d_fp){
            fwrite(buf, 1, s_fle_length + offset, d_fp);
            fclose(d_fp);
            LOG_D("IMX file generation completed!\n");
            LOG_D("IMX file path : %s!\n", IMX_FILE);
        }else{
            LOG_D("Failed to create file!\n");
        }

        // 清理残渣
        free(buf);
    }else{
        LOG_D("Bin file does not exist!\n");
    }
}

/**
 * @brief   将imx文件烧写到SD卡中
 * @param   [in] device SD卡的设备文件,一般为/dev/sd*
 * 
 * @remarks 
 * 该函数用于将生成好的.imx文件烧录到SD卡中,使用Linux的dd命令
 * dd命令参数如下:
 *      iflag   使用同步I/O模式进行内容读取
 *      oflag   使用同步I/O模式进行内容输出
 *      if      要读取的内容,这里指.imx文件
 *      of      要输出的设备或文件,这里指SD卡
 *      bs      输出的块大小,单位是byte
 *      seek    偏移块,i.MX6烧写SD卡官方资料提示需要偏移1Kbyte,所以设置为2
 */
void write_sd(char *device)
{
    // 调用dd命令写入SD卡
    char * dd;
    sprintf(dd, "sudo dd iflag=dsync oflag=dsync if=%s of=%s bs=512 seek=2", IMX_FILE, device);
    LOG_D("Download %s to %s ...\n", IMX_FILE, device);
    system(dd);
    LOG_D("\nSD card writing completed!\n");
}

/**
 * @brief   帮助信息输出
 */
void help()
{
    LOG_D("\nimxdownload [-h] [-r] <source_bin> <target>\n");
    LOG_D("\tThis command is used to write the bin file obtained by cross compilation ");
    LOG_D("\tto SD card to support the startup of i.mx6 series chips. Before writing, ");
    LOG_D("\tthe IVT, boot data and DCD information of IMX will be inserted in front of the bin file. ");
    LOG_D("\tThe above information comes from the official IMX header information. ");
    LOG_D("\tThe official IMX file header information can be read through the -r parameter.\n");
    LOG_D("\t-h           View command help information\n");
    LOG_D("\t-r           Read the header information of the official IMX file and generate the header file .\n");
    LOG_D("\t             If the parameter does not exist, <source_ Bin> indicates the IMX file to read the header information .\n");
    LOG_D("\t             If the parameter exists, <source_ Bin> indicates the bin file to be written to the SD card .\n");
    LOG_D("\tsource_bin   To write to the bin file of the SD card, or to read the IMX file of the header information .\n");
    LOG_D("\ttarget       SD card device file to write or C language header file to save IMX header information .\n");
}

imx6dl.h

#ifndef __IMX_HEADER_
#define __IMX_HEADER_

#define ADDR_ENTRY		(0x17800000)
#define ADDR_SELF		(ADDR_ENTRY - 3*1024)
#define ADDR_START		(ADDR_ENTRY - 4*1024)
#define ADDR_DCD		(ADDR_SELF + 0x2C)
#define ADDR_BOOT		(ADDR_SELF + 0x20)
#define IMAGE_SIZE		(0x00200000)
#define TAB_SIZE		199

const int _h_imx6_ivt_dcd_tbl[TAB_SIZE] =
{
	0X402000D1,ADDR_ENTRY,0X00000000,ADDR_DCD,  ADDR_BOOT, ADDR_SELF, 0X00000000,0X00000000,
	ADDR_START,IMAGE_SIZE,0X00000000,
	0x40F002D2,0x04EC02CC,0x74070E02,0x00000C00,0x54070E02,0x00000000,0xAC040E02,0x30000000,
	0xB0040E02,0x30000000,0x64040E02,0x30000000,0x90040E02,0x30000000,0x4C070E02,0x30000000,
	0x94040E02,0x30000000,0xA0040E02,0x00000000,0xB4040E02,0x30000000,0xB8040E02,0x30000000,
	0x6C070E02,0x30000000,0x50070E02,0x00000200,0xBC040E02,0x30000000,0xC0040E02,0x30000000,
	0xC4040E02,0x30000000,0xC8040E02,0x30000000,0xCC040E02,0x30000000,0xD0040E02,0x30000000,
	0xD4040E02,0x30000000,0xD8040E02,0x30000000,0x60070E02,0x00000200,0x64070E02,0x30000000,
	0x70070E02,0x30000000,0x78070E02,0x30000000,0x7C070E02,0x30000000,0x80070E02,0x30000000,
	0x84070E02,0x30000000,0x8C070E02,0x30000000,0x48070E02,0x30000000,0x70040E02,0x30000000,
	0x74040E02,0x30000000,0x78040E02,0x30000000,0x7C040E02,0x30000000,0x80040E02,0x30000000,
	0x84040E02,0x30000000,0x88040E02,0x30000000,0x8C040E02,0x30000000,0x00081B02,0x030039A1,
	0x0C081B02,0x78006C00,0x10081B02,0x4A004D00,0x0C481B02,0x40003800,0x10481B02,0x44002F00,
	0x3C081B02,0x28022D42,0x40081B02,0x0B020002,0x3C481B02,0x07020342,0x40481B02,0x5D015801,
	0x48081B02,0x46474543,0x48481B02,0x40474444,0x50081B02,0x31303637,0x50481B02,0x2F343235,
	0x1C081B02,0x33333333,0x20081B02,0x33333333,0x24081B02,0x33333333,0x28081B02,0x33333333,
	0x1C481B02,0x33333333,0x20481B02,0x33333333,0x24481B02,0x33333333,0x28481B02,0x33333333,
	0xB8081B02,0x00080000,0xB8481B02,0x00080000,0x04001B02,0x2D000200,0x08001B02,0x4030331B,
	0x0C001B02,0xB352433F,0x10001B02,0x638B6DB6,0x14001B02,0xDB00FF01,0x18001B02,0x40170100,
	0x1C001B02,0x00800000,0x2C001B02,0xD2260000,0x30001B02,0x23104300,0x40001B02,0x27000000,
	0x00001B02,0x00001A83,0x1C001B02,0x32800004,0x1C001B02,0x33800000,0x1C001B02,0x31800400,
	0x1C001B02,0x30802005,0x1C001B02,0x40800004,0x20001B02,0x00580000,0x18081B02,0x17110100,
	0x18481B02,0x17110100,0x04001B02,0x6D550200,0x04041B02,0x06100100,0x1C001B02,0x00000000,
	0x68400C02,0x3F3FC000,0x6C400C02,0x03FC3000,0x70400C02,0x00C0FF0F,0x74400C02,0x0000F03F,
	0x78400C02,0x00F3FF00,0x7C400C02,0xC300000F,0x80400C02,0xFF030000,0x10000E02,0xCF0000F0,
	0x18000E02,0x7F007F00,0x1C000E02,0x7F007F00,
};

#endif /* __IMX_HEADER_ */

imx6ull.h

#ifndef __IMX_HEADER_
#define __IMX_HEADER_

#define ADDR_ENTRY		(0x87800000)
#define ADDR_SELF		(ADDR_ENTRY - 3*1024)
#define ADDR_START		(ADDR_ENTRY - 4*1024)
#define ADDR_DCD		(ADDR_SELF + 0x2C)
#define ADDR_BOOT		(ADDR_SELF + 0x20)
#define IMAGE_SIZE		(0x00200000)
#define TAB_SIZE		133

const int _h_imx6_ivt_dcd_tbl[TAB_SIZE] =
{
	0X402000D1,ADDR_ENTRY,0X00000000,ADDR_DCD,  ADDR_BOOT, ADDR_SELF, 0X00000000,0X00000000,
	ADDR_START,IMAGE_SIZE,0X00000000,
	0x40E801D2,0x04E401CC,0x68400C02,0xFFFFFFFF,0x6C400C02,0xFFFFFFFF,0x70400C02,0xFFFFFFFF,
	0x74400C02,0xFFFFFFFF,0x78400C02,0xFFFFFFFF,0x7C400C02,0xFFFFFFFF,0x80400C02,0xFFFFFFFF,
	0xB4040E02,0x00000C00,0xAC040E02,0x00000000,0x7C020E02,0x30000000,0x50020E02,0x30000000,
	0x4C020E02,0x30000000,0x90040E02,0x30000000,0x88020E02,0x30000C00,0x70020E02,0x00000000,
	0x60020E02,0x30000000,0x64020E02,0x30000000,0xA0040E02,0x30000000,0x94040E02,0x00000200,
	0x80020E02,0x30000000,0x84020E02,0x30000000,0xB0040E02,0x00000200,0x98040E02,0x30000000,
	0xA4040E02,0x30000000,0x44020E02,0x30000000,0x48020E02,0x30000000,0x1C001B02,0x00800000,
	0x00081B02,0x030039A1,0x0C081B02,0x0B000300,0x3C081B02,0x44014801,0x48081B02,0x302C4040,
	0x50081B02,0x343E4040,0x1C081B02,0x33333333,0x20081B02,0x33333333,0x2C081B02,0x333333F3,
	0x30081B02,0x333333F3,0xC0081B02,0x09409400,0xB8081B02,0x00080000,0x04001B02,0x2D000200,
	0x08001B02,0x3030331B,0x0C001B02,0xF3526B67,0x10001B02,0x630B6DB6,0x14001B02,0xDB00FF01,
	0x18001B02,0x40172000,0x1C001B02,0x00800000,0x2C001B02,0xD2260000,0x30001B02,0x23106B00,
	0x40001B02,0x4F000000,0x00001B02,0x00001884,0x90081B02,0x00004000,0x1C001B02,0x32800002,
	0x1C001B02,0x33800000,0x1C001B02,0x31800400,0x1C001B02,0x30802015,0x1C001B02,0x40800004,
	0x20001B02,0x00080000,0x18081B02,0x27020000,0x04001B02,0x2D550200,0x04041B02,0x06100100,
	0x1C001B02,0x00000000,
};

#endif /* __IMX_HEADER_ */

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值