打印
[ZLG-ARM]

请教ZLG/IP驱动程序中Rec_Packet()的疑问

[复制链接]
2324|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mydearm|  楼主 | 2008-1-22 19:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在Rec_Packet()中有一段程序:
    if(bnry!=curr)    //此时表示有新的数据包在缓冲区里
       {            //在任何操作都最好返回page0
        if(REC_BUFF_NUM==MAX_REC_BUFF)//接收缓冲区号清零
        {
            REC_BUFF_NUM=0;
        }
        REC_BUFF_PTR_WORDS=REC_BUFF[REC_BUFF_NUM].words;//设定接收缓冲区的起始地址
        //=======================================
        
        WriteToNet(0x09,bnry);    //RSAR1写入读页地址的高字节
        WriteToNet(0x08,0x00); //RSAR0写入读页地址的低字节
        WriteToNet(0x0b,0x00);    //RSCR1写入读取字节计数高字节
        WriteToNet(0x0a,18);   //RSCR0写入读取字节计数高字节
        WriteToNet(0x00,0x0a); //启动Remote DMA读操作
        //读取一包的前4个字节:4字节的8019头部
        for(i=0;i<2;i++)
        {
            *REC_BUFF_PTR_WORDS=ReadFromNet(0x10);
            tmp=*REC_BUFF_PTR_WORDS;
            REC_BUFF_PTR_WORDS++;
        }
上面程序中在读取包的前4个字节前对RSCR1和RSCR0的设置分别是WriteToNet(0x0b,0x00);  WriteToNet(0x0a,18);   我的疑问是:既然接下来的程序是读取包的前4个字节,那么对RSCR0设置应该是WriteToNet(0x0a,4);但程序为什么是设的18呢?我怎么也想不通.想请教一下各位大侠!万分感谢啦!

相关帖子

沙发
mydearm|  楼主 | 2008-1-23 09:07 | 只看该作者

求救啊!

自己顶一下!

使用特权

评论回复
板凳
sunny_jgp| | 2008-1-23 10:00 | 只看该作者

RE

我也并到过,改成WriteToNet(0x0a,4);也没问题哦

使用特权

评论回复
地板
mydearm|  楼主 | 2008-1-23 10:03 | 只看该作者

谢谢sunny_jgp !

哦,是这样的吗?呵呵,看来我的理解没错啊!谢谢!

使用特权

评论回复
5
sunny_jgp| | 2008-1-23 10:06 | 只看该作者

LZ

LZ,你用的是SMARTARM2200吗,你可否把你的光盘里的SMART2200_ISP1161A的驱动(电脑端的)和USB_I2C.EXE的发到我信箱吗;uye123456@yahoo.com.cn

使用特权

评论回复
6
mydearm|  楼主 | 2008-1-23 10:22 | 只看该作者

re:sunny_jgp

不好意思,我用的是EASYARM2200

使用特权

评论回复
7
sunny_jgp| | 2008-1-23 10:25 | 只看该作者

lz

那也谢谢你

使用特权

评论回复
8
mydearm|  楼主 | 2008-1-23 10:49 | 只看该作者

再请教一个问题!

我还有一个关于Rec_Packet()疑问:
Rec_Packet()中有一段程序:
 
else//表示数据包是完好的.读取剩下的数据
        {
            WriteToNet(0x09,bnry);       //RSAR1写入读页地址的高字节//read page address high
            WriteToNet(0x08,4);          //RSAR0写入读页地址的低字节//read page address low
                 WriteToNet(0x0b,tmp[1]>>8&0x00ff);         //RSCR1写入读取字节计数高字节//read count high
            WriteToNet(0x0a,tmp[1]);    //RSCR0写入读取字节计数低字节//read count low;
            
            WriteToNet(0x00,0x0a);     //启动Remote DMA读操作
            //read dma
            
            length=tmp[1];//计算出要读取的帧的长度
            
            for(ii=0;ii<((length+1)/2);ii++)
            {
                *REC_BUFF_PTR_WORDS=ReadFromNet(0x10);
                REC_BUFF_PTR_WORDS++;
            }
            
其中:我对于for(ii=0;ii<((length+1)/2);ii++)的理解是:由于是16位总线,故只要读(length+1)/2次就可以整个数据包读完,但当包的长度是奇数(即length为奇数),就会多读的一个字节.那多读的一个字节如何处理呢????????????????请教各位大侠!万分感谢啦!                        

使用特权

评论回复
9
mydearm|  楼主 | 2008-1-23 14:09 | 只看该作者

帮忙啊!

自己再顶一下!

使用特权

评论回复
10
我是火光| | 2008-1-23 20:28 | 只看该作者

这个DEMO程序,,,


  这个DEMO程序,,,有许多多余的成分,你需要精简一把!
  

使用特权

评论回复
11
我是火光| | 2008-1-23 20:52 | 只看该作者

我改进过的RTL8019AS部分,你可以看看

#include "config.h"
#include "LPC2294.h"
#include "general.h"

#define    INT_N            0x00000080
#define    NET_RST           0x00000040
#define    NET_BASE_ADDR   0x83400000

//{0x52,0x54,0x4c,0x19,0xf7,0x42}

#define    The_PAR0        0x52
#define    The_PAR1        0x54
#define    The_PAR2        0x4C
#define    The_PAR3        0x19
#define    The_PAR4        0xF7
#define    The_PAR5        0x42

uint8    Tx_Buff_Page    = 0x46;

void WriteToNet(uint8 ADDR_16, uint16 WRITEDATA)
{
    (*((volatile unsigned short *)NET_BASE_ADDR + ADDR_16)) = WRITEDATA;    //0x83400000
    
    return;    
}

uint16 ReadFromNet(uint8 ADDR_16)
{
    uint16 temp_uint16;

    temp_uint16    = (*((volatile unsigned short *)NET_BASE_ADDR + ADDR_16));    //0x83400000

    return    temp_uint16;
}

void SetPage(uint8 pagenumber)  
{
    uint8 temp_uint8;

    temp_uint8    = ReadFromNet(0);        //command register
    temp_uint8    = temp_uint8 & 0x3B;    //注意txp位不能要
    pagenumber    = pagenumber << 6;
    temp_uint8    = temp_uint8 | pagenumber;
    WriteToNet(0, temp_uint8);

    return;
}

void InitNic(void)  
{
    int    temp_i;
    
    PINSEL0    = PINSEL0 & ~0x0000F000;
    IO0DIR    = (IO0DIR & ~INT_N) | NET_RST;
    
    IO0CLR    = NET_RST;
    for (temp_i = 0; temp_i < 40000; temp_i++);

    IO0SET    = NET_RST;
    for (temp_i = 0; temp_i < 40000; temp_i++);

    IO0CLR    = NET_RST;
    for (temp_i = 0; temp_i < 40000; temp_i++);

    //WriteToNet(0x1F, 0x00);     
    //for (temp_i = 0; temp_i < 40000; temp_i++);
    
    WriteToNet(0x00, 0x21);                                //使芯片处于停止模式,这时进行寄存器设置    
    for (temp_i = 0; temp_i < 40000; temp_i++);

    SetPage(0);
    /////////////////////////////////////////////
    WriteToNet(0x0F, 0x00);
    WriteToNet(0x07, 0xFF);
    ///////////////////////////////////
    WriteToNet(0x0E, 0xCB);                                //DCR ???
    WriteToNet(0x0C, 0xE0);                                //RCR ???
    WriteToNet(0x0D, 0xE0);                                //TCR ???
    ///////////////////////////////////
    WriteToNet(0x01, 0x4C);
    WriteToNet(0x02, 0x80);
    WriteToNet(0x03, 0x4C);

    WriteToNet(0x09, 0x40);
    WriteToNet(0x08, 0x00);
    WriteToNet(0x0B, 0x00);
    WriteToNet(0x0A, 0x00);

    WriteToNet(0x04, 0x40);
    WriteToNet(0x06, 0x00);
    WriteToNet(0x05, 0x00);
    /////////////////////////////////////////////
    SetPage(1);
    /////////////////////////////////////////////
    WriteToNet(0x07, 0x4D);
    ///////////////////////////////////
    WriteToNet(0x01, The_PAR0);
    WriteToNet(0x02, The_PAR1);
    WriteToNet(0x03, The_PAR2);
    WriteToNet(0x04, The_PAR3);
    WriteToNet(0x05, The_PAR4);
    WriteToNet(0x06, The_PAR5);
    ///////////////////////////////////
    WriteToNet(0x08, 0x00);
    WriteToNet(0x09, 0x00);
    WriteToNet(0x0A, 0x00);
    WriteToNet(0x0B, 0x00);
    WriteToNet(0x0C, 0x00);
    WriteToNet(0x0D, 0x00);
    WriteToNet(0x0E, 0x00);
    WriteToNet(0x0F, 0x00);
    /////////////////////////////////////////////
    SetPage(0);
    WriteToNet(0x0C, 0xC4);                                //RCR ???
    WriteToNet(0x07, 0xFF);
    WriteToNet(0x00, 0x22);

    Tx_Buff_Page    = 0x46;

    return;                
}

void Send_Packet(uint16 * buf, uint32 len)  
{
    uint32    temp_len;
    int        temp_i, temp_j;

    if (len < 60)
        len = 60;
    if (len & 1)
        len++;
    temp_len = len >> 1;
    if (Tx_Buff_Page == 0x40)
        Tx_Buff_Page =  0x46;
    else
        Tx_Buff_Page =  0x40;

    SetPage(0);                                //切换至第0页

    WriteToNet(0x09, Tx_Buff_Page);            //设置发送页地址    
    WriteToNet(0x08, 0x00);                 //写入RSAR0
    WriteToNet(0x0b, len >> 8);                //写入RSCR1
    WriteToNet(0x0a, len & 0xFF);            //写入RSCR0
    WriteToNet(0x00, 0x12);                    //启动DMA写write dma, page0

    for (temp_i = 0; temp_i < temp_len; temp_i++)
        WriteToNet(0x10, *buf++);
    
    WriteToNet(0x0b, 0x00); 
    WriteToNet(0x0a, 0x00);
    WriteToNet(0x00, 0x22);                    //结束或放弃DMA操作
    
    WriteToNet(0x04, Tx_Buff_Page);            //txd packet start;    
    WriteToNet(0x06, len >> 8);                //high byte counter
    WriteToNet(0x05, len & 0xFF);            //low byte counter

    WriteToNet(0x07, 0xFF);
    WriteToNet(0x00, 0x3E);                    //to sendpacket;
    
    for (temp_i = 0; temp_i < 6; temp_i++)            //最多重发6次
    {
        for (temp_j = 0; temp_j < 1000; temp_j++)
        {
            if ((ReadFromNet(0) & 0x04) == 0)        //检查CR寄存器的txp位是否为低,为1说明正在发送,为0说明发完或出错放弃 
                break;
        }

        if (ReadFromNet(0x04) & 0x01)                //表示发送成功,判断发送状态寄存器TSR,决定是否出错
            break;

        WriteToNet(0x00,0x3E);                        //to sendpacket;
    }
    
    WriteToNet(0x07, 0xFF);
    
    return;
}

int    Rec_Packet(uint16 * buf) 
{
    uint8    temp_BNRY, temp_CURR;
    uint16    temp_buf0, temp_buf1;
    uint32    temp_len;
    uint8    temp_uint8;
    int        temp_i;

    SetPage(0);
    
    /*
    temp_uint8    = ReadFromNet(0x07);                //读取中断状态
    if (temp_uint8 & 0xAC)
    {
        InitNic();
        return -1;
    }
    */

    temp_BNRY    = ReadFromNet(0x03);                //bnry page have read 读页指针
    SetPage(1);
    temp_CURR    = ReadFromNet(0x07);                //curr writepoint 8019写页指针
    SetPage(0);

    temp_BNRY++;                                    //bnry++;
    if (temp_BNRY > 0x7F)
        temp_BNRY = 0x4C;
    
    if (temp_BNRY != temp_CURR)                        //此时表示有新的数据包在缓冲区里
       {
        WriteToNet(0x09, temp_BNRY);                //RSAR1写入读页地址的高字节
        WriteToNet(0x08, 0x00);                        //RSAR0写入读页地址的低字节
        WriteToNet(0x0b, 0x00);                        //RSCR1写入读取字节计数高字节
        WriteToNet(0x0a, 0x04);                        //RSCR0写入读取字节计数低字节
        WriteToNet(0x00, 0x0a);                        //启动Remote DMA读操作

        temp_buf0    = ReadFromNet(0x10);
        temp_buf1    = ReadFromNet(0x10);

        WriteToNet(0x0b,0x00);                        //RSCR1写入读取字节计数高字节
        WriteToNet(0x0a,0x00);                        //RSCR0写入读取字节计数高字节
        WriteToNet(0x00,0x22);                        //结束或放弃DMA操作

        temp_buf1    = temp_buf1 - 4;
        if (((temp_buf0 & 0x0001) == 0) || 
            ((temp_buf0 & 0xFF00) <  0x4C00) ||
            ((temp_buf0 & 0xFF00) >  0x7F00) ||
            ( temp_buf1 > 0x0600))
        {
            SetPage(1);
            temp_CURR    = ReadFromNet(0x07);        //page1读取CURR的值
            SetPage(0);                                //切换回page0
            temp_BNRY    = temp_CURR - 1;            //把bnry恢复为下16K中的空余部分
            if (temp_BNRY < 0x4C) 
                temp_BNRY = 0x7F;
            WriteToNet(0x03, temp_BNRY);            //把BNRY恢复到指向下一帧write to bnry        
            WriteToNet(0x07, 0xFF);                    //清除中断标志

            return -1;
        }
        else                                        //表示数据包是完好的.读取剩下的数据
        {
            WriteToNet(0x09, temp_BNRY);            //RSAR1写入读页地址的高字节//read page address high
            WriteToNet(0x08, 0x04);                    //RSAR0写入读页地址的低字节//read page address low
            WriteToNet(0x0b, temp_buf1 >> 8);        //RSCR1写入读取字节计数高字节//read count high
            WriteToNet(0x0a, temp_buf1 &  0xFF);    //RSCR0写入读取字节计数低字节//read count low;
            WriteToNet(0x00, 0x0a);                    //启动Remote DMA读操作
            
            temp_len    = temp_buf1 / 2;
            for (temp_i = 0; temp_i < temp_len; temp_i++)
                *buf++    = ReadFromNet(0x10);

            WriteToNet(0x0b,0x00);                    //RSCR1写入读取字节计数高字节//read count high   
            WriteToNet(0x0a,0x00);                    //RSCR0写入读取字节计数高字节//read count low;
            WriteToNet(0x00,0x22);                    //结束或放弃DMA操作//结束或放弃DMA

            temp_BNRY    = (temp_buf0 >> 8) - 1;
            if (temp_BNRY < 0x4C)
                temp_BNRY = 0x7F;
            WriteToNet(0x03, temp_BNRY);
            WriteToNet(0x07, 0xFF);

            return temp_buf1;
        }
    }
    else
        return 0;
}

使用特权

评论回复
12
mydearm|  楼主 | 2008-1-24 09:51 | 只看该作者

谢谢"我是火光"分享的改写程序!

看了您改写的程序,我还是有点疑问:
1.在您改写的Rec_Packet()中,读取数据的一段程序是:
temp_len    = temp_buf1 / 2;
for (temp_i = 0; temp_i < temp_len; temp_i++)
*buf++    = ReadFromNet(0x10);
我的疑问是:当temp_buf1 为奇数时,就会少读取一个字节啊!
您后面的程序: temp_BNRY    = (temp_buf0 >> 8) - 1;即把当前的CURR-1赋给BNRY.那么就彻底跳过了少读的那个字节了!
您改写的程序仍然没有解决temp_buf1 为奇数的问题!

2.在您改写的Rec_Packet()中的开始部分省略了对CURR==0的检查!能省略吗?我觉得对CURR==0的检查好象没什么用.即使不能省略,检查CURR也应该是:if(CURR<0x4c);而不应该是if(CURR==0);

3.在您改写的Rec_Packet()中省略了"读取中断状态"的程序!能省略吗?我觉得不应该省吧!

使用特权

评论回复
13
我是火光| | 2008-1-24 19:15 | 只看该作者

呵呵,你说的有道理!!!


呵呵,你说的有道理!!!
实际上啊,我内心就是假设收到的就是偶数个数据的,,,
这里的代码的确是有点问题...

我现在觉得最大的困难就是:周公的资料上对RTL8019AS的控制状态寄存器的描述不够详细...

CR
ISR
DCR
RCR
TCR
RSR
TSR

这几个寄存器中有若干位的意义很模糊...
实在是苦恼的很

当然了,周公的公司不是专门生产RTL8019AS的厂家,本来是没有义务来回答有关RTL8019AS的疑问的.

但我想,如果以周公公司的身份,去向台湾公司索取RTL8019AS的使用方面的更详细资料,是完全能够实现的...

如果能有CR、ISR、DCR、RCR、TCR、RSR、TSR的详细资料,那么编写该类型的网络驱动就易如翻掌了,完全能够写出优美的中断方式的RTL8019AS驱动程序了。。。





使用特权

评论回复
14
我是火光| | 2008-1-24 19:21 | 只看该作者

你的疑问,我编写程序的时候就想到了


你的疑问,我编写程序的时候就想到了,,,
最根本的困难就是没有准确的RTL8019AS的资料,,,许多意义是我自己猜测出来的。。。

如果有资料,,,这些问题完全能够解决的,,,关键的是现在没有资料。。。

使用特权

评论回复
15
mydearm|  楼主 | 2008-1-25 10:10 | 只看该作者

完全同意"我是火光"!

是啊!关于8019资料确实不太详细!我看周公的<<基础教程>>和实验教程(一),好多地方也是写得很简略(仅仅是翻译一下).买了EASYARM2200的板子作实验,只要按步骤:添加工程-->编译-->LOAD-->RUN,就可以完成实验!实验原理的介绍和实验源程序的注释很简略.常常感觉到:作完了实验但还不知道其所以然!就向在玩傻瓜相机!我现在在作UDP和TCP的实验,实验教程(一)上的介绍太简单了!况且周公还说"这些程序只是剪裁版,错误在所难免!完整版是要收费的!"所以要搞清楚实验源程序实在太伤神了!我想要是各位民间大侠把自己对ZLG/IP程序的理解和看法拿出来讨论一下,或许能完善现在的版本(剪裁版),让使用ZLG/IP的人少走一些弯路!^_^

使用特权

评论回复
16
wlq_9| | 2008-1-25 11:29 | 只看该作者

现在

的ISA接口的以太网芯片,RTL8019已经比较悬乎了.现在大家主要用的还是CS8900,DM9000.8019因为供货的问题,已经不在采购之列.
ZLG/IP本身只是个demo,如果真要打算学习tcp/ip的话,还是建议学习lwip或者ucTCP/IP,看完这三个东西以后,你就会发现差距不是一点点.ne2000的驱动都是差不多的,学习就是为了应用,因此建议你们上www.micrium.com下载cs8900和dm9000的驱动作为参考.
你会发现........不同.ucTCP/IP个人学习是免费的,但是商业应用收费的,注意.

使用特权

评论回复
17
我是火光| | 2008-1-25 13:50 | 只看该作者

难度不在TCP/IP


   难度不在TCP/IP协议栈,而是在RTL8019AS的状态控制寄存器的资料,,,主要就是那几个: CR、ISR、DCR、RCR、TCR、RSR、TSR...
   这上面的寄存器中有若干位的含义很不清楚.
   
   RTL8019AS的驱动是不少,但我看到似乎全部是查询方式的,中断方式的没有...
 
   归根到底,是缺乏准确的RTL8019资料,否则中断方式的驱动也是轻松的很的...
   没有资料,那是没有办法的

使用特权

评论回复
18
wlq_9| | 2008-1-25 16:54 | 只看该作者

结论

楼上的高人矣!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

9

帖子

1

粉丝