栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

ARM裸机篇(二)——i.MX6ULL启动过程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ARM裸机篇(二)——i.MX6ULL启动过程

linux系列目录:
linux基础篇(一)——GCC和Makefile编译过程
linux基础篇(二)——静态和动态链接
ARM裸机篇(一)——i.MX6ULL介绍
ARM裸机篇(二)——i.MX6ULL启动过程
ARM裸机篇(三)——i.MX6ULL第一个裸机程序
ARM裸机篇(四)——重定位和地址无关码
ARM裸机篇(五)——异常和中断


文章目录
  • 一、 i.MX6ULL启动流程
  • 二、i.MX6ULL镜像格式
  • 三、镜像实例
  • 四、制作镜像
  • 五、烧写镜像


一、 i.MX6ULL启动流程

I.MX6U 支持多种启动方式以及启动设备,比如可以从 SD/EMMC、 NAND Flash、 QSPI Flash等启动。
i.MX6UL完整的启动流程如下图所示,完成启动任务的代码位于0x0000 0000 地址处的Boot ROM。

启动流程过程大致可分为六步。①检查CPU的ID ,②检查复 位状态,③获取启动方式,④加载程序映像,⑤校验映像,⑥跳转到映像去执行。

i.MX6ULL有四个启动模式,如下表,具体使用哪种启动模式通过内部寄存器 BOOT_MODE 中的值来选择,如图:

当 BOOT_MODE 设置为内部 BOOT 模式以后,所谓“内部”是相对于“Serial Download”来说的,“内部”可以认为是 i.MX6ULL 支持的启动存储设备,例如 emmc、 nandflash、 SD card、norFlash 等等。具体从那种“内部”设备启动,由 BOOT_CFG1[7:4] 决定,如下表所示。表内部启动方式选择:

二、i.MX6ULL镜像格式

知道启动方式后 Boot ROM 代码并不能立即加载启动映像,因为我们的代码保存在芯片外部存储设备,从这些存储设备读数据之前首先要进行初始化。在 Boot ROM 程序根据保存在芯片中的默认配置信息配置这些存储器接口。

I.MX6ULL 的最终可烧写文件组成如下:
①、 Image vector table,简称 IVT, IVT 里面包含了一系列的地址信息,这些地址信息在ROM 中按照固定的地址存放着。

②、 Boot data,启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等。

③、 Device configuration data,简称 DCD,设备配置信息,重点是 DDR3 的初始化配置。

④、用户代码可执行文件,比如 led.bin。

最终烧写到 I.MX6U 中的程序其组成为: IVT+Boot data+DCD+.bin。

这4部分内容合并成为一个映像文件,烧写在EMMC、SD卡或TF卡等启动设备的某个固定地址,boot ROM程序去这个固定地址读出映像文件。启动设备不同,固定地址不同,如下图:

三、镜像实例

制作映像文件的起点是:我们编写的程序。制作过程中各项值的计算方法如下图所示。

按照上述的配置,板子上电后Boot Rom会根据上述的配置初始化时钟和DDR3,然后会将映像文件从启动设备(TF卡、eMMC)自动拷贝到DDR3内存上。Boot Rom应该将映像文件拷贝到内存的哪个位置,上述的配置文件已经规定好了,拷贝到DDR3中的位置和大小由Boot data数据决定,用户.bin文件的起始地址由地址entry决定,需要在链接脚本中手动配置。假设.bin文件的起始地址为0x87800000。复制结束后,CPU会从这个地址读取第一条指令开始执行程序。

四、制作镜像

假设我们已经有了一个led.S的裸机程序,然后经过编译链接到0x87800000这个地址,使用objcopy工具转换成bin文件:

arm-none-eabi-gcc -c led.S -o led.o
arm-none-eabi-ld -Ttext 0x87800000 led.o -o led.elf
arm-none-eabi-objcopy -O binary -S -g led.elf led.bin
  1. 确定入口地址entry:
    我们的程序运行时要放在内存中哪一个位置,这是我们决定的,由于我们把程序链接到了0x87800000,所以此地址就是程序的入口地址。
  2. 确定映像文件在内存中的地址start:
    boot ROM程序启动时,会把“Initial Load Region”读出来,“Initial load Region”里含有IVT、Boot data、DCD。boot ROM根据DCD初始化设备后,再把整个映像文件读到内存。
    在启动设备上,“Initial Load Region”之后紧跟着我们的程序,反过来说就是我们程序的前面,放着“Initial Load Region”。“Initial Load Region”的大小为load_size,那么在内存中“Initial Load Region”的位置start = entry – load_size=0x87800000 - 0x1000 = 0x877FF000。
  3. 确定IVT在内存中的地址self:
    self = start + ivt_offset = 0x877FF000 + 0x400 = 0x877FF400
  4. 确定Boot data在内存中的地址boot_data:
    IVT结构的大小是32个字节,IVT之后就是Boot data,而IVT中的boot_data值表示Boot data在内存中的位置,计算如下:
    boot_data = self + 32 =0x877FF400+32=0x877FF420
  5. 确定DCD在内存中的地址dcd:
    Boot data结构的大小是12字节,Boot data之后就是DCD,而IVT中的dcd值表示DCD在内存中的位置,计算如下:
    dcd = boot_data + 12 = 0x877FF420 + 0x0C = 0x877FF42C
  6. 写入DCD的数据
    DCD是用初始化硬件的,特别是初始化DDR。而DDR的初始化非常的复杂、专业,我们一般是使用硬件厂家提供的代码。
  7. 写入用户程序

经过上述7个步骤,映像文件就构建出来了,可以把它烧入启动设备。

把上述步骤,可以写成如下代码,自动为我们完成映像的制作:
imxdownload.c:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#define SHELLCMD_LEN	(200)
#define BIN_OFFSET		(3072)


#define PRINT_TAB		0	




const int imx6_512mb_ivtdcd_table[256] = {
0x402000D1,0x87800000,0x00000000,0x877FF42C,0x877FF420,0x877FF400,0x00000000,0x00000000,
0x877FF000,0x00200000,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,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000
};

const int imx6_256mb_ivtdcd_table[256] = {
0x402000D1,0x87800000,0x00000000,0x877FF42C,0x877FF420,0x877FF400,0x00000000,0x00000000,
0x877FF000,0x00076000,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,0x04000000,0x3C081B02,
0x3C013C01,0x48081B02,0x38324040,0x50081B02,0x28304040,0x1C081B02,0x33333333,0x20081B02,
0x33333333,0x2C081B02,0x333333F3,0x30081B02,0x333333F3,0xC0081B02,0x09409400,0xB8081B02,
0x00080000,0x04001B02,0x2D000200,0x08001B02,0x3030331B,0x0C001B02,0xF352433F,0x10001B02,
0x630B6DB6,0x14001B02,0xDB00FF01,0x18001B02,0x40172000,0x1C001B02,0x00800000,0x2C001B02,
0xD2260000,0x30001B02,0x23104300,0x40001B02,0x47000000,0x00001B02,0x00001883,0x90081B02,
0x00004000,0x1C001B02,0x32800002,0x1C001B02,0x33800000,0x1C001B02,0x31800400,0x1C001B02,
0x30802015,0x1C001B02,0x40800004,0x20001B02,0x00080000,0x18081B02,0x27020000,0x04001B02,
0x2D550200,0x04041B02,0x06100100,0x1C001B02,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
};




void message_print(void)
{	
	printf("I.MX6ULL bin download softwarern");
	printf("Edit by:zuozhongkairn");
	printf("Date:2019/6/10rn");
	printf("Version:V1.1rn");
	printf("log:V1.0 initial version,just support 512MB DDR3rn");
	printf("    V1.1 and support 256MB DDR3rn");
}

int main(int argc, char *argv[])
{
	FILE *fp;
	unsigned char *buf;
	unsigned char *cmdbuf;
	int nbytes, filelen;
	int i = 0, j = 0;
	int ddrsize = 0; 

	message_print();

	if((argc != 3) && (argc != 4)){
		printf("Error Usage! Reference Below:rn");
		printf("sudo ./%s <-512m or -256m>  rn", argv[0]);
		return -1;
	}

	
	for(i = 0; i < argc; i++)
	{
		char *param = argv[i];
		if(param[0] != '-')
			continue;
		if(strcmp(param, "-256m") == 0) 		
			ddrsize = 1;
		else if(strcmp(param, "-512m") == 0)	
			ddrsize = 0;
	}
	if(argc == 3)	
		ddrsize = 0;

	
	fp = fopen(argv[1], "rb"); 
	if(fp == NULL){
		printf("Can't Open file %srn", argv[1]);
		return -1;
	}
	
	
	fseek(fp, 0L, SEEK_END);
	filelen = ftell(fp);
	fseek(fp, 0L, SEEK_SET);
	printf("file %s size = %dBytesrn", argv[1], filelen);
	
	
	buf = malloc(filelen + BIN_OFFSET);
	if(buf == NULL){
		printf("Mem Malloc Failed!rn");
		fclose(fp);
		return -1;
	}
	memset(buf, 0, filelen + BIN_OFFSET); 
	
	fread(buf + BIN_OFFSET, 1, filelen, fp);

	
	fclose(fp);

#if PRINT_TAB
	printf("IVT DCD Table:rn");
	for(i = 0; i < 1024/32; i++){
		for(j = 0; j < 8; j++)
		{
			printf("0X%08X,",*(int *)(buf + BIN_OFFSET + (((i * 8) + j) * 4)));
		}
		printf("rn");
	}	
	free(buf);
	return 0;
#endif
	
	
	if(ddrsize == 0) {		
		printf("Board DDR SIZE: 512MBrn");
		memcpy(buf, imx6_512mb_ivtdcd_table, sizeof(imx6_512mb_ivtdcd_table));
	}
	else if (ddrsize == 1) {	
		printf("Board DDR SIZE: 256MBrn");
		memcpy(buf, imx6_256mb_ivtdcd_table, sizeof(imx6_256mb_ivtdcd_table));
	}

	
	printf("Delete Old load.imxrn");
	system("rm -rf load.imx");		
	
	printf("Create New load.imxrn");
	system("touch load.imx");		
	fp = fopen("load.imx", "wb");	
	if(fp == NULL){
		printf("Cant't Open load.imx!!!rn");
		free(buf);
		return -1;
	}
	nbytes = fwrite(buf, 1, filelen + BIN_OFFSET, fp);
	if(nbytes != (filelen + BIN_OFFSET)){
		printf("File Write Error!rn");
		free(buf);
		fclose(fp);
		return -1;
	}
	free(buf);
	fclose(fp);	
	
	
	cmdbuf = malloc(SHELLCMD_LEN);
	sprintf(cmdbuf, "sudo dd iflag=dsync oflag=dsync if=load.imx of=%s bs=512 seek=2",argv[2]);	
	printf("Download load.imx to %s  ......rn", argv[2]);
	
	
	system(cmdbuf);
	free(cmdbuf);
	return 0;	
}

编译:

gcc imxdownload.c -o imxdownload

使用方法:

sudo ./imxdownload <-512m or -256m>  

推荐在usr/local/bin 文件夹下建立软链接,后续可以直接使用imxdownload命令:

sudo ln -s ~/imx6ull/tools/imxdownload/imxdownload /usr/local/bin/imxdownload

测试:

五、烧写镜像

将USB读卡器插入电脑后,默认连接到主机,将鼠标放到USB图标上(虚拟机右下角状态栏), 单击鼠标右键如下所示,选择将读卡器连接到虚拟机上。

在将读卡器连接到虚拟机之后,使用lsblk查看,增加出来的设备就是我们内存卡的标识名。

使用imxdownload命令进行烧写:imxdownload led.bin /dev/sdb

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/830577.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号