buf

BE something YOU love and understand
posts - 94, comments - 35, trackbacks - 0, articles - 2
   :: 首页 :: 新随笔 :: 联系 ::  :: 管理

S3C44B0+U-Boot调试RTL8019AS经验小结

Posted on 2008-11-01 23:09 buf 阅读(4379) 评论(8)  编辑 收藏 引用 所属分类: Embedded
直到我看了NI DP8390D的芯片手册,我才意识到RTL8019的文档有多滥。有了DP8390的Datasheet,调试U-Boot的RTL8019就不是那么困难的事情了。更何况U-Boot中的以太网工作在较为简单的查询模式,更何况还有Writing Drivers for the DP8390 NIC Family of Ethernet Controllers一文提供了实践指导。

发现一点小问题就是,U-Boot(v1.1.1)中ping命令会过快地超时,远远不到代码中定义的超时常数T。按照我的理解udelay(ulong usec)正常工作,Timer1的输入时钟频率F应为125KHz,而检查是否超时时是按照 F = 1KHz 计算的。于是调整 T = T * 125,超时检查正常。

- 2008年11月03日 -
今天在debian etch上把tftp server也配置好了,然后在板子上运行tftp client简单测试了一下,没有问题。或许是添加了许多调试输出的关系,感觉网络传输速度并不是很快,不过无所谓了。

- 2008年11月04日 -
今天去掉调试输出再来测试网络,tftp下载编译好的u-boot.bin,130K的文件几乎瞬间完成,看来调试这个驱动还是有意义的。回忆起最初在Windows下用HyperTerminal下载,那简直是龟速。。。不过,kermit下要快得多,以太网自然更快 :-)



本例中的ARM7开发板带有以太网接口,芯片选用RealTek RTL8019AS(以下简称为8019)。8019遵循Ethernet IIIEEE802.3规范,数据总线8/16位可选,软件兼容NE2000,内置16KB SRAM

概括的说,NIC的工作流程很简单。向网络发送数据时,CPU将数据按指定的格式写入NIC内置RAM,然后启动发送命令;NIC接收到网络数据时,将收到的数据写入内置RAM,完成一帧数据接收后向CPU提交一个中断请求,等待中断服务例程进行数据处理。

8019支持三种模式:JumperPnPRT Jumpless。在Jumper模式下,网卡的I/O地址和中断由跳线决定;而使用非Jumper模式时,还需要一片EEPROM(如93C46)来存储网卡的配置信息。这些信息将在上电时加载到8019的内置RAM或相关寄存器中。本例中8019工作在Jumper模式。

8019接口电路基本情况:Jumper模式,数据宽度=16位,基址=0x06000300
SA[4:0]               
连接到CPUADDR[5:1]SA[9:8]VDD,其余地址线接
GND
SD[15:0]            
连接到CPU
DATA[15:0]
Pin34 AEN        
连接到CPU
nGCS3
Pin65 JP            
10K ohm
VDD
Pin96 SLOT16  
300 ohm
VDD
由于U-Boot中网卡驱动没有使用中断,所以中断信号线的连接情况在这里暂不考虑。

寄存器和内置RAM是网卡功能实现的载体,驱动程序也是通过对它们的操作完成CPU所指令的任务。驱动程序所涉及的寄存器主要在Page0Page1,在开始驱动的调试之前,最好对这部分的寄存器已经比较熟悉了。至于内置RAM,在Jumper模式下我们只需要关心其收发缓存部分。偏移地址从0x4000开始至0x7FFF16KB RAM区域构成8019的收发缓存,它以256字节为单位划分为64(Page),页地址为0x40 ~ 0x7F,发送和接收缓存所分配的页数可以由驱动程序设定。一种比较常见的分配方式为[0x40,0x4C)用作发送,[0x4C,0x80)用作接收,这也是本例所采用的配置。

在对网卡芯片的工作流程有了一个感性的认识,并确定硬件电路的接口情况后,我们就可以进入驱动程序部分了。8019驱动程序需要向U-Boot提供下列函数:
eth_reset                   
芯片复位
rtl8019_get_addr     
读芯片MAC,在Jumper模式下这个函数实际可以去掉
eth_init                      
芯片初始化
eth_send                   
发送
eth_rx                        
接收,需调用nic_to_pc
eth_halt              
芯片停机

eth_reset (void)
这个函数比较简单,读复位端口或向其写入任意数据均可引起芯片的软复位。进入复位状态后ISRBit7被置1,发起复位操作后应检查该标志位确保复位完成。向该标志位写入1(而不是0)以清除标志。

rtl8019_get_addr (uchar * addr)
该函数读取偏移地址从0x0000开始的12字节,用以初始化gd->bd-> bi_enetaddrU-Boot使用。从前面的内置RAM Mapping我们知道这部分内容是从外部的EEPROM加载的,而本例中8019工作在Jumper模式,并没有使用EEPROM存储配置信息,因此这部分的内容都为0x00。修改后的代码对从内置RAM读出的MAC进行了验证,若为全0,则使用环境变量中定义的MAC;否则更新环境变量中定义的MAC。需要注意的是,网卡最终所使用的MAC是保存在Page1寄存器组的PAR5~PAR0的,gd->bd->bi_enetaddr指向的6字节数据会在网卡初始化时写入这些寄存器。

eth_init (bd_t * bd)
8019
的初始化按照DP8390D芯片手册第11Initialization Procedures列出的步骤进行。BNRY初始化为0x4C(和PSTART相同),CURR初始化为0x4D,关于这两个寄存器的操作会在eth_rx函数中说明。

eth_send (volatile void *packet, int length)
将从packet开始的length长度的数据发送到网络上。软件流程也比较简单,将数据通过Remote DMA写入8019的发送缓冲区,然后启动发送命令就可以了。8019 Datasheet 中指出发送数据时RD[2:0]=011b,因此发送命令应为向CR写入0x3E。而在NE2000系的驱动程序中,发送命令为向CR写入0x26。测试中这两种方法都是可以的,不过考虑到兼容其它NE2000系的网卡,我觉得还是使用0x26比较好。注意若数据包长度小于60字节,驱动程序要负责对数据部分进行填充。

eth_rx (void)
U-Boot
中的网络部分没有使用中断,而是使用了查询的工作方式。发起网络操作后,程序的执行由eth_rx和超时检查函数来驱动。8019在接收到来自网络的数据后会将ISRPRX位置1eth_rx检查该标志位,若为1则调用nic_to_pcnic_to_pc需要做的是将芯片缓存下来的数据读入系统内存,并调用NetReceive将读到数据交上层处理。U-Boot循环调用eth_rx和超时检查函数,直到网络操作成功完成,或是操作超时退出。

下面我们来详细看一下网卡接收缓冲区的操作。这里涉及到四个寄存器:PSTARTPSTOPBNRYCURR[PSTART, PSTOP)标记着整个接收缓冲区的范围,网卡不断地将接收到的数据包写入并通知CPU,而CPU则从这里读出数据进行处理。如何保证CPU尚未读取的页面不被网卡写入呢?这就需要用到CURRBNRY这两个寄存器了。网卡接收到的下一个数据包将写入从CURR开始的页面,接收完成后由芯片硬件逻辑自动更新CURR,使其指向下一个可用的页面。BNRY用来标记CPU已读的最末页,驱动程序每次读出数据后,都要负责更新此寄存器。初始化时BNRY=PSTARTCURR=PSTART+1

为了方便驱动程序的设计,NE2000系的网卡为每一个接收到的数据包自动添加了一个4字节的头部,一并写入接收缓存中。status标记着数据包的接收状态,npr标记着下一个数据包的开始页,packet length标记着头部和随后数据包的总长度。有了这些信息,驱动程序读取网络数据就很方便了。完成一次读操作后,驱动程序使用npr – 1 更新BNRY,直到BNRY+1CURR相等为止。

eth_halt (void)
芯片停机,CRSTP位置1即可。或许在此之前检查一下接收缓存是不是空的。

源码下载

参考资料

1. RTL8019AS Datasheet
2. DP8390D Datasheet
3. Writing Drivers for the DP8390 NIC Family of Ethernet Controllers
4. AX88796B Datasheet
5. NE2000
网卡芯片驱动程序,by 杨屹

Feedback

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2008-12-13 23:15 by nandl
真是救命啊,跳了半天调不出来,在这里找到救星了。

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2008-12-13 23:17 by nandl
我的msn nandl_0916@hotmail.com 如不嫌弃菜鸟,希望希望一起进步

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2008-12-16 18:46 by buf
@nandl
我后来发现u-boot里有ne2000兼容网卡的驱动,不过没有细看

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2008-12-26 22:52 by gougou
#define ADDR_SFT 1


#define RTL8019_REG_00 (RTL8019_BASE + (0x00<<ADDR_SFT))
buf你好,看了你的源代码,不明白为什么要有#define ADDR_SFT 1 ,能说一下吗?

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2008-12-27 20:00 by buf
@gougou
我的目标板上网卡和CPU是16位接口的,地址线有错位(CPU的A1连接到网卡芯片的A0),所以编程的时候需要移位调整。

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2009-01-05 11:15 by feillow
多谢提供,正需要这方面资料

# re: S3C44B0+U-Boot调试RTL8019AS经验小结  回复  更多评论   

2009-04-28 16:44 by arm菜鸟
果如所言,我看RTL8019AS的datasheet是云里雾里,当时看别人用uclinux里8390来代替8019,还不知道是哪个厂家的,没有细究,以为应该还有一份文档来详细解释8019,多谢,我下个文中提的两个文档,仔细研究下

# re: S3C44B0+U-Boot调试RTL8019AS经验小结[未登录]  回复  更多评论   

2013-08-08 14:52 by yang
基址=0x06000300如何计算
只有注册用户登录后才能发表评论。