网卡芯片的工作原理

DM9000AE具有以下主要性能:

①48管脚的LQFP封装,管脚少体积小;

②支持8/16位数据总线;

③适用于10Base-T和100Base-T,10/100M自适应,适应不同的网络速度要求

④内置16KB的SRAM,用于收发缓冲,降低对主处理器的速度要求;

⑤支持IP /TCP /UDP加速,减轻了CPU负担,提高网络速度;⑥支持Back pressure半双工流量控制,与IEEE802.3u兼容,支持IEEE802.3x全双工流量控制;

⑦20ns响应时间,2.5V/3.3V低功耗。下图是DM9000网卡芯片常用在嵌入式网络系统上的结构框图。

数据支持8位和16位,不同模式下的PIN脚定义是不相同额,就拿16bit数据位宽来说。如下

其中RX和TX和LED是到隔离变压器的,X1和2为工作时钟晶振接入。CS为片选脚,默认低电平有效,可通过内部EEPROM配置。SD为数据脚,INT为接受到数据并校验正确后的中断信号,一般接到处理器的中断脚上。EE打头的脚是用来操作内部eeprom的。其中32脚为CMD脚,他是控制数据交换的主要脚,SD脚负责数据传输。通过手册可以知道CPU总线只访问它的两个地址,CMD管脚为0时,数据线送的是DM9000的寄存器地址,CMD管脚为1时,数据线上送的是16位的寄存器数据,所以对DM9000的操作至少需要两步:先写地址,再写(读)数据。这样CPU和他的数据交换原理就清楚了。下面是我的硬件的原理图

这里看到他将这个芯片接在了SOC内存接口0上,通过三星的手册知道芯片的这个接口可以支持访问外部8/16bit的 norflash、SRAM等,共支持6个bank。由片选脚的编号可以知道网卡被安排在bank1上,所以上面芯片内存map图,知道地址为88000000~8fffffff。中断脚接在了芯片的外部中断7脚上。知道这些信息就可以修改Uboot中的代码以使我们的板子支持这个网卡芯片了。

代码修改

先直接通过menuconfig使能Networking support 并选择DM9000网卡驱动,烧写后启动提示(这个图是我当时调试参考的博主的博客中的因为自己当时调试忘记截图了。。。)

根据提示信息找打打印这一段信息的代码位置在board_r.c这个文件中,可见我通过menuconfig启用网络实际上就是在配置文件中增加CONFIG_CMD_NET 这个宏

#ifdef CONFIG_CMD_NET
static int initr_net(void)
{
puts("Net: ");
eth_initialize();
#if defined(CONFIG_RESET_PHY_R)
debug("Reset Ethernet PHY\n");
reset_phy();
#endif
return 0;
}
#endif

继续向下看里面的各个函数内部的实现

int eth_initialize(void)
{
int num_devices = 0; eth_devices = NULL;
eth_current = NULL;
eth_common_init();
/*
* If board-specific initialization exists, call it.
* If not, call a CPU-specific one
*/
if (board_eth_init != __def_eth_init) {
if (board_eth_init(gd->bd) < 0)
printf("Board Net Initialization Failed\n");
} else if (cpu_eth_init != __def_eth_init) {
if (cpu_eth_init(gd->bd) < 0)
printf("CPU Net Initialization Failed\n");
} else {
printf("Net Initialization Skipped\n");
} if (!eth_devices) {
puts("No ethernet found.\n");
bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
} else {
struct eth_device *dev = eth_devices;
char *ethprime = getenv("ethprime"); bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
do {
if (dev->index)
puts(", "); printf("%s", dev->name); if (ethprime && strcmp(dev->name, ethprime) == 0) {
eth_current = dev;
puts(" [PRIME]");
} if (strchr(dev->name, ' '))
puts("\nWarning: eth device name has a space!"
"\n"); eth_write_hwaddr(dev, "eth", dev->index); dev = dev->next;
num_devices++;
} while (dev != eth_devices); eth_current_changed();
putc('\n');
} return num_devices;
}

这里主要是u-boot的为了增加他的通用性和兼容所以内部机制复杂了一些,首先判断板级和CPU级的网络配置接口是否定义,具体的处理就是如果板级和cpu级的配置接口都在则优先执行board的网络初始化,通过打印内容可以很清楚的看到实际上我们现在是都未定义所以执行最后的else分支打印了上面的log信息。所以我们需要自己实现两者其中之一,移植大法就是参考已有的,通过在u-boot代码中找到我们自己的硬件比较相似的现成驱动来参考,全局搜索最后选择使用三星的smdk100他使用了网卡所以可以借鉴他的实现

int board_eth_init(bd_t *bis)
{
int rc = 0;
#ifdef CONFIG_SMC911X
rc = smc911x_initialize(0, CONFIG_SMC911X_BASE);
#endif
return rc;
}

发现他使用的网卡是SMC911x系列的和我们的并不相同,还是找参考找和我手上相同的网卡的初始化驱动代码来参考,最后找到u-boot内部自带自带的dm9000x.c这个驱动文件,他就是实现好了网卡的初始化而且这个驱动封装的非常容易移植,通用的的部分内部实现不通用的部分留给移植实现如下

int dm9000_initialize(bd_t *bis)
{
struct eth_device *dev = &(dm9000_info.netdev); /* Load MAC address from EEPROM */
dm9000_get_enetaddr(dev); dev->init = dm9000_init;
dev->halt = dm9000_halt;
dev->send = dm9000_send;
dev->recv = dm9000_rx;
strcpy(dev->name, "dm9000"); eth_register(dev); return 0;
}

这里我在我的板级文件s5pc210.c的文件中增加这个接口内容如下同时还需要通过menuconfig使能dm9000x的驱动:

int board_eth_init(bd_t *bis)
{
int rc = 0;
#ifdef CONFIG_DRIVER_DM9000
rc = dm9000_initialize(bis);
#endif
return rc;
}

接下来还要继续实现一下具体的不通用的部分的部分,因为SMC911x和DM9000的工作原理类似就如同我前面介绍的一样,他们都是作为ROM实现接在CPU存储器控制总线上的所以当然也需要初始化CPU的存储器控制接口,这也是参考smdk100进行修改最后如下

static void dm9000_pre_init(void)
{
u32 smc_bw_conf, smc_bc_conf; /* gpio configuration GPK0CON */
gpio_cfg_pin(S5PC110_GPIO_MP010 + CONFIG_ENV_SROM_BANK, S5P_GPIO_FUNC(2)); /* Ethernet needs bus width of 16 bits */
smc_bw_conf = SMC_DATA16_WIDTH(CONFIG_ENV_SROM_BANK) |
SMC_BYTE_ADDR_MODE(CONFIG_ENV_SROM_BANK)|
SMC_WAIT_ENABLE(CONFIG_ENV_SROM_BANK) |
SMC_BYTE_ENABLE(CONFIG_ENV_SROM_BANK); smc_bc_conf = SMC_BC_TACS(0x0) | SMC_BC_TCOS(0x1) | SMC_BC_TACC(0x3)
| SMC_BC_TCOH(0x1) | SMC_BC_TAH(0x0)
| SMC_BC_TACP(0x0) | SMC_BC_PMC(0x0); /* Select and configure the SROMC bank */
s5p_config_sromc(CONFIG_ENV_SROM_BANK, smc_bw_conf, smc_bc_conf);
}

其中主要修改索对应的BANK,IO接口和硬件接口时序时间控制参数相关的内容,然后在板级初始化文件中调用完成硬件的提前初始化,从而保证后面DM9000网卡驱动工作时的硬件基础

int board_init(void)
{
#ifdef CONFIG_CMD_NET
dm9000_pre_init();
#endif
/* Set Initial global variables */
gd->bd->bi_arch_number = MACH_TYPE_S5PV210;
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; return 0;
}

其实当时调试的时候我还在好奇dm9000的驱动是怎么和具体额硬件操作关联起来的,最后再看前面原理的时候就焕然大悟了,因为DM9000是作为ROM挂接在CPU的存储器总线上的,自然由CPU内部总线直接访问到网卡,而需要知道的就是网卡芯片作为ROM到底映射在了内存接口总线上的哪一个地址空间这是dm9000网卡的内部寄存器相关的就直接映射到CPU的存储总线地址空间了,这地址映射这一部分就是在dm9000_pre_init()处理接口中完成的这一部分涉及具体CPU的存储总线接口的初始化和工作原理,所以需要先了解这部分内容才是理解这部分的关键。

然后重新编译烧录SD卡启动如下(图片同上唯一的不同是我当时为出现地址为设置的提示,因为在板级文件中我指定了MAC地址)

u-boot的调试过程网络驱动的移植十分重要,他可以大大的简化后面的调试移植内核的工作,要不然就是需要修改编译一次内核就的插拔SD卡拷贝新的内核镜像文件到SD在重新启动,移植完了网络驱动在通过配置u-boot就支持ftp从而配合交叉编译的机器搭建tfp服务器后就很方便的可以从网络加载内核镜像进行调试移植内核和驱动了。这篇博客写作中间简短了一段时间所以效果不太好,但是总是要做完所以这里就强行结束了。不过在当时移植的时候是遇到了不少坑的,以后长点心及时记录不然 坑复坑。这里需要感谢一个博主是他的博客给力我很大的帮助从移植u-boot和Linux内核即部分驱动的开发。他的主页链接:https://blog.csdn.net/qq_16777851,感谢!

参考:https://blog.csdn.net/qq_16777851/article/details/81843354

u-boot 移植 --->5、友善之臂Tiny210底板王网卡驱动移植的更多相关文章

  1. AM335x(TQ335x)学习笔记——Nand&&网卡驱动移植

    移植完成声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前 ...

  2. AM335x(TQ335x)学习笔记——Nand&amp;&amp;网卡驱动移植

    移植完毕声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前 ...

  3. U-BOOT 移植到友善之臂mini2440

    U-BOOT 移植到友善之臂mini2440 开发环境:ubuntu 10.10 编译器:友善之臂mini2440光盘自带arm-linux-gcc 4.4.3 一. 在denx官网下载源码,我所用版 ...

  4. linux4.1内核配置以及编译及千兆网卡dp83867网卡驱动移植

    一  内核配置编译 1首先解压内核 tar jxvf linux-at91-4.1.tar.bz2: 2下载编译链 在ubuntu命令行中输入sudo apt-get install gcc-arm- ...

  5. linux网卡驱动移植

    这里重要的是物理层PHY receiver,MAC(media access control)层,这里与软件中的协议栈不同,在硬件上MAC是PHY的下一层.DM9000A将MAC和PHY做到一起,也可 ...

  6. 【Linux驱动】TQ2440 DM9000E网卡驱动移植(Linux-2.6.30.4)

    花了一天的时间研究了一下Linux-2.6.30.4版本号内核下关于TQ2440 DM9000E的网卡驱动移植.总结一下自己的收获. 事实上.在Linux-2.6.30.4版本号内核下有关于网卡驱动, ...

  7. Linux网卡驱动移植--Dm9000网卡驱动分析

    1. Linux网络体系结构由以下5部分组成 ① 系统调用接口: 位于Linux网络子系统的顶部,为应用程序提供访问内核网络子系统的方法,主要指socket系统调用. ② 协议无关接口: 实现一组基于 ...

  8. 基于tiny4412的Linux内核移植 -- DM9621NP网卡驱动移植(四)

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  9. linux enc28j60网卡驱动移植(硬件spi和模拟spi)

    本来想移植DM9000网卡的驱动,无奈硬件出了点问题,通过杜邦线链接开发板和DM9000网卡模块,系统上电,还没加载网卡驱动就直接崩溃了,找不到原因...刚好手上有一个enc28j60的网卡模块,于是 ...

随机推荐

  1. 鸿蒙的多媒体及Menu组件及小程序的多媒体组件

    目录: js业务逻辑层 视图渲染层 css属性设置 效果图 微信小程序展示 内网穿透工具下载 我们在搭建一个小程序或者网站的时候,往往要加载很多的图片,音频和视频文件.如果都从服务器获取静态资源,这样 ...

  2. codeup 1934 查找元素

    题目描述: 输入一个数n,然后输入n个数值各不相同,再输入一个值x,输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1. 输入: 测试数据有多组,输入n(1<=n<=200), ...

  3. history附上时间戳,history命令_Linux history命令:查看和执行历史命令

    起因是这样的,一台机器客户反馈连接不上,说没有任何操作.好吧,排查吧. 1.第一步先看网络是否通: 从图中可以看到一开始是一直不通的.然后就通了,问了客户有没操作重启什么的结果说没有任何操作,还让给个 ...

  4. 3、剑指offer-数组——数组中重复的数字

    *题目描述* **在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输 ...

  5. (007)每日SQL学习:将字符和数字分离

    with aa as ( select 'sad10' as data from dual union all select 'datf20' as data from dual union all ...

  6. Python爬虫学习笔记(三)

    Cookies: 以抓取https://www.yaozh.com/为例 Test1(不使用cookies): 代码: import urllib.request # 1.添加URL url = &q ...

  7. Spring Cloud系列之Commons - 1. 背景与基础知识准备

    本文基于 Spring Cloud 2020.0 发布版的依赖 本系列会深入分析 Spring Cloud 的每一个组件,从Spring Cloud Commons这个 Spring Cloud 所有 ...

  8. Jsp数字格式化

    日期格式(2008年5月5日22点00分23秒) <fmt:formatDate value="<%=new Date() %>" pattern="y ...

  9. (一)在Spring Boot应用启动之后立刻执行一段逻辑

    在Spring Boot应用启动之后立刻执行一段逻辑 1.CommandLineRunner 2.ApplicationRunner 3.传递参数 码农小胖哥:如何在Spring Boot应用启动之后 ...

  10. Golang之如何(优雅的)比较两个未知结构的json

    这是之前遇到的一道面试题,后来也确实在工作中实际遇到了.于是记录一下,如何(优雅的)比较两个未知结构的json. 假设,现在有两个简单的json文件. { "id":1, &quo ...