📄 udp.c
字号:
/************************************************************************
FileName: Udp.c
Description: Udp protocol process
Date: 2007 09 21
************************************************************************/
#include "Main.h"
#include "EEPROM.h"
/************************************************************************/
bit EthernetBuf0DataFlag; // 以太网卡缓冲0已有数据
bit EthernetLinkFlag; // 以太网是否LINK上
bit EthernetNoDataFlag; // 以太网芯片中没有数据
UWORK16 RTL8019asRcvNum; // 在缓存中以太网包的个数,16K存满64页,每页256字节
xdata ST_RECEIVE_ETHERNET gstaRevEthernet; // 接收以太网包
xdata ST_ETHERNET_STATISTICS gstEthernetStatistics; // 以太网卡收发统计
xdata UWORK8 MAC_Remote_buf[ETHER_HEAD_LEN]; // 以太网头(目的MAC,源MAC,协议)
xdata UWORK8 NetSend_buf[NET_SEND_BUFF]; // 以太网发送缓冲
xdata UWORK8 gucaSegTemp[SEGMENT_DATA]; // 分片数据
/*************************************************************************************/
bit ARPFinishFlag; // ARP完成标志
bit IPConflitTestFlag; // IP冲突测试
bit IPOrMacConfiltFlag; // IP,MAC冲突标志
bit StartConfiltLedFlag; // 冲突时启动快闪
/************************************************************************/
xdata ST_ARP_FORMAT ArpRequestFormat; // ARP帧请求格式
xdata ST_ARP_FORMAT ArpAnswerFormat; // ARP应答格式
xdata ST_ARP_CACHE ArpCache_Buf[REMOTE_IP_NUM]; // ARP高速缓存
UWORK8 IpModeNum; // 在不同模式下IP数据不一样
UWORK8 ArpCachePoniter; // ARP高速缓存指针
xdata UWORK8 gucARPOddNum; // 老化后,ARP完不成的次数
xdata UWORK8 ArpPhases; //ARP阶段
/************************************************************************/
xdata ST_IP_HEAD_FORMAT gstIphead;
xdata UWORK16 LocalIpID; // 本地IP的ID号
xdata UWORK16 RevIpID; // 接收的ID号
xdata UWORK8 IPAddress_buf[IP_LEN]; // IP地址
xdata UWORK8 SubNetMask_buf[IP_LEN]; // 子网掩码
xdata UWORK8 GateWay_buf[IP_LEN]; // 网关
bit gbMoreSegFlag; // 还有更多的分片标志
bit gbHaveFragment; // 有分片标志
/***********************************************************************/
xdata UWORK8 SetupIP_RcvSignal[32]; // 接收前导和标志信号
xdata UWORK8 SetupIP_SendSignal[32]; // 发送前导和标志信号
xdata ST_UDP_STATISTICS gstUDPStatistics; // UDP统计
/*********************************************************************
函数名: void InitPara(void)
功能: 初始化网络参数
输入: 系统启动或者参数改变时
输出: 将IP,端口号等参数从flash中读出进行配置
返回: none
日期: 2006/05/30
*********************************************************************/
void InitPara(void)
{
memcpy(&MAC_Remote_buf[6],&NetParameter.MAC_Local_buf[0],MAC_LEN); //把源本地MAC地址复制到发送MAC缓存中
memcpy(&IPAddress_buf[0],&NetParameter.IP_Local_buf[0],IP_LEN); // 本地IP
memcpy(&SubNetMask_buf[0],&NetParameter.SubMask_buf[0],IP_LEN); // 掩码
memcpy(&GateWay_buf[0],&NetParameter.Gateway[0],IP_LEN); // 默认网关
memcpy(&ArpCache_Buf[0].ucaIP[0],&NetParameter.IP_Remote_buf[0],IP_LEN); // 远程IP1
ArpCache_Buf[0].usRemotePort = NetParameter.Port_Remote; //远程端口号1
ARPFinishFlag = FALSE;
EthernetLinkFlag = FALSE;
}
/*********************************************************************
函数名: UWORK8 RTL8019asInit(void)
功能: 初始化RTL8019AS
输入: None
输出: None
返回: OK, ERROR
日期: 2004/02/04
*********************************************************************/
UWORK8 RTL8019asInit(void)
{
xdata UWORK8 ucBNRY,ucLoop,ucLoop1;
xdata UWORK8 ucMAR0,ucMAR1,ucMAR2,ucMAR3,ucMAR4,ucMAR5,ucMAR6,ucMAR7;
EX0 = FALSE; // 禁止外部中断0
RTL8019asReset();
RTL8019asWrite(RW0_CR,0x21); // 网卡停止运行
DelayMs(10); // 延时100ms,确保芯片进入停止模式
RTL8019asRead(R0_ID0,ucLoop); // 读入芯片ID号
RTL8019asRead(R0_ID1,ucLoop1);
if((RTL8019AS_ID0 != ucLoop) || (RTL8019AS_ID1 != ucLoop1))
{
return ERROR;
}
RTL8019asWrite(W0_DCR,0xd8); // 8位DMA方式
RTL8019asWrite(W0_RBCR0,0x00); // 清零远程DMA读/写的字节数
RTL8019asWrite(W0_RBCR1,0x00);
// 芯片处于监视和环回模式,跟外部网络断开 */
RTL8019asWrite(W0_RCR,0xe0); // 监视模式
RTL8019asWrite(W0_TCR,0xe2); // 环回模式
// 使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包
// 使用0x4c~0x7f 为网卡的接收缓冲区共52 页 */
RTL8019asWrite(W0_PSTART,0x4c);
RTL8019asWrite(W0_PSTOP,0x80);
RTL8019asWrite(RW0_BNRY,0x4c); // 读页指针
// 清除所用中断标志
RTL8019asWrite(RW0_ISR,0xff); // 写1清零,上电必须清零
RTL8019asWrite(W0_IMR,RW0_ISR_TXE |RW0_ISR_RXE |
RW0_ISR_PTX | RW0_ISR_PRX); // 使能发送完成,发送出现错误,接收完成,接收出现错误中断
Page1();
RTL8019asWrite(RW1_CURR,0x4d); // 当前网卡正在写的页
RTL8019asWrite(RW1_MAR0,0x00); // 禁止组播
RTL8019asWrite(RW1_MAR1,0x00);
RTL8019asWrite(RW1_MAR2,0x00);
RTL8019asWrite(RW1_MAR3,0x00);
RTL8019asWrite(RW1_MAR4,0x00);
RTL8019asWrite(RW1_MAR5,0x00);
RTL8019asWrite(RW1_MAR6,0x00);
RTL8019asWrite(RW1_MAR7,0x00);
RTL8019asWrite(RW1_PAR0,NetParameter.MAC_Local_buf[0]); // 初始化MAC
RTL8019asWrite(RW1_PAR1,NetParameter.MAC_Local_buf[1]);
RTL8019asWrite(RW1_PAR2,NetParameter.MAC_Local_buf[2]);
RTL8019asWrite(RW1_PAR3,NetParameter.MAC_Local_buf[3]);
RTL8019asWrite(RW1_PAR4,NetParameter.MAC_Local_buf[4]);
RTL8019asWrite(RW1_PAR5,NetParameter.MAC_Local_buf[5]);
Page3();
Rtl3ConfigEnable(); // page3配置使能
Rtl3IntEnable(); // 中断引脚使能
Auto3DetectNMT(); // 自动选择网络媒介类型
RTL8019asWrite(RW3_CONFIG2,0);
RTL8019asWrite(RW3_CONFIG3,R3_CONFIG3_LEDS1|R3_CONFIG3_LEDS0);
Rtl3ConfigDisable(); // page3配置禁止
Page0();
RTL8019asRead(RW0_BNRY,ucBNRY); // 读出部分值,比较写入的值来判断是否初始化成功
Page1();
RTL8019asRead(RW1_MAR0,ucMAR0);
RTL8019asRead(RW1_MAR1,ucMAR1);
RTL8019asRead(RW1_MAR2,ucMAR2);
RTL8019asRead(RW1_MAR3,ucMAR3);
RTL8019asRead(RW1_MAR4,ucMAR4);
RTL8019asRead(RW1_MAR5,ucMAR5);
RTL8019asRead(RW1_MAR6,ucMAR6);
RTL8019asRead(RW1_MAR7,ucMAR7);
StartTimer(0,100); // 运行灯定时器,1秒钟闪烁
StartTimer(8,105); // 检测以太网link与否
StartTimer(9,1000); // 以太网芯片保护校验
StartTimer(13,6000); // 自我保护
if((0x4c == ucBNRY) && (0x00 == ucMAR0) && (0x00 == ucMAR1)
&& (0x00 == ucMAR2) && (0x00 == ucMAR3) && (0x00 == ucMAR4)
&& (0x00 == ucMAR5) && (0x00 == ucMAR6) && (0x00 == ucMAR7))
{
ArpRequestFormat.usHTYPE = HTYPE; //初始化ARP请求包
ArpRequestFormat.usPTYPE = PTYPE;
ArpRequestFormat.ucHLEN = HLEN;
ArpRequestFormat.ucPLEN = PLEN;
memcpy(&ArpRequestFormat.ucaSHA[0],&NetParameter.MAC_Local_buf[0],MAC_LEN); // 源MAC地址
memset(&ArpRequestFormat.ucaTHA,0,MAC_LEN); // 目的MAC
ArpAnswerFormat.usHTYPE = HTYPE; //初始化ARP应答包
ArpAnswerFormat.usPTYPE = PTYPE;
ArpAnswerFormat.ucHLEN = HLEN;
ArpAnswerFormat.ucPLEN = PLEN;
ArpAnswerFormat.usOPER = OPER_APLY; // ARP应答
memcpy(&ArpAnswerFormat.ucaSHA[0],&NetParameter.MAC_Local_buf[0],MAC_LEN); // 源MAC地址
gstIphead.ucVerAndLen = 0x45; //初始化IP包
gstIphead.ucDs = 0x00;
gstIphead.usSegOffset = 0x00;
gstIphead.ucTTL = 0x80;
LocalIpID = rand(); // IP发送的16位标志,上电初始化为一个随机值
Page0(); // 将网片配置成正常工作模式
RTL8019asWrite(W0_RCR,0xcc); // 接收广播和组播数据
RTL8019asWrite(W0_TCR,0xe0);
RTL8019asWrite(W0_RBCR0,0x00);
RTL8019asWrite(W0_RBCR1,0x00);
RTL8019asWrite(RW0_CR,0x22); // 网片开始工作
RTL8019asWrite(RW0_ISR,0xff); // 清除所有中断
EX0 = TRUE; // 外部中断0使能 // 使能外部中断0
IPOrMacConfiltFlag = FALSE;
EthernetLinkFlag = FALSE;
IPConflitTestFlag = FALSE;
return OK;
}
else
{
return ERROR;
}
}
/*********************************************************************
函数名: UWORK8 If8019SendReady(void)
功能: 检测以太网是否发送准备好
输入: 串口有数据需要发送
输出:
返回: OK, ERROR
日期: 2007/03/13
*********************************************************************/
UWORK8 If8019SendReady(void)
{
// ARP完成且发送完成
if(ARPFinishFlag && (FALSE == EthernetBuf0DataFlag)) //缓冲0有数据标志
{
return OK;
}
else
{
return ERROR;
}
}
/*********************************************************************
函数名: void RcvEthernetData(void)
功能: 接收以太网数据
输入: None
输出: None
返回: OK, ERROR
日期: 2007/03/13
*********************************************************************/
void RcvEthernetData(void)
{
UWORK16 ucTemp,ucResult;
EX0 = FALSE; // 禁止外部中断0
if(0 != RTL8019asRcvNum) // 以太网芯片缓存中是否有以太网包
{
EX0 = FALSE; // 禁止外部中断0
ucTemp = RevEthernetPacket(); //解析网络包
// SerialSendbuf((UWORK8 *)&gstaRevEthernet.usprotocol,sizeof(ST_RECEIVE_ETHERNET));
EX0 = TRUE; // 外部中断0使能
if(OK == ucTemp) // 正确接收了数据,记录的缓存减1
{
RTL8019asRcvNum--;
EthernetNoDataFlag = FALSE;
switch(gstaRevEthernet.usprotocol) // 劈以太网帧
{
case IP_type: //IP协议
IpReceive();
break;
case ARP_type: //ARP协议
ArpProcess();
break;
default:
break;
}
}
}
else // 可能中断未被及时执行
{
if(FALSE == EthernetNoDataFlag) // 可能有没有及时中断造成数据没有读完
{
EX0 = FALSE; // 禁止外部中断0
Page1();
RTL8019asRead(RW1_CURR,ucTemp); // 比较读指针和写指针,判断是否有数据
Page0();
if((ucTemp < 0x80) && (ucTemp > 0x4b)) // 读的过程是否出错,CUUR处于0x4c~0x7f
{
RTL8019asRead(RW0_BNRY,ucResult);
ucResult++;
if(ucResult > 0x7f)
{
ucResult = 0x4c;
}
if(ucTemp != ucResult) // 是否有没有读完的数据
{
ucTemp = RevEthernetPacket();
EX0 = TRUE; // 外部中断0使能
if(OK == ucTemp) // 正确接收了数据,记录的缓存减1
{
switch(gstaRevEthernet.usprotocol) // 劈以太网帧
{
case IP_type:
IpReceive();
break;
case ARP_type:
ArpProcess();
break;
default:
break;
}
}
}
else
{
EthernetNoDataFlag = TRUE; // 以太网芯片中确实没有了数据
}
}
EX0 = TRUE; // 外部中断0使能
}
}
EX0 = TRUE; // 外部中断0使能
}
/*********************************************************************
函数名: UWORK8 SendEthernetPacket(UWORK16 usEthDataSendLen)
功能: 发送以太网包
输入: 协议头长度,串口数据长度,临时数据长度
输出: None
返回: OK, ERROR
日期: 2004/12/06
*********************************************************************/
UWORK8 SendEthernetPacket(UWORK16 usEthDataSendLen)
{
UWORK16 usLoop;
UWORK8 ucLenHigh,ucLenLow,ucLoop,ucPadding = 0;
if(FALSE == EthernetLinkFlag) // 以太网link上,才能发送数据
{
return ERROR;
}
if(EthernetBuf0DataFlag) //清除缓冲0有数据标志, 网络正忙,等待
{
for(usLoop = 0; usLoop < 5; usLoop++)
{
DelayMs(5);
if(FALSE == EthernetBuf0DataFlag) //清除缓冲0有数据标志
{
break;
}
}
if(5 == usLoop)
{
return ERROR; // 等待超时,丢弃数据
}
}
EX0 = FALSE; // 禁止外部中断0
Page0();
RTL8019asWrite(W0_RSAR1,0x40); // 缓冲区0,远程DMA高地址
RTL8019asWrite(W0_RSAR0,0x00); // 远程DMA低地址
usLoop = ETHER_HEAD_LEN + usEthDataSendLen; // 帧长 = 以太网头 + 数据
if(usLoop < 60)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -