网卡芯片的工作原理

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. MVC和MTV框架模式

    1. MVC: MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  2. Py第一次练习,第二次练习

    有两个列表      l1 = [11,22,33]        l2 = [22,33,44] 1.获取内容相同的元素列表2.获取l1中有l2中没有的元素列表3.获取l1和l2中不同的元素列表 l ...

  3. 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

    最近栈长注意到阿里开源了自家的 Mock 工具:TestableMock,该工具号称最轻量.简单.舒适的 Mock 测试工具,功能十分强大,媲美 PowerMock,用法比 Mockito 还要简洁, ...

  4. javascript通过递归改子节点数据-用于层级深度未知的树形结构

    最近在做这么个需求:树形结构,层级深度未知,一旦某个节点的状态是置灰的话,其所有子节点都要置灰. 方案一(数据库有值):如果数据库里置灰节点的所有子节点,值也都是"置灰",那后台取 ...

  5. Java语法糖详解

    语法糖 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更 ...

  6. 解析MySQL中存储时间日期类型的选择问题

    解析MySQL中存储时间日期类型的选择问题_Mysql_脚本之家 https://www.jb51.net/article/125715.htm 一般应用中,我们用timestamp,datetime ...

  7. CPU飙高,系统性能问题如何排查?

    CPU飙高,系统性能问题如何排查? 原创 雍雍 阿里技术 2020-09-29 https://mp.weixin.qq.com/s/fzLcAkYwKhj-9hgoVkTzaw  

  8. V2版的接口在V3版里面都能找到对应接口 数据结构

    开发文档 - 微信支付商户平台 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/api.shtml 版本选择 关闭 V2版接口和V3版接口实际 ...

  9. REST 架构的替代方案 为什么说GraphQL是API的未来?

    Managing enterprise accounts - GitHub Docs https://docs.github.com/en/graphql/guides/managing-enterp ...

  10. dij的优先队列边表优化

    dij的复杂度为v*v,通过优先队列优化后为e*logv. (第一次写,没有过多的测试,不保证对.只当是测试blog了!) #include<cstdio> #include<ios ...