在U-boot中添加以太网驱动

2023-09-07  

当定义CONFIG_CMD_NET和CONFIG_CMD_PING,编译之后执行ping命令,告警没有找到以太网。

因此,需要打开U-boot的网络功能, u-boot-sunxi-sunxi中没有找到明显的网络驱动代码,或许有通用的驱动,但可以获得资料的途径有限,再说我是个初学者,平时工作属于自动控制类,网络方面很菜,因此想通过修改一个网络驱动,进行一次初步学习,想到就开工...

边做边写,恐怕会比较乱。

 

开发环境:   1、笔记本RHEL5,安装编译器arm-none-eabi-版本4.7.2; 编辑器Vim;minicom2.1

                     2、台式机XPsp3,安装SourceInsight3.5

基本思路:  1、找到u-boot内网络代码运行的轨迹,初始化、数据交换的驱动接口等等

                     2、实现一个驱动,加入到这个运行轨迹中,设备初始化,数据读写等等

准备工作:   1、找到芯片资料,这个比较坑,只能找到RTL8021CP的PDF,至于CPU芯片资料,

                            ×,那简直不能称为资料,看看三星处理器资料,为啥别人能做大,不是没有原因的。

                     2、Cubieboard原理图一份,这个好弄,人手一份呀

                     3、网线准备了两根,一个常用上网的,一根交叉线。路由器一只。

                            在没有研究清楚硬件连接之前,这样准备应该比较充足了。

                     4、下个新版本编译器,找了一个arm-none-eabi-的编译器,版本4.7.2,估计是目前最高版本。

                            下载:http://www.codesourcery.com/sgpp/lite/arm

                            选择arm处理器,linux版本,点进去之后需要用邮箱注册,下载地址会发到邮箱。

                     5、因为没有CPU资料,需要寻找一个A10的网络驱动代码,在支持Cubieboard的内核中找到了。

                           下载:http://linux-sunxi.org/Cubieboard/Cubieboard_Linux-3.9

                            这个驱动是linux下的,需要修改一下或参考其操作硬件的过程,以便在u-boot内运行。

 

一、环境建立,初步编译

        考虑到这次需要参考其他开发板或CPU的网络驱动,因此用SourceInsight3.5建立一个u-boot-sunxi-sunxi的工程,建立关联关系,方便代码查阅。建立方法很简单,不懂的可以网上搜索一下。建立工程时不要删除其他代码,全部使用。

        linux下编译环境设置,将下载的编译器解压到 /usr/local/arm/目录,解压之后目录是arm-2012.09

        设置环境变量,在RHEL5系统内,在/ect/profile的末尾加上一句:

        export   PATH=$PATH:/usr/local/arm/arm-2012.09/bin

        保存之后,执行:source /ect/profile 或者logout,或者重启机器。

        回到bash,输入arm再按Tab键,可以看到编译工具链列出来了,执行

        arm-none-eabi-gcc   -v,可以看到版本是4.7.2

        其他系统编译器安装设置可以在网上搜索,有很多文章会提到。

        进入u-boot-sunxi-sunxi目录,修改Makefile内容,找到 CROSS_COMPILE ?=  这一行

        改为:CROSS_COMPILE ?= arm-none-eabi-

        进入 u-boot-sunxi-sunxi/arch/arm,修改config.mk内容,也是这一句 CROSS_COMPILE ?= 

        改为:CROSS_COMPILE ?= arm-none-eabi-

 

       回到u-boot-sunxi-sunxi目录,执行:

       make  distclean                     //清除之前编译的内容

       make  cubieboard_config     //设置板子

       make  -j4                                //编译,-j4表示多线程编译,可以使用-j2,如果是虚拟机可以不用这个参数,

                                                       //如果电脑配置比较好,可以使用 -j8

 

      等待一会,不出意外,编译完成,写入SD卡,到板子上运行,可以看到串口输出信息。

 

二、U-boot网络模块分析

      1、网络初始化

       之前曾经分析过主循环,在主循环main_loop()调用之前就是初始化。

       在文件u-boot-sunxi-sunxiarcharmlibboard.c, 函数board_init_r()内:

       ...........

        #if defined(CONFIG_CMD_NET)
        puts("Net:   ");
        eth_initialize(gd->bd);
        #if defined(CONFIG_RESET_PHY_R)
        debug("Reset Ethernet PHYn");
        reset_phy();
        #endif
        #endif

        ...........

       这一段代码可以看出,要执行网络初始化,需要定义CONFIG_CMD_NET。

       因此在u-boot-sunxi-sunxiincludeconfigssunxi-common.h 末尾加一句:

       #define  CONFIG_CMD_NET

 

      再来看看函数eth_initialize() 的内容,在文件 u-boot-sunxi-sunxineteth.c内:

       .................

       if (board_eth_init != __def_eth_init) {
             if (board_eth_init(bis) < 0)
             printf("Board Net Initialization Failedn");
       } else if (cpu_eth_init != __def_eth_init) {
             if (cpu_eth_init(bis) < 0)
                    printf("CPU Net Initialization Failedn");
       } else
             printf("Net Initialization Skippedn");

       .................

       如果只定义CONFIG_CMD_NET,在上电时就会打印 Net Initialization Skipped,执行了最后一个else的内容,因此,需要完成网络初始化,需要实现函数board_eth_init()或者cpu_eth_init()

       看代码,这两个函数谁等于__def_eth_init就执行谁,在看看__def_eth_init是啥,也在eth.c这个文件内

       static int   __def_eth_init(bd_t *bis)
       {
              return -1;
       }
       int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
       int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));

       可见,实现__def_eth_init的“alias  ”,bash命令里面有个alias,如果你用过就明白这是什么意思了,实现它,就可以进行初始化啦。

       想知道weak, alias是什么意思,请围观这位大侠的博客 http://blog.chinaunix.net/uid-20272712-id-1969771.html

       以太网模块在A10内,A10的手册称之为WEMAC模块,因此,我们需要实现cpu_eth_init函数,表明eathnet模块在CPU内部。

       在文件u-boot-sunxi-sunxiarcharmcpuarmv7sunxiboard.c内增加函数cpu_eth_init,内容如下:

   

      #ifdef   CONFIG_SUN4I_WEMAC

       int cpu_eth_init(bd_t *bis)
       {
              return   sun4i_wemac_initialize(bis);
       }
       #endif

      2、如何实现网络模块

      网络模块已经成熟了,我们并不需要增加很多代码,只需要实现对硬件的操作就可以了。

      基本的操作大约就几个:初始化、打开、关闭、接收、发送、挂起

      分析u-boot-sunxi-sunxinet目录内的代码,发现网络的数据结构定义在u-boot-sunxi-sunxiincludenet.h内

      struct eth_device {
           char name[16];                                                                              //网络名
           unsigned char enetaddr[6];                                                         //以太网地址
           int iobase;                                                                                       //io基址?
           int state;                                                                                          //设备状态

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。