从最简单的开始做起。。
目前,为实现TFTP下载,从包的格式可知,需要板子和主机的IP地址,板子和主机的MAC地址。这四个值我们实现为环境变量。故在net_device.c中增加五个命令:
net setip
net setserverip
net setmac
net setservermac
net setgateway
其对应的五个函数:
void set_ip(int argc,const char **argv);
void set_server_ip(int argc,const char **argv);
void set_mac(int argc,const char **argv);
void set_server_mac(int argc,const char **argv);
void set_gateway(int argc,const char **argv);
|
将这五个函数的声明添加到include/net.h中,在net/net.c中实现这四个函数。来测试一下这五个函数的实现是否正确。开始的时候,链接错误,后来发现是Makefile有问题,开始的时候Makefile是
vivi: include/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) -v $(LINKFLAGS) \
$(HEAD) \
$(CORE_FILES) \
$(DRIVERS) \
$(LIBS) \
$(NET)\
-o vivi-elf $(CLIBS)
开始没有修改VIVI的时候,编译链接是没问题的。修改之后链接出错,注意到这里的$(NET)是个目录,不明白开始的时候为什么要这样写,于是依据net/Makefile, ,改为$(NET)\libnet.a。编译链接通过。。测试结果表示实现正确。
接着,我们加入网卡CS8900的驱动。驱动是拷贝的uboot-1.3.3中的CS8900的驱动,并稍稍对超时处理的部分作了下修改。重新make后下载到板子运行,发现不能识别出网卡。这时我想到了以前移植内核驱动的时候也出现过这样的情况,当时是因为没有对BWSCON、BANKCON3这两个寄存器初始化。因为硬件电路决定了CS8900的物理地址是在BANK3的区间内。故我们需要对其进行相应的设置。CS8900是16位的寄存器,故我们设置BANK3的BUS WIDTH也为16位。相应的代码:
int *p=(volatile int *)0x48000000; //BWSCON
int reg=(*p)|(1<<15)|(1<<14)|(1<<12)&(0<<12);
*p=reg;
p=(volatile int *)0x48000010; //BANKCON3
*p=0x1f7c;
|
问题解决,CS8900被识别出。。
----------------------------------------------------------------------------------------------
补充一点关于编译链接的知识,这些都是在曾经困惑过我的(有颜色的部分来自) 1、运行时,动态库的装载依赖于ld-linux.so.6的实现,它查找共享库的顺序如下: (1)ld-linux.so.6在可执行的目标文件中被指定,可用readelf命令查看 (2)ld-linux.so.6缺省在/usr/lib和lib中搜索;当glibc安装到/usr/local下时,它查找/usr/local/lib (3)LD_LIBRARY_PATH环境变量中所设定的路径 (4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路径,由ldconfig生成二进制的ld.so.cache中2、编译时,搜索库的路径顺序如下: (1)ld-linux.so.6由gcc的spec文件中所设定 (2)gcc --print-search-dirs所打印出的路径,主要是libgcc_s.so等库。可以通过GCC_EXEC_PREFIX来设定 (3)LIBRARY_PATH环境变量中所设定的路径,或编译的命令行中指定的-L/usr/local/lib (2)binutils中的ld所设定的缺省搜索路径顺序,编译binutils时指定。(可以通过“ld --verbose | grep SEARCH”来查看)3、二进制程序的搜索路径顺序为PATH环境变量中所设定。一般/usr/local/bin高于/usr/bin4、编译时的头文件的搜索路径顺序,与library的查找顺序类似。一般/usr/local/include高于/usr/include 对于用-I选项指定的路径,比如说-I/home/lpzgbd/ ,这时如果要包含/home/lpzgbd下的头文件file.h,用#include
就可以了.在VIVI的Makefile中
已指定头文件路径为
/usr/local/arm/2.95.3/include 以及vivi/include。故这两个目录下的头文件可以用<>包含进来。
在用arm-linux-gcc编译时,默认链接的是glibc库。如果我们想重新写一个glibc中已经有了的函数,我们应该怎么办了,应该怎么让程序链接到我们自己写的函数,而不是glibc呢?我想到的办法有两个。
1.放在编译的时候解决这个问题。方法就是把这个函数定义在调用这个函数的函数所在的那个文件中。当然就不能包含glibc库中声明的头文件了,以避免声明冲突。如:
#include<stdio.h>
// unsigned long int strtoul(char *c,char **enp,int x){return 0;}
int main(){
char *c="1234";
printf("%d\n",strtoul(c,0,0));
return 0;
}
|
strtoul是glibc库中的函数,以上程序的结构是输出了1234。现在我们将其改为
#include<stdio.h>
unsigned long int strtoul(char *c,char **enp,int x){return 0;}
int main(){
char *c="1234";
printf("%d\n",strtoul(c,0,0));
return 0;
}
|
程序的输出为0。
但是这样做的限制也就显尔易见了,就是其它文件中的函数不能调用自己重新定义的函数。
2.放在链接的时候解决这个问题。如:file.c:
#include<stdio.h>
int main(){
char *c="1234";
printf("%d\n",strtoul(c,0,0));
return 0;
}
file1.c:
#include"f.h"
unsigned long int strtoul(char *c,char **enp,int x){return 0;}
f.h:
extern unsigned long int strtoul (char *nptr,char **endptr, int base);
|
编译的时候 cc file.c file1.c就可以避免链接到glibc了。
因此,比如说要在VIVI中自己实现strtoul这个函数,只要让调用strtoul的函数所在的源文件包含strtoul声明所在的头文件,然后在将这两个文件链接即可。
-----------------------------------------------------------------------------------------------
阅读(2552) | 评论(0) | 转发(0) |