u-boot移植(十二)---代码修改---支持DM9000网卡

一、准备工作

1.1 原理图

  

  CONFIG_DM9000_BASE

  片选信号是接在nGCS4引脚,若要确定网卡的基地址,则要根据片选信号的接口去确定。

  在三星2440的DATASHEET中memory control这一章的Figure 5-1. S3C2440A Memory Map after Reset 已经说明了片选4的地址,如下:

  

  只要发出的信号在 0x20000000--0x28000000 之间,就会使得片选4引脚变为低电平。所以可以确定我们网卡的基地址为0x20000000。

  CONFIG_DM9000_IO 和CONFIG_DM9000_DATA

  LADDR2 接在网卡的CMD引脚上,即CPU在LADDR2上发出高电平或低电平的时候可以去访问某个地址。这些地址称为IO地址和DATA地址。

  LADDR2 对应 100,即为4。

  之后就是位宽要确定,根据原理图,可以确定的是DM9000为16位的位宽(LDATA0~LADATA15)。那么要设置BWSCON寄存器:

  

  DW4应该置1。这一项可以更改 low_level_init 中的寄存器的值进行设置。

  再检查时序,时序在BANKCON4寄存器中设置,默认值也可以,寄存器也在low_level_init 中的寄存器的值进行设置。

  修改下Toch的值,改为2个时钟的保持时间。

  

1.2 修改参数

  u-boot 中已经有了DM9000的驱动,即dm9000x.c,现在要将DM9000的网卡驱动加进u-boot中进行编译。

  在drivers/net/Makefile文件中已经加进了dm9000x.c的编译文件,如下:

  

  现在要修改include/configs/jz2440.h文件,来支持dm9000x:

  

  改为:

  

  编译运行一次:

  

  运行成功,烧写:

  

二、代码修改

  搜索:No ethernet found.

  

  这里涉及到两个函数 eth_initialize 和 eth_init

    查看board_r.c中的init_sequence_r链表,找到网路的初始化程序。

  

  进入查看:

  

  这里调用的是 eth_initialize()函数。

  

  根据打印信息可以确定是调用的下面的那个。

  

  由代码可以看出  应该是在 eth_common_init()函数中初始化失败导致eth_devices初始化失败的。

  

  代码中调用了board_eth_init函数Jz2440.c (board\samsung\jz2440):

  

  这里只定义了 CONFIG_CS8900 并没有9000网卡,修改代码:

  

  编译运行:

  

  报告有错误:dm9000 address not set

  MAC地址未设置。

  对着打印信息查看代码,可以知道打印此条信息的代码是eth_write_hwaddr这个函数,这个函数在eth_initlize中调用:

 1 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 2            int eth_number)
 3 {
 4     unsigned char env_enetaddr[6];
 5     int ret = 0;
 6
 7     eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 8
 9     if (!is_zero_ethaddr(env_enetaddr)) {
10         if (!is_zero_ethaddr(dev->enetaddr) &&
11             memcmp(dev->enetaddr, env_enetaddr, 6)) {
12             printf("\nWarning: %s MAC addresses don‘t match:\n",
13                    dev->name);
14             printf("Address in SROM is         %pM\n",
15                    dev->enetaddr);
16             printf("Address in environment is  %pM\n",
17                    env_enetaddr);
18         }
19
20         memcpy(dev->enetaddr, env_enetaddr, 6);
21     } else if (is_valid_ethaddr(dev->enetaddr)) {
22         eth_setenv_enetaddr_by_index(base_name, eth_number,
23                          dev->enetaddr);
24     } else if (is_zero_ethaddr(dev->enetaddr)) {
25 #ifdef CONFIG_NET_RANDOM_ETHADDR
26         net_random_ethaddr(dev->enetaddr);
27         printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
28                dev->name, eth_number, dev->enetaddr);
29 #else
30         printf("\nError: %s address not set.\n",
31                dev->name);
32         return -EINVAL;
33 #endif
34     }
35
36     if (dev->write_hwaddr && !eth_mac_skip(eth_number)) {
37         if (!is_valid_ethaddr(dev->enetaddr)) {
38             printf("\nError: %s address %pM illegal value\n",
39                    dev->name, dev->enetaddr);
40             return -EINVAL;
41         }
42
43         ret = dev->write_hwaddr(dev);
44         if (ret)
45             printf("\nWarning: %s failed to set MAC address\n",
46                    dev->name);
47     }
48
49     return ret;
50 }

  上面定义了一个宏  CONFIG_NET_RANDOM_ETHADDR ,如果定义了此宏的话就会随机分配网卡物理地址,否则就打印错误信息,我们并不需要此宏。自己定义物理地址,从代码流程看,网卡地址是直接写进环境变量中的,然后再读取环境变量,这个时候就需要看看设置环境变量的地方了。

  环境变量的设置在 board_r.c的链表中,initr_env函数,initr_env 会调用 env_relocate() ,env_relocate() 调用 set_default_env 函数,set_default_env 函数中有一个结构体 default_environment ,这里面定义了默认的参数,进去看看一看就知道里面全部定义的是默认的环境变量参数,其中也有网络的:

  

  这里面没有物理地址的定义,所以我们可以自己定义物理地址:

  在这里加入下面的内容:

  

  在 include/configs/jz2440.h 中加入 CONFIG_ETHADDR的宏 ,这里我们可以根据自己本机上的MAC地址进行定义:

  

  

  保存编译,查看结果:

  

  已经不会再报错网卡了。进行测试看通讯是否正常。

  

  

  已经ping 通 网卡移植完成。

  

  

时间: 2024-10-13 15:16:32

u-boot移植(十二)---代码修改---支持DM9000网卡的相关文章

u-boot移植(十)---代码修改---支持nor flash

一.问题定位 开发板重启后打印了2个提醒和一个错误,caches的提醒先不看,看看flash和nand下面的提醒,bad CRC,Using default enviroment,我们可以定位Using default enviroment定位到 代码位置,如下: Env_common.c (common) 传入的参数应该是 !badCRC,再次定位函数set_default_env 看是在哪里调用此函数: 基本上文件都在common文件夹下,有common中的调用和 dataflash,nan

u-boot移植(十三)---代码修改---支持文件系统及补丁制作

一.烧写文件系统 1.1 jffs2烧写 1.下载文件系统:tftp 30000000 fs_mini_mdev.jffs2 2.擦除文件的块:nand erase.part rootfs 3.烧入文件系统:nand write.jffs2 30000000 0x00260000 5b89a8 4.设置启动参数:set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2 5.重新启动 这个需要先烧写内核. 1.2 yaffs

u-boot移植(二)---修改前工作:代码流程分析1

一.代码执行总体流程图 1.1 代码路径 U-boot.lds (arch\arm\cpu) vectors.S (arch\arm\lib) start.S (arch\arm\cpu\arm920t) lowlevel_init.S (board\samsung\jz2440) crt0.S (arch\arm\lib) relocate.S (arch\arm\lib) Board_init.c (common\init) Board_f.c (common) Jz2440.h (incl

Postfix邮箱(十二):修改Web页面及多域名访问

说明:Extmail支持多域名访问,通过修改WEB页面,实现各个域使用独立的页面文件,访问不同的域名看到相应的页面风格. 流程:先修改默认域yourmail.com的页面,再复制给新增域,最后稍稍修改新增域即可. 一.修改Web页面 说明:修改页面请参考附件中的模板文件,这里只列出一些重点项 1.修改页面中的显示文字 [[email protected] ~]# cd /var/wwww/excuite/extmail [[email protected] extmail]# vi lang/z

Spring Boot(十二)单元测试JUnit

一.介绍 JUnit是一款优秀的开源Java单元测试框架,也是目前使用率最高最流行的测试框架,开发工具Eclipse和IDEA对JUnit都有很好的支持,JUnit主要用于白盒测试和回归测试. 白盒测试:把测试对象看作一个打开的盒子,程序内部的逻辑结构和其他信息对测试人 员是公开的: 回归测试:软件或环境修复或更正后的再测试: 单元测试:最小粒度的测试,以测试某个功能或代码块.一般由程序员来做,因为它需要知道内部程序设计和编码的细节: JUnit GitHub地址:https://github.

学习mongo系列(十二)修改器($inc/$set/$unset/$push/$pop/upsert)

对于文档的更新除替换外,针对某个或多个文档只需要部分更新可使用原子的更新修改器,能够高效的进行文档更新.更新修改器是中特殊的键,用来指定复杂的操作,比如增加.删除或者调整键,还可能是操作数组或者内嵌文档.1.$inc > db.b.insert({"uid":"201603","type":"1","size":10})WriteResult({ "nInserted" : 1 }

Liferay 6.2 改造系列之十二:修改Portal设置页面表单内容

将Portal设置页面中无用的内容删除: 在/portal-master/portal-impl/src/portal.properties文件中,有如下配置: # # Input a list of sections that will be included as part of the company # settings form. # company.settings.form.configuration=general,authentication,users,mail-host-n

(十二)修改字符串中的空格

一.问题描述 给定一个数组形的字符串.为了网络传输,方便通用型,需求把空格变为  %20. 二.思路和Code 1 package algorithm; 2 3 /** 4 * Created by adrian.wu on 2019/2/26. 5 */ 6 public class ReplaceSpace { 7 /* 8 先遍历,求出spaceCount数目. 9 1.设定一个指针,P1 10 2.P1指向原始string的尾部. 11 3.从后向前遍历. 12 4.P1遇到字符把字符向

libevent源码深度剖析十二

libevent源码深度剖析十二 --让libevent支持多线程张亮 Libevent本身不是多线程安全的,在多核的时代,如何能充分利用CPU的能力呢,这一节来说说如何在多线程环境中使用libevent,跟源代码并没有太大的关系,纯粹是使用上的技巧. 1 错误使用示例 在多核的CPU上只使用一个线程始终是对不起CPU的处理能力啊,那好吧,那就多创建几个线程,比如下面的简单服务器场景.1 主线程创建工作线程1:2 接着主线程监听在端口上,等待新的连接:3 在线程1中执行event事件循环,等待事