Chinaunix首页 | 论坛 | 博客
  • 博客访问: 357909
  • 博文数量: 49
  • 博客积分: 3229
  • 博客等级: 中校
  • 技术积分: 616
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-26 21:46
文章分类

全部博文(49)

文章存档

2011年(8)

2010年(2)

2009年(3)

2008年(36)

我的朋友

分类:

2008-09-20 23:00:12

  从最简单的开始做起。。
  目前,为实现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/bin

4、编译时的头文件的搜索路径顺序,与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) |
给主人留下些什么吧!~~