210学习日记(6)
--独立日
写了这么久的S5PV210的裸板程序了,每次编译完成后,生成的bin文件总是要经过mktiny210spl.exe工具(是u-boot生成的)重新生成一个新的bin文件,而该bin文件只比旧的bin文件多出四行信息(在Tiny210学习日记(2)中有讲过),也就是说,该四行信息是mktiny210spl.exe帮我们写的,所以我们没有真正的独立,没有真正的从头开始写程序。
但是,出于好奇,我今天必须要揭开mktiny210spl.exe的神秘面纱,实现真正的独立!!
尝试一:
在在Tiny210学习日记(2)中有讲到,IROM从外部存储器中拷贝到IRAM中的代码的前16字节不能够是真正的代码,而应该是头部信息,排列格式如下:
---------------------------------------------
0x0地址:BL1 size
---------------------------------------------
0x4地址:必须设置为0 (是规定)
---------------------------------------------
0x8地址:CheckSum
---------------------------------------------
0xc地址:必须设置为0 (是规定)
---------------------------------------------
IROM需要前16字节是头部信息,那我给你头部信息就是,该怎么做呢?按照对信息的强制要求,我做了以下尝试,在start.s的开头添加了以下代码:
.word 0x4000 @规定0x0地址存放要拷贝的大小,那我就给你大小,就16K吧(最多拷贝16K)
.word 0x0 @规定0x4地址存放0,那我给你0
.word ?? @规定0x8地址存放CheckSum,那么CheckSum该是多少呢?
.word 0x0 @规定0xc地址存放0,那我给你0
在添加代码的时候,出现了疑问,就是CheckSum该是多少?是一个固定值吗?网上收索了大量资料后,最终得出CheckSum的计算公司如下(用一C程序来描述):
#define uBlAddr 直接编译出的bin文件的开始地址
unsigned int count;
unsigned int dataLength; /* 用于指明要拷贝数据的大小,即BL1 size */
unsigned char buf; /* 用于存放临时数据 */
unsigned int checksum; /* 我们要计算的结果,checksum */
for(count=0;count< dataLength;count+=1)
{
buffer = (*(volatile unsigned char*)(uBlAddr+count));
checksum = checksum + buffer;
}
最终发现,checksum是动态生成的,是可变的,所以直接导致尝试一以失败告终!!!
继续查阅资料......
尝试二:
查了很久的资料,最终想起,最好的资料就是u-boot了,这个工具不是u-boot生成的吗?那么里面肯定有它的源码,一搜索,一提炼,果然,发现它的代码如下:
这是一个属于应用程序的工具了,一看这个代码,我才发现我大一学习的C函数中关系文件操作的知识全部忘光了,不过在查阅资料以后,我还是给出了详细的注释......
#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;
}
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;
}
以上的实现过程就是mktiny210spl.exe的真实面目。接下来就是该怎么生成这个工具了,步骤如下:
1).新建一个文件,命名为wy_mktools.c;(毕竟花费了这么久的时间来学习它,所以就取属于自己的名字了)
2).将尝试二中的代码录入wy_mktools.c;
3).编译生成wy_mktools.exe:(Makefile的内容如下)
wy_mktools.exe: wy_mktools.c
gcc wy_mktools.c -o wy_mktools.exe
到此,自制小工具终于成功了,独立日也从此到来。以后请执行./wy_mktools.exe old.bin new.bin吧!!
注意:
1.我用的是第一个流水灯实验做的测试,用于测试的代码放到了"Tiny210学习日记_代码"目录下了,名为"5_water_led_independent",当然,以后每个程序都是用的wy_mktools.exe!!
2.自制工具的相关代码,以及Makefile都放到了"Tiny210学习日记_代码"目录下了,名为"wy_mktools"。
3.该工具有点问题,但是现在能够使用。我会在后面讲问题出在哪里,和如何修改!!
注:
如有问题,请到韦东山LINUX视频讨论群里面,我们一起讨论学习,或者加我QQ:317312379