📄 ip.c
字号:
#include "cpu_reg.h"
#include "string.h"
#include "ip.h"
extern Uint16 AicRegs;
extern Uint16 RxSuccessFlag;
extern Uint16 TxEthnetFrameBuffer[1518/2];
extern Uint16 RxEthnetFrameBuffer[1518/2];
extern int ms;
//小端格式存储
const Uint16 MyMAC[] = { 0xE002, 0xA04C, 0x7A7E }; //本机MAC地址:0x02,0xE0,0x4C,0xA0,0x7E,0x7A
const Uint16 MyIP[] = { 0xA8C0, 0x0B01 }; //192.168.1.11
const Uint16 RemoteIP[] = { 0xA8C0, 0x2801 }; //192.168.1.40
const Uint16 SubnetMask[] = { 0xFFFF, 0x00FF }; //255.255.255.0
const Uint16 GatewayIP[] = { 0xA8C0, 0x0101 }; //192.168.1.1
Uint16 TxBufFlag;
Uint16 bnry,curr;
Uint16 UDPUserDataLenth;
Uint16 IpEdition; //IP版本
Uint16 IpServiceType;
Uint16 IpIdent;
Uint16 MyUdpPort;
Uint16 RemoteMAC[3]; //48 bit MAC
Uint16 RecdFrameMAC[3];
Uint16 RecdFrameIP[2];
Uint16 RecdIpFrameLenth;
Uint16 TxFrameSize;
Uint16 ARPAnswerSuccessFlag;
void delay(int k)
{
while(k--);
}
Uint16 SwapByte(Uint16 value)
{
Uint16 temp;
temp = (value << 8) | (value >> 8 );
return(temp);
}
//==============================================================================
/**********************************************************************
**函数原型: void page(uchar pagenumber)
**入口参数: Uint16 pagenumber: 要切换的页
**出口参数: 无
**返 回 值: 无
**说 明: 选择页,可选择0,1,2三页,第四页ne000兼容芯片保留
************************************************************************/
void page(Uint16 pagenumber)
{
Uint16 temp;
temp = Reg00; //command register
temp = temp & 0x3B ; //注意txp位不能要
pagenumber = pagenumber << 6;
temp = temp | pagenumber;
Reg00 = temp;
}
/**********************************************************************
**函数原型: void Init8019()
**入口参数: 无
**出口参数: 无
**返 回 值: 无
**说 明: 对芯片的工作寄存器进行设置,各个寄存器的用法可参考文档和
** 络芯片的数据手册
************************************************************************/
void Init8019()
{
ms = 0;
while(ms < 100);
/**********************************************************************
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: 这两个位用来启动命令或停止命令
1 0 启动命令
0 1 停止命令
//============================================
***********************************************************************/
Reg00=0x21; //使芯片处于停止模式,这时进行寄存器设置
ms = 0;
while(ms < 100);//延时100毫秒,确保芯片进入停止模式
page(0);
delay(10);
Reg0a = 0x00; //清RBCR0,RBCR0及RBCR1用来设置DMA传输的字节数
delay(5);
Reg0b = 0x00; //清RBCR1
delay(5);
Reg0c = 0xe0; //RCR,监视模式(地址匹配、CRC校验、帧对齐),不接收广播、多播及小于64字节的数据包
delay(5);
Reg0d = 0xe2; //TCR,loop back模式
delay(5);
Reg01 = 0x4c; //PSTART = 0x4c,接收环形缓冲区的起始页地址
delay(5);
Reg02 = 0x80; //PSTOP = 0x80,接收环形缓冲区的结束页地址
delay(5);
Reg03 = 0x4c; //BNRY = 4c
delay(5);
Reg04 = 0x40; //TPSR,发送起始页寄存器,设置发送包的起始页地址
delay(5);
Reg07 = 0xff; //ISR,清除所有中断标志位,中断状态寄存器
delay(5);
Reg0f = 0x01; //IMR,中断屏蔽寄存器清0,禁止中断
delay(5);
Reg0e = 0xc9; //DCR,数据配置寄存器,16位DMA方式
page(1);
delay(10);
Reg07 = 0x4d; //CURR,指向接收缓冲区用于接收数据的第一个页地址
delay(5);
Reg08 = 0x00; //MAR,多播地址寄存器
delay(5);
Reg09 = 0x00;
delay(5);
Reg0a = 0x00;
delay(5);
Reg0b = 0x00;
delay(5);
Reg0c = 0x00;
delay(5);
Reg0d = 0x00;
delay(5);
Reg0e = 0x00;
delay(5);
Reg0f = 0x00;
delay(5);
Reg01 = 0x02; //PAR0,本机MAC地址:0x02,0xE0,0x4C,0xA0,0x7E,0x7A,用于自动匹配操作
delay(5);
Reg02 = 0xE0;
delay(5);
Reg03 = 0x4C;
delay(5);
Reg04 = 0xA0;
delay(5);
Reg05 = 0x7E;
delay(5);
Reg06 = 0x7A;
delay(5);
page(3);
delay(10);
Reg01 = 0x30;
delay(5);
Reg04 = 0x80; //CONFIG1,选择IO基本地址:300H;选择IRQ:INT0
delay(5);
page(0);
delay(10);
Reg0c = 0xce; //接收广播、多播及小于64字节的包,不接收有错误的包
delay(5);
Reg0d = 0xe0; //将芯片设置成正常模式,跟外部网络连接
delay(5);
Reg00 = 0x22; //启动芯片开始工作
delay(5);
//-----------------------------------
Reg07 = 0xff; //清除所有中断标志位
ms = 0;
while(ms < 100);
}
Uint16 CalcCheckSum(Uint16 *Start, Uint16 Count, Uint16 IsTCP, Uint16 IsUDP)
{
Uint32 Sum;
Sum = 0;
if ((IsTCP) || (IsUDP))
{
Sum += MyIP[0];
Sum += MyIP[1];
Sum += RemoteIP[0];
Sum += RemoteIP[1];
Sum += SwapWord(Count*2);
if(IsTCP)
Sum += SwapWord(PROTOCOL_TCP);
else
Sum += SwapWord(PROTOCOL_UDP);
}
while(Count > 0)
{
Sum += *Start;
Start ++;
Count --;
}
Sum = (Sum & 0xFFFF) + ((Sum >> 16) & 0xFFFF);
if(Sum & 0xFFFF0000)
Sum++;
return((Uint16)((~Sum) & 0xFFFF));
}
//=============================================================================
/**********************************************************************
**函数原型: void SendFrame(Uint16 *TxdNetBuff,Uint16 length)
**入口参数: Uint16 *TxdNetBuff :指向发送缓冲区
** uint length :发送数据包的长度
**出口参数: 无
**返 回 值: 无
**说 明: 发送数据包,以太网底层驱动程序,所有的数据发送都要通过该程序
************************************************************************/
void SendFrame(Uint16 *TxdNetBuff, Uint16 length)
{
Uint16 i,ii;
if(length < 46/2)
{
for(i = length; i < 60/2; i++)
TxEthnetFrameBuffer[i] = 0;
length = 60/2;
}
page(0);
delay(10); //切换至第0页
length = length << 1;
TxBufFlag =! TxBufFlag; //设置两个发缓区,提高发送效率
if(TxBufFlag)
{
Reg09 = 0x40; //CRDA1,当前DMA地址,设置发送页地址
}
else
{
Reg09 = 0x46; //设置发送页地址
}
Reg08 = 0x00; //CRDA0,read page address low
delay(1);
Reg0b = length >> 8; //RBCR1,写发送长度高位
delay(1);
Reg0a = length & 0x00ff; //RBCR0,写发送长度低位
delay(1);
Reg00 = 0x12; //Remote Write,write dma,page0
for(i = 0; i < length/2; i++)
{
Reg10 = TxEthnetFrameBuffer[i];
}
/***************************************/
//以下为终止DMA操作
Reg0b=0x00;
delay(1);
Reg0a=0x00;
delay(1);
Reg00=0x22; //结束或放弃DMA操作
delay(1);
/***************************************/
for(i = 0; i < 6; i++) //最多重发6次
{
for(ii = 0; ii < 1000; ii++)//检查CR寄存器的txp位是否为低,为1说明正在发送,为0说明发完或出错放弃
{
if((Reg00 & 0x04) == 0)
{
break;
}
}
if((Reg04 & 0x01) != 0) //表示发送成功,判断发送状态寄存器TSR,决定是否出错
{
break;
};
Reg00 = 0x3e; //TXP = 1
}
delay(1);
Reg07 = 0xff; //清除所有中断标志位
if(TxBufFlag)
{
Reg04 = 0x40; //txd packet start;
}
else
{
Reg04 = 0x46; //txd packet start;
}
delay(1);
Reg06 = length >> 8; //TBCR1,high byte counter
delay(1);
Reg05 = length & 0xff; //TBCR0,low byte counter
delay(1);
Reg07 = 0xff;
delay(1);
Reg00 = 0x3e; //to sendpacket;
}
/**********************************************************************
**函数原型: Uint16 Rec_NewPacket()
**入口参数: 无
**出口参数: 无
**返 回 值: 0 没有新数据包
** 1 接收到新数据包
**说 明: 查询是否有新数据包并接收进缓冲区
************************************************************************/
Uint16 RecFrame()
{
Uint16 i,ii;
Uint16 Temp,length;
union
{
Uint16 total;
struct
{
Uint16 high:8;
Uint16 low:8;
}e;
}d;
for(i = 0; i < 1518/2; i++)
RxEthnetFrameBuffer[i] = 0;
page(0);
delay(10);
bnry = Reg03; //读页指针 the last receive buffer page the host has read
bnry = bnry & 0x00FF;
page(1);
delay(10);
curr = Reg07; //curr writepoint 8019写页指针 指向接收缓冲区用于接收数据的第一个页地址
curr = curr & 0x00FF;
page(0);
delay(10);
if((curr == 0))
return(0); //读的过程出错
bnry++;
if(bnry > 0x7f)
bnry = 0x4c;
if(bnry != curr) //此时表示有新的数据包在缓冲区里
{ //在任何操作都最好返回page0
page(0);
delay(10);
//=======================================
Reg09 = bnry; //读页地址的高字节,DMA的当前地址
delay(5);
Reg08 = 0x00; //读页地址的低字节
delay(5);
Reg0b = 0x00; //读取字节计数高字节
delay(5);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -