SmartOS/Drivers/W5500.cpp

759 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "W5500.h"
/*
硬件设置部分
硬件:TCP,UDP,ICMP,IPv4,ARP,IGMP,PPPoE
引脚 PMODE[2:0]---- 也可以通过 PHYCFGR 寄存器进行配置
000 10BI半双工关闭自动协商
001 10BI全双工关闭自动协商
010 100BI半双工关闭自动协商
011 100BI全双工关闭自动协商
100 100BI半双工启用自动协商
101 未启用
110 未启用
111 所有功能,启用自动协商
RSTn 重置 低电平有效低电平时间至少500us才能生效
InTn 中断输出 (低电平有效)--- 程序中 IRQ 引脚
支持SPI 模式0和模式3 自动识别
*/
/*
内部结构
一个通用寄存器区
0x0000-0x0039 独立寻址BSB选区
IP MAC 等整体信息
八个Socket寄存器区
0x0000-0x0030 独立寻址BSB选区
8个Socket收发缓存 总缓存32K
发缓存一共16K(0x0000-0x3fff) 初始化分配为 每个Socket 2K
收缓存一共16K(0x0000-0x3fff) 初始化分配为 每个Socket 2K
再分配时 收发都不可越16K大边界 地址自动按Socket编号调配
*/
class ByteStruct // 位域基类
{
public:
void Init(byte data = 0) { *(byte*)this = data; }
byte ToByte() { return *(byte*)this; }
};
// 数据帧格式
// 2byte Address + 1byte CONFIG_Phase + nbyte Data Phase
// 可变数据长度模式下SCSn 拉低代表W5500的SPI 帧开始(地址段),拉高表示帧结束 可能跟SPI NSS 不一样)
// 位域 低位在前
// 配置寄存器 CONFIG_Phase结构
typedef struct : ByteStruct
{
byte OM:2; // SPI 工作模式
// 00 可变数据长度模式N字节数据段1<=N
// 01 固定数据长度模式1字节数据长度N=1
// 10 固定数据长度模式1字节数据长度N=2
// 11 固定数据长度模式1字节数据长度N=4
// 固定模式不需要NSS 芯片NSS 接地) 可变模式SPI NSS 受控
byte RWB:1; // 0读 1
byte BSB:5; // 区域选择位域 // 1个通用寄存器 8个Socket寄存器组选择写缓存收缓存
// 00000 通用
// XXX01 SocketXXX 寄存器
// XXX10 SocketXXX 发缓存
// XXX11 SocketXXX 收缓存
// 其余保留, 如果选择了保留的将会导致W5500故障
}CONFIG_Phase;
//通用寄存器结构
// 模式寄存器
typedef struct : ByteStruct
{
byte Reserved:1;
byte FARP:1; // 强迫ARP 0 关闭1开启 强迫ARP模式下无论是否发送数据都会强迫ARP请求
byte Reserved2:1;
byte PPPoE:1; // PPPoE 0 关闭1开启
byte PB:1; // Ping 屏蔽位 1 ping不响应0 ping 有响应
byte WOL:1; // 网络唤醒 0关闭1开启 (收到唤醒包发生中断)
byte Reserved3:1;
byte RST:1; // 软件复位 1 复位
}T_MR;
// IR 不为零中断
// IMR 为零屏蔽中断
typedef struct : ByteStruct // IMR 结构一样
{
byte Reserved:4;
byte MP:1; // 收到网络唤醒包
byte PPPoE:1; // PPPoE 连接不可达
byte UNREACH:1; // 目标不可达
byte CONFLICT:1; // IP冲突
}T_IR;
// PHY 配置
typedef struct : ByteStruct
{
byte LNK:1; // 连接状态 1已连接 0连接断开
byte SPD:1; // 速度状态 1:100Mpbs 0:10Mbps 【只读】
byte DPX:1; // 双工状态 1全双工 0半双工 【只读】
byte OPMDC:3; // 如下OPMD
byte OPMD:1; // 1通过OPMDC配置0通过硬件引脚
// 配置引脚 PMODE[2:0]---- 也可以通过 PHYCFGR 寄存器进行配置
// 000 10BI半双工关闭自动协商
// 001 10BI全双工关闭自动协商
// 010 100BI半双工关闭自动协商
// 011 100BI全双工关闭自动协商
// 100 100BI半双工启用自动协商
// 101 未启用
// 110 未启用
// 111 所有功能,启用自动协商
byte RST:1; // 重启 为0时内部PHY 重启
// 重启后为1
}T_PHYCFGR;
W5500::W5500() { Init(); }
W5500::W5500(Spi* spi, Pin irq, OutputPort* rst)
{
Init();
Init(spi, irq,rst);
}
W5500::~W5500() { }
// 复位(软硬兼施)
void W5500::Reset()
{
if(nRest)
{
*nRest = false; // 低电平有效
Sys.Delay(600); // 最少500us
debug_printf("硬件复位 \r\n");
*nRest = true;
}
SoftwareReset();
//Sys.Sleep(1500);
}
// 软件复位
void W5500::SoftwareReset()
{
debug_printf("软件复位 \r\n");
Frame frame;
frame.Address = 0x00000;
frame.BSB = 0x00; // 直接赋值简单暴力
T_MR mr;
mr.Init();
mr.RST = 1 ;
frame.Data.Write<byte>(mr.ToByte());
WriteFrame(frame);
}
// 初始化
void W5500::Init()
{
_Lock = 0;
_spi = NULL;
nRest = NULL;
memset(&General_reg,0,sizeof(General_reg));
memset(&_socket,NULL,sizeof(_socket));
PhaseOM = 0x00;
RX_FREE_SIZE = 0x16;
TX_FREE_SIZE = 0x16;
IsDhcpIp = 0; // IP 本地ip不是dhcp获得的
}
// 初始化
void W5500::Init(Spi* spi, Pin irq, OutputPort* rst)
{
if(rst) nRest = rst;
if(irq != P0)
{
// 中断引脚初始化
debug_printf("\r\nW5500::Init IRQ = P%c%d\r\n",_PIN_NAME(irq));
_IRQ.ShakeTime = 0;
_IRQ.Floating = false;
_IRQ.PuPd = InputPort::PuPd_UP;
_IRQ.Set(irq);
_IRQ.Register(OnIRQ, this);
}
if(spi)
_spi = spi;
else
{
debug_printf("SPI ERROR\r\n");
return;
}
// 提前打开 后面少费时间
_spi->Open();
// 复位
Reset();
// 读硬件版本
Frame frame;
frame.Address = 0x0039;
frame.BSB = 0x00;
ReadFrame(frame,1);
byte version = frame.Data.Read<byte>();
debug_printf("Hard Vision: %02X\r\n",version);
// 读所有寄存器
//Frame frame;
//frame.BSB = 0x00;
frame.Address = 0x0000;
frame.Data.SetPosition(0);
ReadFrame(frame,sizeof(General_reg));
// 同步寄存器值到 General_reg
frame.Data.Read((byte *)&General_reg,0,sizeof(General_reg));
}
// 网卡状态输出
void W5500::StateShow()
{
debug_printf("\r\nW5500 State:\r\n");
debug_printf("MR (模式): 0x%02X ",General_reg.MR);
T_MR mr;
mr.Init(General_reg.MR);
debug_printf("WOL: %d ",mr.WOL);
debug_printf("PB: %d ",mr.PB);
debug_printf("PPPoE: %d ",mr.PPPoE);
debug_printf("FARP: %d ",mr.FARP);
debug_printf("\r\n");
debug_printf("GAR (网关地址): %d.%d.%d.%d\r\n",General_reg.GAR[0],General_reg.GAR[1],General_reg.GAR[2],General_reg.GAR[3]);
debug_printf("SUBR (子网掩码): %d.%d.%d.%d\r\n",General_reg.SUBR[0],General_reg.SUBR[1],General_reg.SUBR[2],General_reg.SUBR[3]);
debug_printf("SHAR (源MAC地址): %02X-%02X-%02X-%02X-%02X-%02X\r\n",General_reg.SHAR[0],General_reg.SHAR[1],General_reg.SHAR[2],General_reg.SHAR[3],General_reg.SHAR[4],General_reg.SHAR[5]);
debug_printf("SIPR (源IP地址): %d.%d.%d.%d\r\n",General_reg.SIPR[0],General_reg.SIPR[1],General_reg.SIPR[2],General_reg.SIPR[3]);
debug_printf("INTLEVEL(中断低电平时间): 0x%02X%02X\r\n",General_reg.INTLEVEL[1],General_reg.INTLEVEL[0]); // 回头计算一下
debug_printf("IMR (中断屏蔽): 0x%02X ",General_reg.IMR);
T_IR imr;
imr.Init(General_reg.MR);
debug_printf("CONFLICT: %d ",imr.CONFLICT);
debug_printf("UNREACH: %d ",imr.UNREACH);
debug_printf("PPPoE: %d ",imr.PPPoE);
debug_printf("MP: %d ",imr.MP);
debug_printf("\r\n");
debug_printf("SIMR (Socket中断屏蔽): 0x%02X\r\n",General_reg.SIMR);
debug_printf("RTR (重试时间): 0x%02X%02X\r\n",General_reg.RTR[1],General_reg.RTR[0]); // 回头计算一下
debug_printf("RCR (重试计数): %d 次\r\n",General_reg.RCR);
// 暂且不输出的
// byte PTIMER; // PPP 连接控制协议请求定时寄存器 0x001c
// byte PMAGIC; // PPP 连接控制协议幻数寄存器 0x001d
// byte PHAR[6]; // PPPoE 模式下目标 MAC 寄存器 0x001e
// byte PSID[2]; // PPPoE 模式下会话 ID 寄存器 0x0024
// byte PMRU[2]; // PPPoE 模式下最大接收单元 0x0026
// byte UIPR[4]; // 无法抵达 IP 地址寄存器【只读】 0x0028
// byte UPORTR[2]; // 无法抵达端口寄存器【只读】 0x002c
PhyStateShow();
}
// 输出物理链路层状态
void W5500::PhyStateShow()
{
T_PHYCFGR phy;
phy.Init(General_reg.PHYCFGR);
if(phy.OPMD)
{
debug_printf("PHY 模式由 OPMDC 配置\r\n");
switch(phy.OPMDC)
{
case 0 : debug_printf(" 10BI半双工关闭自动协商\r\n");break;
case 1 : debug_printf(" 10BI全双工关闭自动协商\r\n");break;
case 2 : debug_printf(" 100BI半双工关闭自动协商\r\n");break;
case 3 : debug_printf(" 100BI全双工关闭自动协商\r\n");break;
case 4 : debug_printf(" 100BI半双工启用自动协商\r\n");break;
case 7 : debug_printf(" 所有功能,启用自动协商\r\n");break;
}
}
else
{
debug_printf("PHY 模式由引脚配置\r\n");
}
if(phy.LNK)
{
debug_printf("已连接 ");
if(phy.SPD) { debug_printf("100Mpbs ");}
else { debug_printf("10Mpbs ");}
if(phy.DPX) { debug_printf("全双工");}
else { debug_printf("半双工");}
debug_printf("网络\r\n");
}
else
{
debug_printf("连接已断开\r\n");
}
}
bool W5500::WriteFrame(Frame& frame)
{
while(_Lock != 0)Sys.Sleep(0);
_Lock = 1;
SpiScope sc(_spi);
byte temp = frame.Address>>8; // 地址高位在前
_spi->Write(temp);
temp = frame.Address;
_spi->Write(temp);
CONFIG_Phase config_temp; // 配置读写和OM
config_temp.Init(frame.BSB<<3);
config_temp.OM = PhaseOM; // 类内整体
config_temp.RWB = 1; // 写
_spi->Write(config_temp.ToByte());
w5500_printf("W5500::WriteFrame Address: 0x%04X CONFIG_Phase: 0x%02X\r\n",frame.Address,config_temp.ToByte());
uint len = frame.Data.Position(); // 获取数据流内有效数据长度
w5500_printf("Data.Length: %d ",len);
w5500_printf("Data:0x");
frame.Data.SetPosition(0); // 移动游标到头部
for(uint i = 0;i < len;i ++)
{
byte temp = frame.Data.Read<byte>();
_spi->Write(temp);
w5500_printf("-%02X",temp);
}
w5500_printf("\r\n");
_Lock = 0;
return true;
}
bool W5500::ReadFrame(Frame& frame,uint length)
{
while(_Lock != 0)Sys.Sleep(0);
_Lock = 1;
SpiScope sc(_spi);
byte temp = frame.Address>>8; // 地址高位在前
_spi->Write(temp);
temp = frame.Address;
_spi->Write(temp);
CONFIG_Phase config_temp; // 配置读写和OM
config_temp.Init(frame.BSB<<3);
config_temp.OM = PhaseOM; // 类内配置
config_temp.RWB = 0; // 读
//frame.Config = config_temp.ToByte();
_spi->Write(config_temp.ToByte());
w5500_printf("W5500::ReadFrame Address: 0x%04X CONFIG_Phase: 0x%02X\r\n",frame.Address,config_temp.ToByte());
w5500_printf("Read Length: %d Data: 0x",length);
for(uint i = 0;i < length; i++)
{
byte temp = _spi->Write(0x00);
w5500_printf("-%02X",temp);
frame.Data.Write<byte>(temp);
}
w5500_printf("\r\n");
frame.Data.SetPosition(0);
_Lock = 0;
return true;
}
// 测试PHY状态 返回是否LNK
bool W5500::CheckLnk()
{
Frame frame;
frame.Address = 0x002e;
frame.BSB = 0x00;
ReadFrame(frame,1);
General_reg.PHYCFGR = frame.Data.Read<byte>();
T_PHYCFGR phy;
phy.Init(General_reg.PHYCFGR);
return phy.LNK;
}
// 设置MAC地址
bool W5500::SetMac(MacAddress& mac) // 本地MAC
{
Frame frame;
frame.Address = (ushort)((uint)General_reg.SHAR - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
// 通用寄存器备份一份
memcpy(General_reg.SHAR,&mac.Value,6);
frame.Data.Write<ulong>(mac.Value);
frame.Data.SetPosition(frame.Data.Position() - 2); // 多了2字节 这里做个处理
WriteFrame(frame);
ReadFrame(frame,6);
MacAddress mac2(frame.Data.Read<ulong>());
if(mac2 == mac)
{
w5500_printf("MAC设置成功\r\n");
return true;
}
return false;
}
// “随机”一个MAC 并设置
void W5500::AutoMac()
{
MacAddress mac;
// 随机Mac前三个字节取自YWS的ASCII最后3个字节取自后三个ID
mac[0] = 'P'; mac[1] = 'M'; //mac[2] = 'W'; mac[3] = 'L';
for(int i=0; i< 4; i++)
mac[2 + i] = Sys.ID[3 - i];
// MAC地址首字节奇数表示组地址这里用偶数
SetMac(mac);
}
// 获取MAC地址
MacAddress W5500::Mac()
{
_mac.Value = (*(ulong *)* General_reg.SHAR) & 0xFFFFFFFFFFFFull;
return _mac;
}
// 设置网关IP
void W5500::SetGateway(IPAddress& ip)
{
memcpy(General_reg.GAR,&ip.Value,4);
Frame frame;
frame.Address = (ushort)((uint)General_reg.GAR - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<uint>(ip.Value);
WriteFrame(frame);
}
// 设置默认网关IP
void W5500::DefGateway()
{
const byte defip_[] = {192, 168, 0, 1};
IPAddress defip(defip_);
SetGateway(defip);
}
// 设置子网掩码
void W5500::SetIpMask(IPAddress& mask)
{
//short temp[2];
//temp[1] = __REV16(mask.Value);
//temp[0] = __REV16(mask.Value >> 16);
memcpy(General_reg.SUBR,&mask.Value,4);
Frame frame;
frame.Address = (ushort)((uint)General_reg.SUBR - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<uint>(mask.Value);
WriteFrame(frame);
}
// 设置默认子网掩码
void W5500::DefIpMask()
{
byte mask[4] = {255,255,255,0};
IPAddress defip(mask);
SetIpMask(defip);
}
// 设置自己的IP
void W5500::SetMyIp(IPAddress& ip)
{
memcpy(General_reg.SIPR,&ip.Value,4);
Frame frame;
frame.Address = (ushort)((uint)General_reg.SIPR - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<uint>(ip.Value);
WriteFrame(frame);
}
// 设置超时时间
void W5500::SetRetryTime(ushort ms)
{
// RTR 单位是100us 所以最大6553ms
if(ms > 6553)
{
debug_printf("不支持的时间范围!\r\n");
return;
}
ushort time = ms*10;
memcpy(General_reg.RTR,&time,2);
Frame frame;
frame.Address = (ushort)((uint)General_reg.RTR - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<ushort>(time);
WriteFrame(frame);
}
// 设置重试次数
void W5500::SetRetryCount(byte count)
{
General_reg.RCR = count;
Frame frame;
frame.Address = (ushort)((uint)General_reg.RCR - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<byte>(count);
WriteFrame(frame);
}
// 中断时低电平持续时间
void W5500::SetIrqLowLevelTime(int us)
{ // Time = ( INTLEVEL + 1) * PLL_CLK *4 PLL_CLK = 25M 还是150M
// 150M/4 26.67ns
// 50M/4 80ns
ushort intlevel = (us * 1000)/27;
//ushort intlevel = (us * 1000)/80;
memcpy(General_reg.INTLEVEL,&intlevel,2);
Frame frame;
frame.Address = (ushort)((uint)General_reg.INTLEVEL - (uint)&General_reg);
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<ushort>(intlevel);
WriteFrame(frame);
}
// 开启PING应答
void W5500::OpenPingACK()
{
T_MR mr;
mr.Init(General_reg.MR);
mr.PB = 0; // 0 是有响应
General_reg.MR = mr.ToByte();
Frame frame;
frame.Address = 0x0000;
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<byte>(mr.ToByte());
WriteFrame(frame);
}
// 开启PING应答
void W5500::ClosePingACK()
{
T_MR mr;
mr.Init(General_reg.MR);
mr.PB = 1; // 0 是有响应
General_reg.MR = mr.ToByte();
Frame frame;
frame.Address = 0x0000;
frame.BSB = 0x00; // 通用寄存器区
frame.Data.Write<byte>(mr.ToByte());
WriteFrame(frame);
}
// 恢复全部状态
void W5500::Recovery()
{
Frame frame;
frame.Address = 0x0000;
frame.BSB = 0x00;
frame.Data.Write<struct T_GenReg>(General_reg);
WriteFrame(frame);
// PHY 配置后要重启特殊处理
frame.Address = (ushort)((uint)General_reg.PHYCFGR - (uint)&General_reg);
T_PHYCFGR phy;
phy.Init(General_reg.PHYCFGR);
phy.RST = 0; // 0重启
frame.Data.SetPosition(0);
frame.Data.Write<byte>(phy.ToByte());
WriteFrame(frame);
for(int i = 0; i < 8; i++)
{
if(_socket[i] != NULL)
if(_socket[i]->Recovery != NULL)_socket[i]->Recovery();
}
}
byte W5500::GetSocket()
{
for(byte i = 0;i < 8;i ++)
{
if(_socket[i] == NULL)return i ;
}
debug_printf("没有空余的Socket可用了 !\r\n");
return 0xff;
}
// 注册 Socket
void W5500::Register(byte Index,HardwareSocket* handler)
{
if(_socket[Index] == NULL)
{
debug_printf("Index: %d 被注册 !\r\n",Index);
_socket[Index] = handler;
}
else
_socket[Index] = NULL;
}
// irq 中断处理部分
void W5500::OnIRQ(Pin pin, bool down, void* param)
{
if(down)return; // 低电平中断
W5500* send = (W5500*)param;
send->OnIRQ();
}
void W5500::OnIRQ()
{
// 读出中断状态
Frame frame;
frame.BSB = 0x00;
frame.Address = (ushort)((uint)General_reg.IR - (uint)&General_reg);
ReadFrame(frame,4);
frame.Read((byte *)&General_reg.IR,0,4);
// 分析IR
//T_IR ir;
//ir.Init(General_reg.IR);
//if(ir.CONFLICT)
//{
// // IP 冲突
//}
//if(ir.MP)
//{
// // 收到网络唤醒包
//}
//if(ir.UNREACH)
//{
// // 读出不可达 IP 的信息
// frame.Address = (ushort)((uint)General_reg.IR - (uint)&General_reg);
// frame.Data.SetPosition(0); // 丛头开始用
// ReadFrame(frame,6); // UIPR + UPORTR
// frame.Data.Read((byte *)General_reg.UIPR,0,6);
// debug_printf("IP 不可达: ");
// debug_printf("IP: %d.%d.%d.%d ",General_reg.UIPR[0],General_reg.UIPR[1],General_reg.UIPR[2],General_reg.UIPR[3]);
// debug_printf("Port: %d\r\n",*(ushort*)General_reg.UPORTR);
// // 处理..
//}
//if(ir.PPPoE) // PPPoE 连接不可达
byte temp = General_reg.SIR;
for(int i = 0;i < 8; i++)
{
if(temp & 0x01)
{
if(_socket[i])
_socket[i]->Process();
}
temp =>> 1;
if(temp = 0x00)break;
}
// 中断位清零 说明书说的不够清晰 有待完善
}
/****************************** 硬件Socket控制器 ************************************/
typedef struct : ByteStruct
{
byte Protocol:4; // Socket n 协议模式
// 0000 Closed
// 0001 TCP
// 0010 UDP
// 0100 MACRAW 【限定 Socket0 使用】
/* MACRAW 格式 *
* |***PACET_INFO**|********DATA_PACKET************** | *
* | PACKET_SIZE |DEC MAC|SOU MAC| TYPE | PAYLOAD | *
* | 2BYTE | 6BYTE | 6BYTE | 2BYTE|46-1500BYTE| */
byte UCASTB_MIP6B:1; // 【UCASTB】【MIP6B】
// [UCASTB] 单播阻塞 条件【UDP 模式】且MULTI=1
// 0关闭单播阻塞1开启单播阻塞
// [MIP6B] IPv6包阻塞 条件【MACRAW 模式】
// 0关闭IPv6包阻塞1开启IPv6包阻塞
byte ND_MC_MMB:1; // 【ND】【MC】【MMB】
// [ND] 使用无延时ACK 条件【TCP 模式】
// 0关闭无延时ACK选项需要RTR设定的超时时间做延时
// 1开启无延时ACK选项, 尽量没有延时的回复ACK
// [MC] IGMP版本 条件【UDP 模式】且MULTI=1
// 0IGMP 版本2
// 1IGMP 版本1
// [MMB] 多播阻塞 条件【MACRAW 模式】
// 0关闭多播阻塞
// 1开启多播阻塞
byte BCASTB:1; // 广播阻塞 条件【MACRAW 模式】或者【UDP 模式】
// 0关闭广播阻塞
// 1开启广播阻塞
byte MULTI_MFEN:1; // 【MULTI】【MFEN】
// [MULTI] UDP多播模式 条件【UDP 模式】
// 0关闭多播
// 1开启多播
// 注意使用多播模式需要Sn_DIPR Sn_DPORT 在通过Sn_CR 打开配置命令打开之前分别配置组播IP地址及端口号
// [MFEN] MAC 过滤 条件【MACRAW 模式】
// 0: 关闭 MAC 过滤,收到网络的所有包
// 1开启 MAC 过滤,只接收广播包和发给自己的包
}TSn_MR;
// Sn_CR 寄存器比较特殊
// 写入后会自动清零但命令任然在处理中为验证命令是否完成需检查Sn_IR或者SnSR寄存器
enum ESn_CR
{
OPEN = 0x01, // open 之后,检测 Sn_SR 的值
// Sn_MR.Protocol Sn_SR
// 【CLOSE】 -
// 【TCP】 【SOCK_INT】0X13
// 【UDP】 【SOCK_UDP】0X22
// 【MACRAW】 【SOCK_MACRAW】0X02
LISTEN = 0x02, // 只在【TCP 模式】下生效 LISTEN 会把 Socket 变成服务端等待TCP连接
// LISTEN 把 SOCK_INIT 变为 SOCK_LISTEN
// 当 SOCK 被连接成功 SOCK_LISTEN 变为 SOCK_ESTABLISHE,同时 Sn_IR.CON =1
// 当连接非法断开 Sn_IR.TIMEOUT =1 Sn_SR = SOCK_CLOSED
CONNECT = 0x04, // 只在【TCP 模式】下生效 Socket 作为客户端 对 Sn_DIPR:Sn_DPORT 发起连接
// 链接成功时 Sn_SR = SOCK_ESTABLISHE Sn_IR.CON =1
// 三种情况意味着请求失败 Sn_SR = SOCK_CLOSED
// 1.ARP 发生超时(Sn_IR.TIMEOUT =1)
// 2.没有收到 SYN/ACK 数据包(Sn_IR.TIMEOUT = 1)
// 3.收到RST数据包
DISCON = 0x08, // 只在【TCP 模式】下生效 FIN/ACK 断开机制断开连接 (不分 客户端,服务端)
// Sn_SR = SOCK_CLOSED
// 另外 当断开请求没有收到ACK时 Sn_IR.TIMEOUT =1
// 使用 CLOSE 命令来代替 DISCON 的话Sn_SR = SOCK_CLOSED 不再执行 FIN/ACK 断开机制
// 收到RST数据包 将无条件 Sn_SR = SOCK_CLOSED
CLOSE = 0x10, // 关闭Socket Sn_SR = SOCK_CLOSED
SEND = 0x20, // 发送 Socket TX内存中的所有缓冲数据
// 一般来说先通常自动ARP获取到MAC才进行传输
SEND_MAC = 0x21, // 只在【UDP 模式】下生效
// 使用Sn_DHAR 中的MAC进行发送不进行ARP
SEND_KEEP = 0x22, // 只在【TCP 模式】下生效 通过发送1字节在线心跳包检查连接状态
// 如果对方不能在超时计数期内反馈在线心跳包,这个连接将被关闭并触发中断
RECV = 0x40, // 通过使用接收读指针寄存器 Sn_RX_RD 来判定 接收缓存是否完成接收处理
};
//中断寄存器
typedef struct : ByteStruct
{
byte CON:1; // 连接成功 Sn_SR = SOCK_ESTABLISHE 此位生效
byte DISCON:1; // 连接中断 接收到对方 FIN/ACK 断开机制数据包时 此位生效
byte RECV:1; // 无论何时,接收到对方数据包,此位生效
byte TIMEOUT:1; // ARP TCP 超时被触发
byte SEND_OK:1; // 发送完成
byte Reserved:3;
}TSn_IR;
// 状态
enum ESn_SR
{
// 常规状态
SOCK_CLOSED = 0x00, // 关闭
SOCK_INIT = 0x13, // TCP 工作模式 OPEN 后状态
SOCK_LISTEN = 0x14, // TCP 服务端模式 等待 TCP 连接请求
SOCK_ESTABLISHE = 0x17, // TCP 连接OK 此状态下可以 Send 或者 Recv
SOCK_CLOSE_WAIT = 0x1C, // TCP 连接成功基础上 收到FIN 包可以进行数据传输若要全部关闭需要使用DISCON命令
SOCK_UDP = 0x22, // UDP 工作模式
SOCK_MACRAW = 0x02, // MACRAW 工作模式
// 中间状态
SOCK_SYNSENT = 0x15, // CONNECT 指令后(SOCK_INIT 状态后)SOCK_ESTABLISHE 状态前
SOCK_SYNRECV = 0x16, // 收到客户端连接请求包,发送了连接应答后,连接建立成功前
// SOCK_LISTEN 状态后SOCK_ESTABLISHE 状态前
// 如果超时 Sn_SR = SOCK_CLOSED Sn_IR.TIMEOUT =1
SOCK_FIN_WAIT = 0x18, // Socket 正在关闭
SOCK_CLOSING = 0x1A, // Socket 正在关闭
SOCK_TIME_WAIT = 0x1B, // Socket 正在关闭
SOCK_LAST_ACK = 0x1D, // Socket 被动关闭状态下,等待对方断开连接请求做出回应
// 超时或者成功收到断开请求都将 SOCK_CLOSED
};
HardwareSocket::HardwareSocket(W5500* phard)
{
if(!phard)
{
_THard = phard;
Index = _THard->GetSocket();
if(Index < 8)
_THard->Register(Index , this);
}
}
HardwareSocket::~HardwareSocket()
{
}