网卡芯片的工作原理

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. argparse的简单使用

    简单记录一下argparse的用法 这个是针对我做区块链的一些demo时需要用到的,仅把用到了的一些操作记录,argparse很强大,更多细致的操作可以参考:https://docs.python.o ...

  2. MySQL高可用HA——keepalived配置

    0. Keepalived介绍   Keepalived是基于VRRP(Virtual Router Redundancy Protocol,虚拟路由器冗余协议)协议的一款高可用软件.Keepaili ...

  3. Feign配置日志的打印级别

    一.细粒度的配置Feign的日志级别(针对每个微服务配置) 1.java代码方式 (1)在Feign接口注解上面配置configuration /** * @author : maybesuch * ...

  4. es5和es6的区别

    ECMAScript5,即ES5,是ECMAScript的第五次修订,于2009年完成标准化ECMAScript6,即ES6,是ECMAScript的第六次修订,于2015年完成,也称ES2015ES ...

  5. mysql8.0.19忘记密码

    1.管理员打开cmd窗口 2.输入net stop mysql,停止mysql服务 3.开启跳过验证密码的mysql服务 用记事本打开 输入skip-grant-tables ,保存 4.管理员打开新 ...

  6. Python学习【第5篇】:数据类型和变量总结

    字符串,数字,列表,元组,字典 可变不可变 1.可变:列表 如: p.p1 { margin: 0; font: 11px Menlo; color: rgba(0, 0, 0, 1); backgr ...

  7. 【Android初级】如何实现一个具有选择功能的对话框效果(附源码)

    我们去餐厅吃饭时,服务员都会拿菜单给我们选择点什么菜.今天就分享一个具有选择功能的简易对话框,给用户展示一个选择列表.实现思路如下: 既然有选择列表,那么这个列表的内容肯定保存在某个地方 用户选择某一 ...

  8. springboot+Jenkins+docker-compose自动部署项目实践

    DevOps思想 一个开发.测试.运维的整个过程的思想. plan:需求.计划 code:编码 build:构建 test: 测试 release:发布版本 deploy:部署 operate:项目运 ...

  9. JS从后台获取数据,前台动态添加tr标签中的td标签

    功能描述: 要求从后台查询该省份的所有城市,然后动态的再前台固定的tr标签中添加相应的td标签来展示城市基本信息: 文章目录 #一.前台jsp及js源码 jsp:在固定的tr标签中添加一个id,通过j ...

  10. Python实现量子态采样

    什么是量子态矢量? 在前面一篇量子系统模拟的博客中,我们介绍了使用python去模拟一个量子系统演化的过程.当我们尝试理解量子态和量子门操作时,可以通过其矩阵形式的运算来描述量子态演化的过程: \[\ ...