mini2440nbsp;裸奔dm9000(下)

2024-03-15 03:30
文章标签 dm9000 裸奔 mini2440nbsp

本文主要是介绍mini2440nbsp;裸奔dm9000(下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:mini2440 裸奔dm9000(下) 作者:捷易通湖北旗舰店

4、验证初始化中的各个函数。

下面我们来看一下,上面所写的初始化函数是否可用。以上我们写好了三个函数,分别为

DM9000_init(),sendpacket()和receivepacket(),保存并命名为dm9000.c。既然我们要进行调试,当

然要有结果输出,根据自己的处理器的情况写一个串口程序,这些函数是学某个单片机的基础,这里不

做详细介绍,用到是时候会在函数里注释一下。

接下来我们来写个主函数,新建C文件,命名为mian.c,填写如下函数:

void main(void)

{

    unsigned int i;

    unsigned char c;

    uart0_init();//初始化串口,调试时用到

    DM9000_init();//初始化网卡

    print_regs();

}

函数写好,保存文件,连接硬件,连接网线到电脑上或局域网上,运行结果如下图所示: clip_image001

图4 显示寄存器值

这里首先检查,各个控制寄存器是否是自己写进去的值,在检查状态寄存器是否正确,其中主要要

看NSR寄存器的bit[6]是否为“1”,该位表示是否连接成功。本例中NSR的值为40H,括号里的数为对应

的十进制数。

下面我们将主函数改进一下,增加个中断接收函数,查看是否能接收到数据。

void main(void)

{

    unsigned int i;

    unsigned char c;

    uart0_init();//初始化串口,调试时用到

    DM9000_init();//初始化网卡

    sendpacket(60);

    while(1);//等待中断

}

void int_issue(void) //中断处理函数,需要根据自己的处理器进行设置

{

    unsigned int i;

    i = receivepacket(Buffer);//将数据读取到Buffer中。

int_again :

    if(i == 0)

    {

        return;

    }

     else

     {

        print_buffer();//将接收到的所有数据打印出来

         while(1);//停止在这里等待观察,注意:实际应用中是不允许停止在中断中的。

     }

    i = receivepacket(Buffer);

    if(i != 0)

    {

        goto int_again;

    }

}

编译调试,运行结果如下: clip_image002

图5 接收数据包中的数据

这是一个ARP应答包,包含了我电脑上的MAC地址和局域网内的IP地址。反正我也不是啥重要人物,

这里就不保密了,呵呵。

如果一些顺利,到这里对DM9000网卡芯片的初始化工作就完成了。如果出现问题,首先要

检查寄存器的值是否正确。可以将DM9000中的寄存器打印出来,查看到底是哪里的问题。如果打印出的

值很混乱,在确保串口程序无误的前提下,查看硬件连接,以及寄存器读写时序是否正确,重复调试几

次查找原因。

三、ARP协议的实现

    1、ARP协议原理简述

    ARP协议(Address Resolution Protocol 地址解析协议),在局域网中,网络中实际传输的是“

帧”,帧里面有目标主机的MAC地址。在以太网中,一个注意要和另一个主机进行直接通信,必须要知

道目标主机的MAC地址。这个MAC地址就是标识我们的网卡芯片唯一性的地址。但这个目标MAC地址是如

何获得的呢?这就用到了我们这里讲到的地址解析协议。所有“地址解析”,就是主机在发送帧前将目

标IP地址转换成MAC地址的过程。ARP协议的基本功能就是通过目标设备的IP地址,查询目标设备的MAC

地址,以保证通信的顺利进行。所以在第一次通信前,我们知道目标机的IP地址,想要获知目标机的

MAC地址,就要发送ARP报文(即ARP数据包)。它的传输过程简单的说就是:我知道目标机的IP地址,

那么我就向网络中所有的机器发送一个ARP请求,请求中有目标机的IP地址,请求的意思是目标机要是

收到了此请求,就把你的MAC地址告诉我。如果目标机不存在,那么此请求自然不会有人回应。若目标

机接收到了此请求,它就会发送一个ARP应答,这个应答是明确发给请求者的,应答中有MAC地址。我接

到了这个应答,我就知道了目标机的MAC地址,就可以进行以后的通信了。因为每次通信都要用到MAC地

址。

    ARP报文被封装在以太网帧头部中传输,如图为ARP请求报文的头部格式。 clip_image003

图6 用于以太网的ARP请求或应答分组格式

注意,以太网的传输存储是“大端格式”,即先发送高字节后发送低字节。例如,两个字节的数据

,先发送高8位后发送低8位。所以接收数据的时候要注意存储顺序。

整个报文分成两部分,以太网首部和ARP请求/应答。下面挑重点讲述。

“以太网目的地址”字段:若是发送ARP请求,应填写广播类型的MAC地址FF-FF-FF-FF-FF-FF,意思是

让网络上的所有机器接收到;

“帧类型”字段:填写08-06表示次报文是ARP协议;

“硬件类型”字段:填写00-01表示以太网地址,即MAC地址;

“协议类型”字段:填写08-00表示IP,即通过IP地址查询MAC地址;

“硬件地址长度”字段:MAC地址长度为6(以字节为单位);

“协议地址长度”字段:IP地址长度为4(以字节为单位);

“操作类型”字段:ARP数据包类型,0表示ARP请求,1表示ARP应答;

“目的以太网地址”字段:若是发送ARP请求,这里是需要目标机填充的。

    2、ARP的处理程序

    ARP协议原理很简单,下面我们来编写ARP协议的处理函数。新建文件命名为arp.c,填写如下函数

unsigned char mac_addr[6] = {*,*,*,*,*,*};

unsigned char ip_addr[4] = { 192, 168, *, * };

unsigned char host_ip_addr[4] = { 192, 168, *, * };

unsigned char host_mac_addr[6]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

unsigned char Buffer[1000];

uint16 packet_len;

#define HON(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))

void arp_request(void) //发送ARP请求数据包

{

//以太网首部

memcpy(ARPBUF->ethhdr.d_mac, host_mac_addr, 6);

memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);

ARPBUF->ethhdr.type = HON( 0x0806 );

//ARP首部

ARPBUF->hwtype = HON( 1 );

ARPBUF->protocol = HON( 0x0800 );

ARPBUF->hwlen = 6;

ARPBUF->protolen = 4;

ARPBUF->opcode = HON( 0 );

memcpy(ARPBUF->smac, mac_addr, 6);

memcpy(ARPBUF->sipaddr, ip_addr, 4);

memcpy(ARPBUF->dipaddr, host_ip_addr, 4);

packet_len = 42;//14+28=42

sendpacket( Buffer, packet_len );

}

注释:ARPBUF的宏定义和ARP首部结构,在前面已经讲过。同时注意执行该函数时中断的处理。这里没

作处理。

看上去很easy吧,下面函数实现接收ARP请求或接收ARP应答的处理。

unsigned char arp_process(void)//ARP接收函数,成功返回1,否则返回0

{

//简单判断ARP数据包有无损坏,有损坏则丢弃,不予处理

if( packet_len < 28 )//ARP数据长度为28字节为无效数据

{

return 0;

}

switch ( HON( ARPBUF->opcode ) )

{

   case 0    : //处理ARP请求

         if( ARPBUF->dipaddr[0] == ip_addr[0] &&

             ARPBUF->dipaddr[1] == ip_addr[1] &&

             ARPBUF->dipaddr[2] == ip_addr[2] &&

             ARPBUF->dipaddr[3] == ip_addr[3] )//判断是否是自己的IP,是否向自己询问MAC地址

         {
             ARPBUF->opcode = HON( 2 );//设置为ARP应答

             memcpy(ARPBUF->dmac, ARPBUF->smac, 6);

             memcpy(ARPBUF->ethhdr.d_mac, ARPBUF->smac, 6);

             memcpy(ARPBUF->smac, mac_addr, 6);

             memcpy(ARPBUF->ethhdr.s_mac, mac_addr, 6);

             memcpy(ARPBUF->dipaddr, ARPBUF->sipaddr, 4);

             memcpy(ARPBUF->sipaddr, ip_addr, 4);

             ARPBUF->ethhdr.type = HON( 0x0806 );

             packet_len = 42;

             sendpacket( Buffer, packet_len );//发送ARP数据包

             return 1;

         }

         else

         {

             return 0;

         }

         break;

   case 1    : //处理ARP应答

         if( ARPBUF->dipaddr[0] == ip_addr[0] &&

             ARPBUF->dipaddr[1] == ip_addr[1] &&

             ARPBUF->dipaddr[2] == ip_addr[2] &&

             ARPBUF->dipaddr[3] == ip_addr[3] )//再次判断IP,是否是给自己的应答

         {

          memcpy(host_mac_addr, ARPBUF->smac, 6);//保存服务器MAC地址

          return 1;

         }

         else

         {

             return 0;

         }

         break;

default     ://不是ARP协议

         return 0;

}

}

根据ARP协议格式看这两个函数并不困难。于是我们又得到两个函数:arp_request()和

arp_process()。

    3、ARP程序调试

下面我们修改主函数和中断处理函数。

将mian()函数中的“sendpacket(60);”语句换成“arp_request();”语句。

void int_issue(void) //中断处理函数,需要根据自己的处理器进行设置

{

    unsigned int i;

    i = receivepacket(Buffer);//将数据读取到Buffer中。

    if(i == 0)

    {

        return;

    }

     else

     {

         i = arp_process();

         if(i == 1)//判断是否是ARP协议

             print_hostmacaddr();//打印目标机的MAC地址,就是用串口打印host_mac_addr[]中的6

个字节

     }

}

保存运行调试。 clip_image004

图7 主机MAC地址

至此,关于DM9000的调试过程就完成了。之后我还调试了UDP通讯、TCP通讯等,主要是关于协议的

处理了,这里就不介绍了。有兴趣的朋友可以参看《TCP/IP协议》第一卷,将会有很大帮助。希望这些

调试过程能为读者或多或少的提供些有用的信息,也欢迎大家和我一起讨论。

 

//dm9000.c

 

#include "dm9000.h"
#include "2440lib.h"
#include "string.h"
#include "2440addr.h"

 

unsigned char mac[6]={0x01,0x02,0x03,0x04,0x05,0x06};
U8 buffer[1000];

unsigned char arp[60]=
{
 0x6c,0xf0,0x49,0xc4,0x05,0x5a,
 0x01,0x02,0x03,0x04,0x05,0x06,   //源MAC地址
 0x08,0x06,        //帧类型
 0x00,0x01,        //硬件类型
 0x08,0x00,                         //协议类型
 0x06,          // 硬件地址长度
 0x04,          //协议地址长度
 0x00,0x01,
 0x01,0x02,0x03,0x04,0x05,0x06,   //发送端MAC地址
 59,69,64,200,          //IP
 0x6c,0xf0,0x49,0xc4,0x05,0x5a,
 59,69,64,219        //IP
};

void delay_us(int d)     //1us
{
 int i;
 while(d--)
  for(i=0;i<77;i++);
}


void dm9000_write(unsigned char reg, unsigned char data)
{
    delay_us(20);//之前定义的微妙级延时函数,这里延时20us
    DM_ADD = reg;//将寄存器地址写到INDEX端口
    delay_us(20);
    DM_CMD = data;//将数据写到DATA端口,即写进寄存器
}

unsigned char dm9000_read(unsigned char reg)
{
  delay_us(20);
    DM_ADD = reg;
    delay_us(20);
    return (unsigned char)DM_CMD;//将数据从寄存器中读出
}

U16 dm9000_read16(unsigned char reg)
{
  delay_us(20);
    DM_ADD = reg;
    delay_us(20);
    return (U16)DM_CMD;//将数据从寄存器中读出
}

void dm9000_reset(void)
{
 //  delay_us(40);//之前定义的微妙级延时函数,这里延时20us
    DM_ADD = DM9000_NCR;//将寄存器地址写到INDEX端口
   delay_us(200);
    DM_CMD = NCR_RST;//将数据写到DATA端口,即写进寄存器
 delay_us(200); 
}

void __irq dm9000_int(void)

 if(rINTPND==BIT_EINT4_7)
 {
  ClearPending(BIT_EINT4_7);
  if(rEINTPEND&(1<<7))
  {
   Uart_Printf("DM9000!!!n");
   dm9000_receive(buffer);
  // dm9000_write(DM9000_ISR, 0x01);
   rEINTPEND |= 1<<7; 
  }
 
}

void IOSetInit(void)
{
// rGPFCON = (rGPFCON & (~(0x03<<14))) | (0x02<<14); //GPF7设置为EINT7
 rGPFCON&=~(3<<14);
 rGPFCON|=2<<14;
 rEXTINT0 &= ~(7<<28); 
 rEXTINT0 |= (6<<28); //set eint7 falling edge int

 rEINTPEND |= 1<<7;  //clear eint7
 rEINTMASK &= ~(1<<7); //enable eint11,19
 ClearPending(BIT_EINT4_7);
 pISR_EINT4_7 = (U32)dm9000_int;
 EnableIrq(BIT_EINT4_7);

 

void __irq Key_ISR(void)
{
 if(rINTPND==BIT_EINT8_23)
 {
  ClearPending(BIT_EINT8_23);
  if(rEINTPEND&(1<<8))
  {
   Uart_Printf("eint8n");
   rEINTPEND |= 1<< 8;
  }
 }
}

void keyinit(void)
{
 rGPGCON&=~(3<<0);   //设置引脚
 rGPGCON|=2<<0;    //引脚为EINT8
    rEXTINT1&=~(7<<0);   //设置ENIT8 触发方式
 rEXTINT1|=(2<<0);   //为下降沿触发

 rEINTPEND |= (1<<8);  //写1清除中断标志 1:中断触发
 rEINTMASK &= ~(1<<8);  //允许中断EINT8
 ClearPending(BIT_EINT8_23);
 pISR_EINT8_23 = (U32)Key_ISR;
 EnableIrq(BIT_EINT8_23);
}  

void dm9000_init(void)
{
 int i;
// dm9000_reset();
 IOSetInit();
 dm9000_write(DM9000_GPCR, 0x01); //设置 GPCR(1EH) bit[0]=1,使DM9000的GPIO3为输出。
 dm9000_write(DM9000_GPR, 0x00);  //GPR bit[0]=0 使DM9000的GPIO3输出为低以激活内部PHY。
 delay_us(5000);//延时2ms以上等待PHY上电。
 dm9000_write(DM9000_NCR, 0x03);//软件复位
 delay_us(50);//延时20us以上等待软件复位完成
 dm9000_write(DM9000_NCR, 0x00);//复位完成,设置正常工作模式。
    dm9000_write(DM9000_NCR, 0x03);//第二次软件复位,为了确保软件复位完全成功。此步骤是必要的
    delay_us(50);
    dm9000_write(DM9000_NCR, 0x00);


    dm9000_write(DM9000_NSR, 0x2c);//清除各种状态标志位

    dm9000_write(DM9000_ISR, 0x3f);//清除所有中断标志位


    dm9000_write(DM9000_RCR, 0x39);//接收控制

    dm9000_write(DM9000_TCR, 0x00);//发送控制

    dm9000_write(DM9000_BPTR, 0x3f);

    dm9000_write(DM9000_FCTR, 0x3a);

    dm9000_write(DM9000_FCR, 0xff);  //0x0a接收/发送溢出控制寄存器(RX/TX Flow Control Register)

    dm9000_write(DM9000_SMCR, 0x00);

   for(i=0; i<6; i++)
        dm9000_write(DM9000_PAR + i, mac[i]);//mac_addr[]自己定义一下吧,6个字节的MAC地址  

 

    dm9000_write(DM9000_NSR, 0x2c);

    dm9000_write(DM9000_ISR, 0x3f);

    dm9000_write(DM9000_IMR, 0x81);

}

void dm9000_send(U8 *buffer,U16 length)
{
 int i;
 dm9000_write(DM9000_TXPLH, (length>>8) & 0xff);

    dm9000_write(DM9000_TXPLL, length & 0xff);

 DM_ADD = DM9000_MWCMD;//这里的写法是针对有总线接口的处理器,没有总线接口的处理器要注意加上时序。

    for(i=0; i<length; i+=2)//16 bit mode
    {
        delay_us(20);
        DM_CMD = buffer[i]|(buffer[i+1]<<8);
    }
 dm9000_write(DM9000_TCR, 0x01);   //  设置传送标志位,启动数据发送:
 while((dm9000_read(DM9000_TCR) & 0x01)!=0);//等待数据发送完成  when send completed, TCR bits0 will set to 0
// while((dm9000_read(DM9000_NSR)&0x0c) == 0)                   //check again
    dm9000_write(DM9000_NSR, 0x2c);  //清除状态寄存器,由于发送数据没有设置中断,因此不必处理中断标志位
    dm9000_write(DM9000_IMR, 0x81);  //DM9000网卡的接收中断使能
 delay_us(20);
// Uart_Printf("send!!!n");
}

U16 dm9000_receive(U8 *data)
{
 U16 status=0,len=0,i,tem;
 U8 ready=0;
 if(dm9000_read(DM9000_ISR) & 0x01)
    {
     dm9000_write(DM9000_ISR, 0x01);
    }
 ready = dm9000_read(DM9000_MRCMDX); // 第一次读取,一般读取到的是 00H
 if(ready!=0x01)
 {
  ready = dm9000_read(DM9000_MRCMDX); // 第二次读取
  if(ready!=0x01) //若第二次读取到的不是 01H 或 00H ,则表示没有初始化成功
  {
         dm9000_write(DM9000_IMR, 0x80);//屏幕网卡中断
         dm9000_init();//重新初始化
   dm9000_write(DM9000_IMR, 0x81);//打开网卡中断
   Uart_Printf("Init failed!!n");
   return 0;
  }
 }
 if(ready==0)
  return 0;
 status = dm9000_read16(DM9000_MRCMD);
    delay_us(20);
    len = DM_CMD;
 Uart_Printf("length=:%dn",len);

 for(i=0;i<len;i+=2)
 {
     delay_us(20);
        tem = DM_CMD;
        data[i] = tem & 0x0ff;
        data[i+1] = (tem >>8)&0x0ff;
 }
 Uart_Printf("data:");
 for(i=0;i<len;i++)
  Uart_Printf("%2x ",data[i]); 

 return len;
}

 

void dm9000_arp(void)
{
 dm9000_send(arp,60); 
}

 

void read_reg(void)
{
 int i;
 Uart_Printf("DM9000_NCR:%xn",dm9000_read(DM9000_NCR));
 Uart_Printf("DM9000_NSR:%xn",dm9000_read(DM9000_NSR));
 Uart_Printf("DM9000_TCR:%xn",dm9000_read(DM9000_TCR));
 Uart_Printf("DM9000_RCR:%xn",dm9000_read(DM9000_RCR));
 Uart_Printf("DM9000_RSR:%xn",dm9000_read(DM9000_RSR));
 Uart_Printf("DM9000_BPTR:%xn",dm9000_read(DM9000_BPTR));
 Uart_Printf("DM9000_FCTR:%xn",dm9000_read(DM9000_FCTR));
 Uart_Printf("DM9000_FCR:%xn",dm9000_read(DM9000_FCR));
 Uart_Printf("DM9000_GPCR:%xn",dm9000_read(DM9000_GPCR));
 Uart_Printf("DM9000_IMR:%xn",dm9000_read(DM9000_IMR));
 Uart_Printf("DM9000_PIDL:%xn",dm9000_read(DM9000_PIDL));
 Uart_Printf("DM9000_PIDH:%xn",dm9000_read(DM9000_PIDH));
 Uart_Printf("MAC:");  
 for(i=0;i<6;i++)
  Uart_Printf("%x ",dm9000_read(DM9000_PAR + i)); 
}

 

 

 

这篇关于mini2440nbsp;裸奔dm9000(下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810641

相关文章

不懂搜索引擎原理的seoer们就是在裸奔

站长最长说的一句口头禅就是:不懂SEO搜索引擎事理的seoer就是在裸奔! 按照上图诠释的搜索引擎工作原理,笔者要一步一步为巨匠注释,讲解。进行完整的seo基本常识普及。  1、:我们的互联上网,一个巨年夜的、复杂的系统   2、汇集器:这个我们站长们就都熟悉了,我们对它的俗称也就是蜘蛛,爬虫,而他的工作使命就是访谒页面,抓取页面,并下载页面   德诚承兑汇票营业   3、节制器

stm32f103zet6 DM9000 UCOSII LWIP 快速集成modus tcp

之前使用stm32f103rbt6芯片完成了集成 freemodbus modbus rtu参照:点击打开链接 现使用stm32f103zet6 DM9000 UCOSII LWIP 集成modus tcp,类似于集成modbus rtu 首先参照原子官方提供的战舰V3  UCOSII+LWIP试验 为基础模板 第二:添加modbus 、 port的C文件和H文件,参照 点击打开链接 第三

DM9000驱动时序优化

想了解一下DM9000的移植修改原理,所以分析了一下时序图和引脚连接 首先看一下DM9000的引脚和MINI2440的引脚连接 DM9000  MINI2440 功能描述 SD0   DATA0  数据信号  |           | SD15  DATA15  数据信号 CMD  ADDR2  识别为地址还是数据 INT   EINT7  中断 IOR#   nOE   读命令使能 I

TX2440 ARM开发板Uboot移植(四、对DM9000网卡的支持)

1、在drivers/net/ 目录下有DM9000的驱动代码,在dm9000x.h中对CONFIG_DRIVER_DM9000宏的依赖,dm9000x.c中对CONFIG_DM9000_BASE宏、DM9000_IO宏、DM9000_DATA等宏的依赖,所以首先修改 include/configs/smdk2440.h ,在文件中加入这些宏的定义: /* * Hardware driv

裸奔真的会中木马病毒 挖矿病毒 wup.exe 程序文件占用电脑资源

4日晚上,打开任务管理器的时候发现CPU使用一直在80%,是 wup.exe 占用的,同时还占用了2G内存,低优先级运行,用户名 SYSTEM,很不正常,于是开始排查。 发现这玩意是上午十点左右中的,仔细回想那时段并无敏感操作,也没有程序要权限,大概是通过某些漏洞传播的罢。 具体行为 程序列表里多了个 CloudNet,且难以卸载在C盘创建了 wup 文件夹和伪装的 rss 文件夹(都是隐藏

大数据时代,如何让个人信息不再“裸奔”

大数据时代,海量的信息为市场走向和企业决策充当了风向标的角色,互联网思维标榜的“用户体验”也成了部分人理直气壮窃取客户信息的理由。“杀熟”、数据泄露等各种危害用户信息安全的事件时有发生。个人信息裸奔似乎已经成了无法根治的毒瘤,一个平台的用户信息泄露风波刚过,就会有另一个平台的个人信息被泄露,身为用户,无处可逃。 外卖平台收集饮食偏好和住宅信息…… 网约车会暴露通勤路线和工作信息…… 电商平台

MDK + Jlink + SDRAM 裸奔2440教程

MDK下裸奔2440教程 1、背景 很多人学习嵌入式编程都是从裸机开始的(我个人也是)。这并不是偶然,想要零基础入门嵌入式开发,玩转裸机绝对是最好的入手点。这样至少可以培养以下必备技能: l  CPU体系结构,编程模式及汇编语言、指令结构的知识 l  芯片内部外设,如串口、定时器、LCD、Nandflash等的相关编程知识 l  编程环境(这里主要介绍MDK),调试

ok6410 u-boot-2012.04.01移植五支持DM9000

继ok6410 u-boot-2012.04.01移植四后,开发板基本已支持MLC NAND,但还有一些细节地方修改,这节增加DM9000支持,通过网卡tftp程序到内存,接着通过NAND命令写到NAND,这一过程肯定会遇到很多问题,遇到后再一个个解决。 开发环境: 系统:ubuntu 10.04.4 单板:ok6410 NAND FLASH:K9GAG08U0D 2048MB DDR:K4X1

5分钟搜索120个平台10年数据!监视软件细节曝光:人人“裸奔”,预测警务歧视严重...

来源:大数据文摘本文约3000字,建议阅读5分钟 本文介绍了监事软件的细节,其中预测警务歧视情况十分严重。 在全球各地,警方利用监视软件监视用户,已经成为众人皆知的秘密。 但你可能不知道的是,这些软件不仅观察着你的所有线上活动、分析你的线上数据、绘制你的社交网络,还在这个过程中包含了对个体、种族、性别的歧视。 近日,根据一份密歇根州警察合同,更多鲜为人知的监控软件细节逐渐浮出水面。 据了解

linux网卡DM9000驱动移植-韦东山-专题视频课程

linux网卡DM9000驱动移植—1392人已学习 课程介绍         根据原厂网卡驱动移植DM9000C 课程收益     会根据原厂程序移植驱动 讲师介绍     韦东山 更多讲师课程     2003 年毕业于中国科学技术大学,电子专业、软件专业双学位。近10年嵌入式开发经验,曾ZTE公司负责Linux底层系统开发。 近5年作为特聘讲师在若干个有名