小盒子的小盒

【原创】LWIP-1.2.0+RTL8019+uC/OS-II--理论篇

0
阅读(3531)

最近有些网友,问我有关LWIP+RTL8019+UC/OS-II整体移植的思路和RTL8019的驱动程序该如何添加进去,网上的确有很多资料都是有关RTL8019的驱动程序,可是总有人会把共享出来的程序动动手脚,导致拿来后未必好用。要么你就共享出来好用的,别做手脚,要么你就干脆别拿出来,要不大家用起来是何等的不方便。

这里就奉献一篇有点含量的文章吧,其中有些RTL8019的资料说明,是摘抄自网上,驱动程序和移植在LWIP里面的都是本人的程序,保证好用!

下面开始介绍RTL8019这个以太网芯片:

1.芯片特性
100-pin PQFP
RTL8019AS 软件兼容(软件兼容8 位和16 位的NE2000)
支持pnp 自动检方式(RTL8019AS 唯一的)
支持以太网II 和IEEE802.3 10Base5,10Base2,10BaseT
支持微软jumper 和jumperless 模式的即插即用配置
支持full-duples 以太网到两倍频带宽
支持三种省电模式
――睡眠模式
――内部时钟运行
――内部时钟停止
改善效率的内置数据先取功能
支持UTP,AUI 和BNC 自动检测(RTL8019AS 唯一的)
支持10BaseT 的自动极性改正
支持8 条IRQ 总线
支持16 条I/O 基本地址选项
和额外I/O 地址输入输出完全解码方式(RTL8019AS 唯一的)
支持到BROM 的16k,32k,64k 和16k-page 方式(到256 页有16k 字节/页)
支持BROM 删除程序后释放内存
支持存储器瞬时读写(RTL8019AS 唯一的)
16kSRAM(RTL8019AS 唯一的)
使用9346(64×16-bit EEPROM)存储资源配置和ID 参数
为了制造便利有规划空白9346 的能力
支持可编程输出的4-诊断 LED

2, 芯片概述【以下摘抄自互联网,翻译未必正确】
RTL8019AS 是高度集成以太网控制器,它能够简单的解答即插即用NE2000兼容适配器,这种适配器具有二重和功率下降特性。通过三电平控制特性,RTL8019AS 是已制的对网络设备GREEN PC 理想的选择。全二重功能能够模拟传播和接收在双绞线到全二重以太网交换机。这个特性不仅强带宽从10 到20MBPS,而且避免了由于以太网频道争夺特性导致的读出多路存取协议的问题。微软公司的即插即用功能能减轻用户较差的营业收入而注意适配器资源,如IRQ,输入输出,和存储器地址等等。然而,为了特殊的应用而得不到即插即用功能的兼容性,RTL8019AS 支持JUMPER 和JUMPERLESS 选项。为了提供完全解决即插即用方案,RTL8019AS 在集成10BASET 收发器,
BNC,和AUI 接口之间的自动检测功能。此外,8 条IRQ 总线和16 条基本地址总线为大资源情况下提供了宽松的环境。RTL8019AS 支持16k,32k,和64k 字节BROM 和闪存接口。它仍然提供页面模式功能,这种功能能支持在仅16k 字节内存系统空间下的4M 字节的BROM.此外,BROM 的无用命令被用来释放BROM 内存空间。RTL8019AS 用16k 字节SRAM 设计在单片芯片上,它的设计不仅提供了更多友好的功能,而且节省了SRAM 存储资源。

3.基本寄存器介绍

reg00命令寄存器:CR,command register,地址偏移量00H,为一个字节

PS1和PS0这两个位用来选择寄存器页,PS1 PS0=00时选择寄存器页0,=01时选择寄存器页1, =10时选择寄存器页2,=11时选择寄存器页3.

下面介绍网卡的初始化子程序:

/*
*******************************************************************************
*        InitRS8019
*
*Description: RTL8019AS初始化
*
*Arguments : 无
*    
*
*Returns : 无
*
*Note  : V1.0 by SmallBox at 2006.10.09
*    
*
*******************************************************************************
*/

static void InitRS8019()
{
 int i;

 outportb(0x21, BaseAddr); //使芯片处于停止模式,这时进行寄存器设置
 for(i=0;i<1000;i++);  //延时确保芯片处于停止模式

outportb(RPSTART, Pstart); //接收缓冲器页开始地址--->0x4c
 outportb(RPSTOP, Pstop); //接收缓冲器页面停止地址->0x80 (for 16bit) 0x60 (for 8bit)
 outportb(RPSTART, BNRY); //这个寄存器是用来放置接收缓冲器的重写。它代表性的作用//是作为接收缓冲器 最后页面的指针。

 outportb(SPSTART, TPSR); //用来设置传送数据包开始页面地址-->0x40
 outportb(0xcc, RCR);  // set RCR 0xcc
 outportb(0xe0, TCR);  // set TCR 0xe0
#ifdef RTL8019_OP_16
 outportb(0xc9, DCR);  // set DCR 0xc9, 16bit DMA
#else
 outportb(0xc8, DCR);  // 8bit DMA
#endif
 outportb(0x03, IMR);  // set IMR 0x03
 outportb(0xff, ISR);
 
 SetRegPage(1);
 outportb(RPSTART+1, CURR);
 /*
 outportb(0x00, MAR0);  //windows 98操作系统里,操作系统写入到这8个寄存器的值
 outportb(0x41, MAR1);
 outportb(0x00, MAR2);
 outportb(0x80, MAR3);
 outportb(0x00, MAR4);
 outportb(0x00, MAR5);
 outportb(0x00, MAR6);
 outportb(0x00, MAR7);
 */

/*
 outportb(0xff, MAR0);  //可以接收所有的组播地址地数据包
 outportb(0xff, MAR1);
 outportb(0xff, MAR2);
 outportb(0xff, MAR3);
 outportb(0xff, MAR4);
 outportb(0xff, MAR5);
 outportb(0xff, MAR6);
 outportb(0xff, MAR7);
 */
 
 outportb(0x00, MAR0);  //不接收任何组播地址的数据包
 outportb(0x00, MAR1);
 outportb(0x00, MAR2);
 outportb(0x00, MAR3);
 outportb(0x00, MAR4);
 outportb(0x00, MAR5);
 outportb(0x00, MAR6);
 outportb(0x00, MAR7);
 
 outportb(0x22, BaseAddr); // set page 0 and start
  rBNRY = RPSTART;
}

PSTART 接收缓冲区的起始页的地址。

PSTOP 接收缓冲区的结束页地址。(该页不用于接收)

BNRY 指向最后一个已经读取的页(读指针)

CURR 当前的接收结束页地址。(写指针)

--网卡含有16K字节的RAM,地址为0x4000-0x7fff(指的是网卡上的存储地址,而不是ISA总线的地址,是网卡工作用的存储器),每256个字节称为一页,共有64页。页的地址就是地址的高8位,页地址为0x40--0x7f 。这16k的ram的一部分用来存放接收的数据包,一部分用来存储待发送的数据包。当然也可以给用户使用。(例如把网卡设置成使用8K的ram,另外8K的ram就可以用来给单片机作为存储器,但我没有这样做,原因是操作网卡上的ram比较复杂)

---在我的程序中使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。使用0x4c-0x7f为网卡的接收缓冲区,共52页。因此PSTART=0x4c,PSTOP=0x80(0x80为停止页,就是直到0x7f,是接收缓冲区,不包括0x80) 刚开始,网卡没有接收到任何数据包,所以,BNRY设置为指向第一个接收缓冲区的页0x4c)

这四个寄存器用于接收的设置。

--CURR是网卡写内存的指针。它指向当前正在写的页的下一页。那么初始化它就应该指向0x4c+1=0x4d 。网卡写完接收缓冲区一页,就将这个页地址加一,CURR=CURR+1。这是网卡自动加的。当加到最后的空页(这里是0x80,PSTOP)时,将CURR置为接收缓冲区的第一页(这里是0x4c,PSTART),也是网卡自动完成的。当CURR=BNRY时,表示缓冲区全部被存满,数据没有被用户读走,这时网卡将停止往内存写数据,新收到的数据包将被丢弃不要,而不覆盖旧的数据。此时实际上出现了内存溢出。

--而BNRR要由用户来操作。用户从网卡读走一页数据,要将BNRY加一,然后再写到BNRY寄存器。 当BNRY加到最后的空页(0x80,PSTOP)时,同样要将BNRY变成第一个接收页(PSTART,0x4c)BNRY=0x4c;

--CURR和BNRY主要用来控制缓冲区的存取过程,保证能顺次写入和读出)。当CURR=BNRY+1(或当BNRY=0x7f ,CURR=0x4c)时,网卡的接收缓冲区里没有数据,表示没有收到数据包。 用户通过这个判断知道没有包可以读。当上述条件不成立时,表示接收到新的数据包。然后用户应该读取数据包,直到上述条件成立时,表示所以数据包已经读完,此时停止读取数据包。

--TPSR 为发送页的起始页地址。初始化为指向第一个发送缓冲区的页,0x40。

--RCR 接收配置寄存器,设置为使用接收缓冲区,仅接收自己的地址的数据包(以及广播地址数据包)和多点播送地址包,小于64字节的包丢弃(这是协议的规定,设置成接收是用于网络分析),校验错的数据包不接收。

--TCR 发送配置寄存器,启用crc自动生成和自动校验,工作在正常模式。

--DCR 数据配置寄存器,设置为使用FIFO缓存,普通模式,8位数据传输模式,字节顺序为高位字节在前,低位字节在后(符合我们的习惯)(如果用16位的单片机,设置成16位的数据总线操作会更快,但80c52是8位总线的单片机)

--IMR 中断屏蔽寄存器,设置成0x00,屏蔽所有的中断。设置成0xff将允许中断)

--MAR0~MAR8是设置多点播送的参数,这点我也不是很清楚,我从电脑读出来是什么数,我也将这8个寄存器设置成这几个数. 由于我们不使用多点播送,所以不要紧,只要保证网卡能正常工作就可以了。

--PAGE2的寄存器是只读的,所以不可以设置,不用设置,PAGE3的寄存器不是NE2000兼容的,所以也不用设置。

4.PAR0-5寄存器

物理地址寄存器,位于page1,共6个字节,这就是网卡的地址,复位之后该6个寄存器的值是不定的。

要由用户将网卡地址写入到该6个寄存器中,以后网卡接收到的数据包,会将数据包的目的地址跟这6个寄存器的值进行比较,结果相同的数据包被接收下来。上电复位时从93c46读入的网卡地址不会自动写入到这里,而是放在rtl8019as的内存地址0000H,0002H,0004H,0006H,0008H,000AH,0000CH里。你的程序要从这6个内存地址里读出网卡地址,写入到PAR0-5 共6个寄存器地址里。如果你的系统没有使用93c46来存储该网卡地址,那么要由你的软件自行产生或分配一个网卡地址,写入到6个寄存器里(比如你可以把网卡地址存储在单片机的flash rom里,存储在24c02的eeprom里等)。

5.MAR0-7

为8个寄存器,提供对组播地址的过滤。跟crc的逻辑有关。我对于该8个寄存器跟组播地址的关系不是很清楚,也没有找到相关的资料。将该8个寄存器全部写入0FFH,可以接收所有的组播地址地数据包。全部写入0,将不接收任何组播地址的数据包。在windows 98操作系统里,操作系统写入到这8个寄存器的值为:

MAR0 :00H

MAR1 :41H

MAR2 :00H

MAR3 :80H

MAR4 :00H

MAR5 :00H

MAR6 :00H

MAR7 :00H

写入的这8个值跟具体的组播地址是什么关系?我也不知道。lphard的方案是写入8个0xff 。那么在嵌入式应用中应该如何处理?建议为全部写入0xff。如果不想支持组播,可以不用理这8个寄存器,或全部写入0。

6.TCR寄存器

其中的第3位ATD,0为正常操作,1为由组播地址控制(用作流控)。我们把这个位设置为0。我们不需要使用流控,因为流控的标准不被所有的网卡支持,有些网卡支持,有些不支持。

7.RCR寄存器

其中的PRO,AM,AB跟地址有关:

PRO为1时,将接收所有的数据包,不管任何地址, 统统收下来。通常用在一些网桥,或一些用来监视网络的电脑里。sniffer软件就是利用这个特性,将以太网上所有数据包都收下来进行分析,以统计以太网里的数据传输率,冲突,出错情况,网卡地址情况,ip数据包等情况。

PRO为0时,接收跟自己的地址一样的数据包,其他目的地址的被丢弃(不包括广播和组播包)。我们设置为0就可以了。

AM=1时,接收组播地址的数据包,AM=0时,不接收组播地址的数据包。 将该位根据你的情况设置为1或0,推荐设置为1。

AB=1时,接收广播地址的数据包,AB=0时,不接收广播地址FF:FF:FF:FF:FF:FF的数据包。该位要设置为1,才能实现tcp/ip协议