S5PV210--1---210启动方式和代码前16字节
2014-10-17 11:26
357 查看
按照三星《S5PV210_UM_REV1.1》手册上说明的启动流程为:S5PV210上电将从IROM(interal ROM)处执行固化的启动代码,它对时钟等初始化、对启动设备进行判断,并从启动设备中复制BL1(最大16KB)到IRAM(0xd002_0000处,其中0xd002_0010之前的16个字节储存的BL1的校验信息和BL1尺寸)中,并对BL1进行校验,校验OK转入BL1进行执行;
首先解释一下我认为的BL0、BL1、BL2:
(1)BL0:是指S5PV210的IROM中固化的启动代码;
(2)BL1:是指在IRAM自动从外扩存储器(nand /sd/usb)中拷贝的uboot.bin二进制文件的头最大16K代码;
(3)BL2:是指在代码重定向后在内存中执行的的UBOOT的完整代码;
(4)三者之间关系是:(Interal ROM固话代码)BL0将BL1(bootloader的前16kB)加载到iRAM;BL1然后在iRAM中运行将BL2(其实整个bootloader)加载到SDRAM(DDR);BL2加载内核;BL就是bootloader的简写;
![](http://img.my.csdn.net/uploads/201212/09/1355018762_2013.png)
刚开始的搞210时,我们编译的代码都必须通过一个工具xxx210.xxx(如mktiny210.exe),这个是为什么呢,它的作用就是在我们生成的bin文件前面加上16个字节, 下面就说说前16字节的内容是什么:
S5PV210的iRAM的地址范围0xD002_0000~0xD003_FFFF,而上电后我们的iROM执行完固化的代码,并将boot设备中的代码拷贝到iRAM中,并跳转到0xD002_0010处执行,问题就在0xD002_0000~0xD002_0010这16字节数据该填写什么?
16字节头部信息,排列格式如下:
_____________________________
|0x0地址:BL1 size |
|0x4地址:必须设置为0 (是规定)|
|0x8地址:CheckSum |
|0xc地址:必须设置为0 (是规定)|
但是为什么要加上16字节呢,其实理解为了ECC校验用的就行了;
上面16字节的内容不是乱加的哦,下面给出uboot中参考代码,可以用的:
[cpp] view
plaincopy
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SEEK_SET 0 /* 文件开头的标记 */
#define SEEK_CUR 1 /* 当前位置的标记 */
#define SEEK_END 2 /* 文件末尾的标记 */
#define BUFSIZE (24*1024)
#define IMG_SIZE (24*1024)
#define SPL_HEADER_SIZE 16
#define SPL_HEADER "S5PC110 HEADER "
int main (int argc, char *argv[])
{
FILE *fp; /* 定义一个文件指针 */
char *Buf, *a;
int BufLen;
int nbytes, fileLen;
unsigned int checksum, count;
int i;
if (argc != 3) /* 如果参数个数错误,打印帮助信息,只能有两个参数*/
{
/* 应用工具时,格式必须是 ./mktiny210spl.exe old.bin new.bin */
printf("Usage: mkbl1 <source file> <destination file>\n");
return -1;
}//这一点大家要注意,main函数其实也是可以接收参数的,argc就表示了参数的个数,
//argv就是参数的内容;
BufLen = BUFSIZE;
Buf = (char *)malloc(BufLen); /* 动态分配一段24k的内存空间 */
if (!Buf) /* 分配失败,将返回0 */
{
printf("Alloc buffer failed!\n");
return -1;
}
memset(Buf, 0x00, BufLen); /* 将上面分配的空间清零 */
fp = fopen(argv[1], "rb"); /* 以读二进制的方式打开没有头部信号的old.bin文件 */
if( fp == NULL)
{
printf("source file open error\n");
free(Buf); /* 如果打开失败,释放掉原来分配的内存,否则会造成内存泄漏 */
return -1;
}
fseek(fp, 0L, SEEK_END); /* 让文件位置指针指向文件末尾,便于下行的统计大小的操作 */
fileLen = ftell(fp); /* 用于得到文件位置指针当前位置相对于文件首的偏移字节数,即文件大小*/
fseek(fp, 0L, SEEK_SET); /* 让文件位置指针指向文件开始 */
/* 如果old.bin文件的大小小于规定的最大大小,则count等于该文件的大小,否则等于最大大小 */
count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE); /* 拷贝16字节的数据到Buf中,即初始化头部信息的位置 */
nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp); /* 将编译生成的old.bin文件拷贝到buf中,紧接着头部信息开始拷贝 */
if ( nbytes != count ) /* 返回值等于拷贝的元素的个数 */
{
printf("source file read error\n"); /* 如果个数和实际的不相等,则失败 */
free(Buf); /* 释放内存 */
fclose(fp); /* 关闭文件 */
return -1;
}
fclose(fp); /* 关闭文件 */
/* 以下三行,用于动态生成checksum,公式见上面的尝试一 */
a = Buf + SPL_HEADER_SIZE;
for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
checksum += (0x000000FF) & *a++;
/* 将checksum写入buf的第三个字节处,即该是checksum的位置处 */
a = Buf + 8;
*( (unsigned int *)a ) = checksum;
fp = fopen(argv[2], "wb"); /* 以二进制写的方式创建一个新的二进制文件 */
if (fp == NULL)
{
printf("destination file open error\n");
free(Buf); /* 释放内存 */
return -1;
}
a = Buf; /* 指向内存的首地址 */
nbytes = fwrite( a, 1, BufLen, fp); /* 把buf中的数据写入新创建的bin文件 */
if ( nbytes != BufLen ) /* 返回值等于写入的元素的个数 */
{
printf("destination file write error\n");
free(Buf); /* 释放内存 */
fclose(fp);/* 关闭文件 */
return -1;
}
free(Buf); /* 释放内存 */
fclose(fp);/* 关闭文件 */
return 0;
}
[cpp] view
plaincopy
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SEEK_SET 0 /* 文件开头的标记 */
#define SEEK_CUR 1 /* 当前位置的标记 */
#define SEEK_END 2 /* 文件末尾的标记 */
#define BUFSIZE (24*1024)
#define IMG_SIZE (24*1024)
#define SPL_HEADER_SIZE 16
#define SPL_HEADER "S5PC110 HEADER "
int main (int argc, char *argv[])
{
FILE *fp; /* 定义一个文件指针 */
char *Buf, *a;
int BufLen;
int nbytes, fileLen;
unsigned int checksum, count;
int i;
if (argc != 3) /* 如果参数个数错误,打印帮助信息,只能有两个参数*/
{
/* 应用工具时,格式必须是 ./mktiny210spl.exe old.bin new.bin */
printf("Usage: mkbl1 <source file> <destination file>\n");
return -1;
}//这一点大家要注意,main函数其实也是可以接收参数的,argc就表示了参数的个数,
//argv就是参数的内容;
BufLen = BUFSIZE;
Buf = (char *)malloc(BufLen); /* 动态分配一段24k的内存空间 */
if (!Buf) /* 分配失败,将返回0 */
{
printf("Alloc buffer failed!\n");
return -1;
}
memset(Buf, 0x00, BufLen); /* 将上面分配的空间清零 */
fp = fopen(argv[1], "rb"); /* 以读二进制的方式打开没有头部信号的old.bin文件 */
if( fp == NULL)
{
printf("source file open error\n");
free(Buf); /* 如果打开失败,释放掉原来分配的内存,否则会造成内存泄漏 */
return -1;
}
fseek(fp, 0L, SEEK_END); /* 让文件位置指针指向文件末尾,便于下行的统计大小的操作 */
fileLen = ftell(fp); /* 用于得到文件位置指针当前位置相对于文件首的偏移字节数,即文件大小*/
fseek(fp, 0L, SEEK_SET); /* 让文件位置指针指向文件开始 */
/* 如果old.bin文件的大小小于规定的最大大小,则count等于该文件的大小,否则等于最大大小 */
count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE); /* 拷贝16字节的数据到Buf中,即初始化头部信息的位置 */
nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp); /* 将编译生成的old.bin文件拷贝到buf中,紧接着头部信息开始拷贝 */
if ( nbytes != count ) /* 返回值等于拷贝的元素的个数 */
{
printf("source file read error\n"); /* 如果个数和实际的不相等,则失败 */
free(Buf); /* 释放内存 */
fclose(fp); /* 关闭文件 */
return -1;
}
fclose(fp); /* 关闭文件 */
/* 以下三行,用于动态生成checksum,公式见上面的尝试一 */
a = Buf + SPL_HEADER_SIZE;
for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
checksum += (0x000000FF) & *a++;
/* 将checksum写入buf的第三个字节处,即该是checksum的位置处 */
a = Buf + 8;
*( (unsigned int *)a ) = checksum;
fp = fopen(argv[2], "wb"); /* 以二进制写的方式创建一个新的二进制文件 */
if (fp == NULL)
{
printf("destination file open error\n");
free(Buf); /* 释放内存 */
return -1;
}
a = Buf; /* 指向内存的首地址 */
nbytes = fwrite( a, 1, BufLen, fp); /* 把buf中的数据写入新创建的bin文件 */
if ( nbytes != BufLen ) /* 返回值等于写入的元素的个数 */
{
printf("destination file write error\n");
free(Buf); /* 释放内存 */
fclose(fp);/* 关闭文件 */
return -1;
}
free(Buf); /* 释放内存 */
fclose(fp);/* 关闭文件 */
return 0;
}
这个代码怎么用呢,在vc或者gcc,甚至Tc中编译,生成一个xxx.exe文件,我生成的是stepmk210.exe,然后按照下面的格式编译bin文件,生成的新bin文件就是我们要用的;
./stepmk210.exe led.bin led1.bin
OK,如果还有不理解,请留言,大家互相了交流~~~
相关文章推荐
- S5PV210--1---210启动方式和代码前16字节
- S5PV210--1---210启动方式和代码前16字节
- S5PV210--1---210启动方式和代码前16字节
- (转)S5PV210--1---210启动方式和代码前16字节
- 发布S5PV210 之Sate210 的 SDMMC/inand 启动wince 系统的bootloader
- FastDFS的配置、部署与API使用解读(2)以字节方式上传文件的客户端代码
- 210的启动方式心得
- u-boot_smdkv210 分析二:启动代码start.s分析
- u-boot_smdkv210 分析四:启动代码汇编部分总结
- s5pv210启动方式
- u-boot_smdkv210 分析二:启动代码start.s分析
- IIS修改上传附件大小后无法启动,错误代码-2145318902的解决方式
- S5PV210开发板启动方式详解
- 对调用了TypeMock.net的代码进行调试遇到的怪问题--在vs.net中启动resharper自带的unit test的过程和方式是什么样的?
- u-boot_smdkv210 分析二:启动代码start.s分析
- u-boot_smdkv210 分析:启动代码汇编部分总结
- u-boot_smdkv210 分析三:启动代码lowlevel.s分析
- u-boot_smdkv210 分析二:启动代码start.s分析
- s5pv210芯片wince6.0系统SD卡启动代码修改过程记录
- u-boot_smdkv210 分析四:启动代码汇编部分总结