📄 arm.c
字号:
//----------------------------------------------------不颠倒,我的理解是上面的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 + -