⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm.c

📁 2812 TCP/IP协议的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
    //----------------------------------------------------不颠倒,我的理解是上面的ReadFromNet(0x10)将第一个字节放到16位数据总线的低位,
    //----------------------------------------------------第二个字节放到16位数据总线的高位,故没有颠倒,tmp[1]中就是包的长度
    //----------------------------------------------------有点类似于存储器存储空间的情况,made by dt_zw
    REC_BUFF[REC_BUFF_NUM].words[1]=tmp[1]; //把真正的接收的帧的长度保存到缓冲区
  
    //=====================以上各步操作表示读入的数据包有效
    //------tmp[0]=[下一包的指针:接收状态];tmp[1]=[本包长度高位:本包长度低位]
    //----------------------------------------------------注意:tmp数组每个元素的字节顺序与网卡中第一个字的存放顺序是不一样的,
    //----------------------------------------------------即每个字的高低位字节是相反的,但字的顺序是相同的,只是字内顺序不同
    if(((tmp[0]&0x0001)==0)||((tmp[0]&0xff00)>0x7f00)//---if( (状态位的bit0==0:接收包错误) or (下一数据包的起始页地址>PStop-1=0x7f00)
     ||((tmp[0]&0xff00)<0x4c00)||(tmp[1]>0x0600))//----    or (下一数据包的起始页地址<PStart=0x4c00) or (接收的数据包长度>0x0600=1536字节) )
        {//接收状态错误或下一数据包的起始页地址错误(过大或过小)或接收的数据包长度>0x0600=1536字节
     page(1);
     curr=ReadFromNet(0X07);    //page1读取CURR的值
     page(0);    //切换回page0
     bnry = curr -1; //把bnry恢复为下16K中的空余部分//-------???啥意思???
     //------------------------------------------------------我的理解是:清空缓冲区
     if(bnry < 0x4c)//---------------------------------------curr=PSTART=ox4c的情况下清空缓冲区
         {
      bnry =0x7f;
         }
     WriteToNet(0x03,bnry);    //把BNRY恢复到指向下一帧write to bnry//----将bnry写入到网卡寄存器中才会生效,表示本页已读  
     WriteToNet(0x07,0xff); //清除中断标志//---------------------------收包错误会将相关中断标志置位,故故需要清除
     //goto rea1;
     OS_EXIT_CRITICAL();
     return(0);
     }//end of if(((tmp[0]&0x0001)//------------------------end of 收包错误
  
    //=============================================
    else//表示数据包是完好的.读取剩下的数据
     {
     WriteToNet(0x09,bnry);      //RSAR1写入读页地址的高字节//read page address high
     //----------------------------当一页的内容全部读完已后才能读直页(bnry++),
   
     WriteToNet(0x08,4);         //RSAR0写入读页地址的低字节//read page address low
     //----------------------------本页在前面已读过四个字节,故WriteToNet(0x08,4),注意不是(0x08,0)
   
     WriteToNet(0x0b,tmp[1]>>8&0x00ff);     //RSCR1写入读取字节计数高字节//read count high
     //----------------------------注:原来的语句是<WriteToNet(0x0b,tmp[0]);>有误.tmp[0]存取的是[下一包的指针:接收状态],怎么是长度呢?
     //----------------------------答:tmp[1]的高字节才是长度的高位部分,故应该改成tmp[1]>>8&0x00ff
   
     WriteToNet(0x0a,tmp[1]); //RSCR0写入读取字节计数低字节//read count low;
         //----------------------------tmp[1]=[本包长度高位:本包长度低位]

     WriteToNet(0x00,0x0a);    //启动Remote DMA读操作
     //read dma
   
     length=tmp[1];//计算出要读取的帧的长度,长度=数据区长度+4(CRC)
   
     for(ii=0;ii<((length+1)/2);ii++)//---------------------由于是16位总线,故只要读(length+1)/2次就可以整个数据包读完
     //-----------------------------------------------------一个疑问:当包的长度是奇数,多读的一个字节如何处理????????????????
      {
      *REC_BUFF_PTR_WORDS=ReadFromNet(0x10);
      REC_BUFF_PTR_WORDS++;
      }
     //================终止DMA操作
     WriteToNet(0x0b,0x00);     //RSCR1写入读取字节计数高字节//read count high   
     WriteToNet(0x0a,0x00);     //RSCR0写入读取字节计数高字节//read count low;
     WriteToNet(0x00,0x22);     //结束或放弃DMA操作//结束或放弃DMA
     //============================
     }//end of else
    //=========================================
    bnry=(tmp[0]/256)-1; //tmp[1]是当前有效的CURR//-----???这个注释无法理解//---------tmp[0]=[下一包的指针:接收状态]
    //---------------------------------------tmp[0]/256的功能:tmp[0]的值右移8位,其实是将下一包的指针求出
    //---------------------------------------再减1表示,下一包字前的一个页已读
  
    if(bnry<0x4c)//--------------------------???????有用吗?[(tmp[0]/256)-1]怎么会<0x4c,似乎没有用!
     bnry=0x7f;
    WriteToNet(0x03,bnry);      //写入有效的BNRY     //write to bnry
    WriteToNet(0x07,0xff);    //清除中断标志//------------?????????????什么情况下需要加此语句???? 
    REC_BUFF_PTR_BYTES=REC_BUFF[REC_BUFF_NUM].bytes;//---------REC_BUFF_PTR_BYTES指向当前缓冲区的首地址
    REC_BUFF_PTR_BYTES=REC_BUFF_PTR_BYTES+4;//把指针恢复到数据包的起始//----因为前4字节是RTL8019AS附加的
#ifdef Little_End//-----------------------------本程序使用小端:字数据的高地址存放数据的高字节,低地址存放数据的低字节
    if((((ipethernet*)REC_BUFF_PTR_BYTES)->NextProtocal==0x0008)//可以减少对数据缓冲取的利用
    //----ipethernet类型在ethernet.h中定义,是一个结构体类型,其中NextProtocal成员存储链路层传送过来的数据中下层协议的类型
     ||(((ipethernet*)REC_BUFF_PTR_BYTES)->NextProtocal==0x0608))//不过如果缓冲区足够大就最好不要
#endif
#ifdef Big_End//--------------------------------没有定义大端:字数据的高字节存储在低地址中,字数据的低字节存放在高地址中
    if((((ipethernet*)REC_BUFF_PTR_BYTES)->NextProtocal==0x0800)//可以减少对数据缓冲取的利用
     ||(((ipethernet*)REC_BUFF_PTR_BYTES)->NextProtocal==0x0806))//不过如果缓冲区足够大就最好不要
#endif
     {
     REC_BUFF_NUM++;
     OS_EXIT_CRITICAL();
     Rec_Ethernet_Packed(REC_BUFF_PTR_BYTES,0);//----------在Rec_Ethernet_Packed在Ethernet.h中定义
     OS_ENTER_CRITICAL();
     goto rea1;
     //可以直接退出。
     }
    else 
     goto rea1;
    }//end of if(bnry!=curr)
OS_EXIT_CRITICAL();
return(0);
}

/**********************************************************************
**函数原型:       void    InitNic()
**入口参数:?无
**出口参数:    无
**返 回 值:?无              
**说      明:?对芯片的工作寄存器进行设置,各个寄存器的用法可参考文档和
**      络芯片的数据手册
************************************************************************/
void InitNic(uint8 num)  
{

uint8    i;
uint8    j;

//PINSEL0 = 0x00000005;    // 设置所有管脚连接GPIO
//PINSEL1 = 0x00000000;
//IODIR=IODIR|(NET_DATA+NET_CS+NET_WR+NET_ALE+NET_RD+NET_RST);
//IOSET=NET_DATA+NET_CS+NET_WR+NET_ALE+NET_RD+NET_RST;
IODIR=IODIR|NET_RST;//--------------设置连接复位控制信号(RSTDRV)的管脚P0.6为输出
//--------------------RSTDRV:复位信号,高电平触发

//下面通过三个循环实现网卡初始化
IOCLR=NET_RST;//--------------------使P0.6输出低电平---------------此
for(i=0;i<200;i++)//----------------延时10毫秒---------------------段
{                      //------------------------------------------必
    for(j=0;j<200;j++);//------------------------------------------需
}//----------------------------------------------------------------吗?似乎没有必要!

IOSET=NET_RST;//--------------------使P0.6输出高电平
for(i=0;i<200;i++)//----------------延时10毫秒
{
    for(j=0;j<200;j++);
}

IOCLR=NET_RST;//--------------------使P0.6输出低电平
for(i=0;i<200;i++)//----------------延时10毫秒//-------似乎没有必要!
{
    for(j=0;j<200;j++);
}
  

WriteToNet(0x1f,0x00);/*------------把数据0x00写入RTL8019AS的NET_BASE_ADDR+0x1f的单元中,实现热复位 
------------------------------------注:18H到1FH共8个地址都是复位地址,每个地址的功能都是一样的,
------------------------------------但实际上只有18H,1AH,1CH,1EH这几个复位端口是有效的,
------------------------------------其他不要使用,有些兼容卡不支持19H,1BH,1DH,1FH等奇数地址的复位)
------------------------------------实际上只要使用冷复位就可以了,热复位程序可以不要。
------------------------------------热复位主要在电脑里有用,冷复位就像电脑的冷启动,热复位相当于电脑的热启动。*/ 
for(i=0;i<200;i++)//----------------延时10毫秒
{
    for(j=0;j<200;j++);
}

/**********************************************************************

     1.Reg00命令寄存器: CR,命令寄存器,地址偏移量00H,为一个字节
     位:    7     6     5     4     3     2     1     0 
     名字: PS1 PS0 RD2 RD1 RD0 TXP STA STP 
     //============================================
     2.
     RD2,RD1,RD0: 这3个位代表要执行的功能。
     0     0     1 : 读网卡内存
     0     1     0 : 写网卡内存
     0     1     1 : 发送网卡数据包
     1     *     * : 完成或结束DMA的读写操作
     //============================================
     3.TXP位置1时发送数据包,发完自动清零
     //============================================
     4.
     STA,STP: 这两个位用来启动命令或停止命令------------------------START->STA
     1     0     启动命令
     0     1     停止命令
     //============================================
********************************************************/
WriteToNet(0x00,0x21);     //使芯片处于停止模式,这时进行寄存器设置(STA,STP=0,1)

for(i=0;i<200;i++)//延时10毫秒,确保芯片进入停止模式
{
    for(j=0;j<200;j++);
} 

page(0);//---------------------------选择0页

WriteToNet(0x0a,0x00);     /*清rbcr0---RBCR0,1: Remote Byte Count Registers (0AH & 0BH; Type=W in Page0)
      ---------------------------These two registers set the data byte counts of remote DMA.*/
WriteToNet(0x0b,0x00);    //清rbcr1---同上
WriteToNet(0x0c, 0xe0); //RCR,监视模式,不接收数据包----Receive Configuration Register (0CH; Type=W in Page0, Type=R in Page2)
WriteToNet(0x0d, 0xe2); //TCR,loop back模式
page(0);
WriteToNet(0x01,0x4c); //PSTART=0X4C---------------构造缓冲环:
WriteToNet(0x02,0x80); //PSTOP=0X80----------------0x4c~0x80
WriteToNet(0x03,0x4c); //bnry=0x4c;
page(0);
WriteToNet(0x04,0x40);    //TPSR,发送起始页寄存器
WriteToNet(0x07,0xff);    //清除所有中断标志位,中断状态寄存器//-------------后面有此命令,必须吗??????
WriteToNet(0x0f,0x11);    //中断屏蔽寄存器清0,禁止中断//--------------------为何不放在最前面,为何设置成0x11?????

WriteToNet(0x0e,0xcb);    // 数据配置寄存器,8位dma方式----DCR
page(1);
WriteToNet(0x07,0x4d);    //curr=0x4d
WriteToNet(0x08,0x00);    //-----------0下面八个是设置Multicast Address Register
WriteToNet(0x09,0x00);    //-----------1--------------------
WriteToNet(0x0a,0x00);    //-----------2--------------------
WriteToNet(0x0b,0x00);    //-----------3--------------------
WriteToNet(0x0c,0x00);    //-----------4--------------------
WriteToNet(0x0d,0x00);    //-----------5--------------------
WriteToNet(0x0e,0x00);    //-----------6--------------------
WriteToNet(0x0f,0x00);    //-----------7--------------------
WriteToNet(0x00,0x22);    //这时让芯片开始工作----0x22=(00 100 0 10)B//-------------后面有此命令,必须吗????
SetMacID(NetPort[num].My_Mac);    //将芯片物理地址写入到MAR寄存器-------在ethernet.h中定义,类型为NetP,NetP

page(0);
WriteToNet(0x0c,0xcc);    //将芯片设置成正常模式,跟外部网络连接
WriteToNet(0x0d,0xe0);
WriteToNet(0x00,0x22);    //启动芯片开始工作
WriteToNet(0x07,0xff);    //清除所有中断标志位
    
}
uint16 swap_int16(uint16 temp)
{uint16 temp1;
temp1=(temp&0xff00)>>8;
temp=(temp&0x00ff)<<8;
return(temp+temp1);
}
uint32 swap_int32(uint32 temp)
{
union     w    temp232,temp132;
temp232.dwords=temp;
temp132.bytes.byte0=temp232.bytes.byte3;
temp132.bytes.byte1=temp232.bytes.byte2;
temp132.bytes.byte2=temp232.bytes.byte1;
temp132.bytes.byte3=temp232.bytes.byte0;
return(temp132.dwords);
}

uint16 Char2ToInt16(uint8 * temp)
{
uint16 temp16;
temp16=((uint16)(*temp))<<8;
temp++;
temp16=temp16+(uint16)(*temp);
return(temp16);
}

uint32 Char4ToInt32(uint8 * temp)
{
uint32 temp32;
temp32=((uint32)(*temp))<<24;
temp++;
temp32=temp32+(((uint32)(*temp))<<16);
temp++;
temp32=temp32+(((uint32)(*temp))<<8);
temp++;
temp32=temp32+(uint32)(*temp);
return(temp32);
}
/**********************************************************************
**函数原型:       void    int_ex1() interrupt 2
**入口参数:?无
**出口参数:    无
**返 回 值:?无              
**说      明:?RTL8019AS中断服务程序
************************************************************************/
/*
void int_ex1() interrupt 2
{
// OS_INT_ENTER();

    EX_RAM uint8 i,TEMP;
    EX1=0;
    iic++;
    TEMP=Reg00;
    page(0);
    i=Reg07;
  
if((i&&0x10)==0x10)
{
OSSemIntPost(RecBufOverFlowFlag);
}
else if((i&&0x01)==0x01)
OSSemIntPost(RecPackedFlag);
Reg07=0XFF;
Reg00=TEMP;
OSIntExit();
}
uint8 rec_data()
{
uint8 i,TEMP;
TEMP=Reg00;
page(0);
i=Reg07;
Reg07=0XFF;
Reg00=TEMP;
if((i&&0x01)==0x01)
return (0);
return(1);

     }
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -