tcp/quic lab finished

This commit is contained in:
2025-12-25 14:33:29 +08:00
parent ac5b4bc15d
commit 200566e8fe
261 changed files with 2664 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
include_directories(
${PROJECT_SOURCE_DIR}/xnet/src/xnet/inc
)
aux_source_directory(. DIR_HELLO_SRCS)
add_library(xnet_lib ${DIR_HELLO_SRCS} )

View File

@@ -0,0 +1,317 @@
#include <stdio.h>
#include "enc28j60_device.h"
// 一共8KB的以太网缓存
static u8 ENC28J60BANK;
int NextPacketPtr;
//delay for ms unit
//suitable for crystal is 8MHz
//static function for ENC28J60
static void ENC28J60_delayms(u32 ms)
{
u16 i=0;
while(ms--)
{
for(i=0;i<8000;i++);
}
}
static inline void ENC28J60_cs_delayms(void)
{
}
//Reset ENC28J60
//Initialize SPI2 and related I/O for ENC28J60
static void ENC28J60_SPI2_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC, ENABLE );
// INT A7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource7);
EXTI_InitStructure.EXTI_Line= EXTI_Line7;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能外部中断所在的通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据结构体信息进行优先级初始化
//CS pin
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
//RST pin
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
//setup SPI2
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
SPI2_ReadWriteByte(0xff);
}
void ENC28J60_Reset(void)
{
ENC28J60_SPI2_Init(); //re-init SPI2
ENC28J60_RST_CLEAR(); //reset ENC28J60
ENC28J60_delayms(10);
ENC28J60_RST_SET(); //finish reset
ENC28J60_delayms(10);
}
//Read ENC28J60 register
//op: command
//addr: register address
//return: read out data
u8 ENC28J60_Read_Op(u8 op,u8 addr)
{
u8 dat=0;
ENC28J60_SELECT();
ENC28J60_cs_delayms();
dat=op|(addr&ADDR_MASK);
SPI2_ReadWriteByte(dat);
dat=SPI2_ReadWriteByte(0xFF);
//datasheet p.29, read two times to get MAC/MII register value
if(addr&0x80)dat=SPI2_ReadWriteByte(0xFF);
ENC28J60_cs_delayms();
ENC28J60_NO_SELECT();
return dat;
}
//Write ENC28J60 register
//op: command
//addr: register address
//data: parameter to write
void ENC28J60_Write_Op(u8 op,u8 addr,u8 data)
{
u8 dat = 0;
ENC28J60_SELECT();
ENC28J60_cs_delayms();
dat=op|(addr&ADDR_MASK);
SPI2_ReadWriteByte(dat);
SPI2_ReadWriteByte(data);
ENC28J60_cs_delayms();
ENC28J60_NO_SELECT();
}
//Read Rx buffer data from ENC28J60
//len: data length to read
//data: pointer to store data
void ENC28J60_Read_Buf(u32 len,u8* data)
{
ENC28J60_SELECT();
ENC28J60_cs_delayms();
SPI2_ReadWriteByte(ENC28J60_READ_BUF_MEM);
while(len--) {
*data++=(u8)SPI2_ReadWriteByte(0);
}
ENC28J60_cs_delayms();
ENC28J60_NO_SELECT();
}
//Write data to send via ENC28J60
//len: data length to send
//data: data pointer
void ENC28J60_Write_Buf(u32 len,u8* data)
{
ENC28J60_SELECT();
ENC28J60_cs_delayms();
SPI2_ReadWriteByte(ENC28J60_WRITE_BUF_MEM);
while(len--)
{
SPI2_ReadWriteByte(*data++);
}
ENC28J60_cs_delayms();
ENC28J60_NO_SELECT();
}
//Setup ENC28J60 register bank
//ban: Bank to be setup
void ENC28J60_Set_Bank(u8 bank)
{
if((bank&BANK_MASK)!=ENC28J60BANK)
{
ENC28J60_Write_Op(ENC28J60_BIT_FIELD_CLR,ECON1,(ECON1_BSEL1|ECON1_BSEL0));
ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,(bank&BANK_MASK)>>5);
ENC28J60BANK=(bank&BANK_MASK);
}
}
//Read ENC28J60 register
//addr: register address
//return: read out value
u8 ENC28J60_Read(u8 addr)
{
ENC28J60_Set_Bank(addr);//select bank
return ENC28J60_Read_Op(ENC28J60_READ_CTRL_REG,addr);
}
//Write ENC28J60 register
//addr: register address
void ENC28J60_Write(u8 addr,u8 data)
{
ENC28J60_Set_Bank(addr);
ENC28J60_Write_Op(ENC28J60_WRITE_CTRL_REG,addr,data);
}
//Write into PHY register of ENC28J60
//addr: register address
//data: parameter written into register
void ENC28J60_PHY_Write(u8 addr,u32 data)
{
u16 retry=0;
ENC28J60_Write(MIREGADR,addr);
ENC28J60_Write(MIWRL,data);
ENC28J60_Write(MIWRH,data>>8);
while((ENC28J60_Read(MISTAT)&MISTAT_BUSY)&&retry<0XFFF)retry++;//wait until PHY writing finish
}
//Setup ENC28J60
//macaddr: assigned MAC address
//return: 0=success, 1=failed
u8 ENC28J60_Init(u8* macaddr)
{
u16 retry=0;
ENC28J60_Reset();
ENC28J60_Write_Op(ENC28J60_SOFT_RESET,0,ENC28J60_SOFT_RESET); //software reset
while(!(ENC28J60_Read(ESTAT)&ESTAT_CLKRDY)&&retry<500) //wait until clock is stable
{
retry++;
ENC28J60_delayms(1);
};
if(retry>=500)return 1;//initialization failed
//set Rx buffer address with 8k capacity
NextPacketPtr=RXSTART_INIT;
//初始化接收缓冲区,设置接收起始地址
ENC28J60_Write(ERXSTL,RXSTART_INIT&0xFF);
ENC28J60_Write(ERXSTH,RXSTART_INIT>>8);
//设置接收读指针指向地址
ENC28J60_Write(ERXRDPTL, RXSTART_INIT &0xFF);
ENC28J60_Write(ERXRDPTH, RXSTART_INIT>>8);
//设置接收缓冲区的末尾地址
ENC28J60_Write(ERXNDL,RXSTOP_INIT&0xFF);
ENC28J60_Write(ERXNDH,RXSTOP_INIT>>8);
//设置发送缓冲区的起始地址
ENC28J60_Write(ETXSTL,TXSTART_INIT&0xFF);
ENC28J60_Write(ETXSTH,TXSTART_INIT>>8);
//setup "eno of tx" byte
ENC28J60_Write(ETXNDL,TXSTOP_INIT&0xFF);
ENC28J60_Write(ETXNDH,TXSTOP_INIT>>8);
ENC28J60_Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
ENC28J60_Write(EPMM0,0x3f);
ENC28J60_Write(EPMM1,0x30);
ENC28J60_Write(EPMCSL,0xf9);
ENC28J60_Write(EPMCSH,0xf7);
//MAC接收使能下行程序段表示使能MAC接收使能IEEE流量控制
ENC28J60_Write(MACON1,MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
// bring MAC out of reset
ENC28J60_Write(MACON2,0x00); //MACON2清零让MAC退出复位状态
// enable automatic padding to 60bytes and CRC operations
ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
// set inter-frame gap (non-back-to-back)
ENC28J60_Write(MAIPGL,0x12);
ENC28J60_Write(MAIPGH,0x0C);
// set inter-frame gap (back-to-back)
ENC28J60_Write(MABBIPG,0x15);
// Set the maximum packet size which the controller will accept
// Do not send packets longer than MAX_FRAMELEN:
ENC28J60_Write(MAMXFLL,MAX_FRAMELEN&0xFF);
ENC28J60_Write(MAMXFLH,MAX_FRAMELEN>>8);
// do bank 3 stuff
// write MAC address
// NOTE: MAC address in ENC28J60 is byte-backward
ENC28J60_Write(MAADR5,macaddr[0]);
ENC28J60_Write(MAADR4,macaddr[1]);
ENC28J60_Write(MAADR3,macaddr[2]);
ENC28J60_Write(MAADR2,macaddr[3]);
ENC28J60_Write(MAADR1,macaddr[4]);
ENC28J60_Write(MAADR0,macaddr[5]);
//setup PHY as Duplex
ENC28J60_PHY_Write(PHCON1,PHCON1_PDPXMD);
// no loopback of transmitted frames 禁止环回
//HDLDISPHY 半双工环回禁止位
ENC28J60_PHY_Write(PHCON2,PHCON2_HDLDIS);
// switch to bank 0
ENC28J60_Set_Bank(ECON1);
// enable interrutps
ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,EIE,EIE_INTIE|EIE_PKTIE);
// enable packet reception
ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,ECON1_RXEN);
if(ENC28J60_Read(MAADR5)== macaddr[0]) {
ENC28J60_delayms(10);
return 0;//initialization success
}
if(ENC28J60_Read(MAADR4)== macaddr[1]) {
ENC28J60_delayms(10);
return 0;//initialization success
}
if(ENC28J60_Read(MAADR3)== macaddr[2]) {
ENC28J60_delayms(10);
return 0;//initialization success
}
if(ENC28J60_Read(MAADR2)== macaddr[3]) {
ENC28J60_delayms(10);
return 0;//initialization success
}
if(ENC28J60_Read(MAADR1)== macaddr[4]) {
ENC28J60_delayms(10);
return 0;//initialization success
}
if(ENC28J60_Read(MAADR0)== macaddr[5]) {
ENC28J60_delayms(10);
return 0;//initialization success
}
return -1;
}
//Read EREVID
u8 ENC28J60_Get_EREVID(void)
{
return ENC28J60_Read(EREVID);
}

View File

@@ -0,0 +1,294 @@
#ifndef _ENC28J60_H
#define _ENC28J60_H
//Include
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ENC28J60 Control Registers
// Control register definitions are a combination of address,
// bank number, and Ethernet/MAC/PHY indicator bits.
// - Register address (bits 0-4)
// - Bank number (bits 5-6)
// - MAC/PHY indicator (bit 7)
#define ADDR_MASK 0x1F
#define BANK_MASK 0x60
#define SPRD_MASK 0x80
// All-bank registers
#define EIE 0x1B
#define EIR 0x1C
#define ESTAT 0x1D
#define ECON2 0x1E
#define ECON1 0x1F
// Bank 0 registers
#define ERDPTL (0x00|0x00)
#define ERDPTH (0x01|0x00)
#define EWRPTL (0x02|0x00)
#define EWRPTH (0x03|0x00)
#define ETXSTL (0x04|0x00)
#define ETXSTH (0x05|0x00)
#define ETXNDL (0x06|0x00)
#define ETXNDH (0x07|0x00)
#define ERXSTL (0x08|0x00)
#define ERXSTH (0x09|0x00)
#define ERXNDL (0x0A|0x00)
#define ERXNDH (0x0B|0x00)
//ERXWRPTH:ERXWRPTL 寄存器定义硬件向FIFO 中
//的哪个位置写入其接收到的字节。 指针是只读的,在成
//功接收到一个数据包后,硬件会自动更新指针。 指针可
//用于判断FIFO 内剩余空间的大小。
#define ERXRDPTL (0x0C|0x00)
#define ERXRDPTH (0x0D|0x00)
#define ERXWRPTL (0x0E|0x00)
#define ERXWRPTH (0x0F|0x00)
#define EDMASTL (0x10|0x00)
#define EDMASTH (0x11|0x00)
#define EDMANDL (0x12|0x00)
#define EDMANDH (0x13|0x00)
#define EDMADSTL (0x14|0x00)
#define EDMADSTH (0x15|0x00)
#define EDMACSL (0x16|0x00)
#define EDMACSH (0x17|0x00)
// Bank 1 registers
#define EHT0 (0x00|0x20)
#define EHT1 (0x01|0x20)
#define EHT2 (0x02|0x20)
#define EHT3 (0x03|0x20)
#define EHT4 (0x04|0x20)
#define EHT5 (0x05|0x20)
#define EHT6 (0x06|0x20)
#define EHT7 (0x07|0x20)
#define EPMM0 (0x08|0x20)
#define EPMM1 (0x09|0x20)
#define EPMM2 (0x0A|0x20)
#define EPMM3 (0x0B|0x20)
#define EPMM4 (0x0C|0x20)
#define EPMM5 (0x0D|0x20)
#define EPMM6 (0x0E|0x20)
#define EPMM7 (0x0F|0x20)
#define EPMCSL (0x10|0x20)
#define EPMCSH (0x11|0x20)
#define EPMOL (0x14|0x20)
#define EPMOH (0x15|0x20)
#define EWOLIE (0x16|0x20)
#define EWOLIR (0x17|0x20)
#define ERXFCON (0x18|0x20)
#define EPKTCNT (0x19|0x20)
// Bank 2 registers
#define MACON1 (0x00|0x40|0x80)
#define MACON2 (0x01|0x40|0x80)
#define MACON3 (0x02|0x40|0x80)
#define MACON4 (0x03|0x40|0x80)
#define MABBIPG (0x04|0x40|0x80)
#define MAIPGL (0x06|0x40|0x80)
#define MAIPGH (0x07|0x40|0x80)
#define MACLCON1 (0x08|0x40|0x80)
#define MACLCON2 (0x09|0x40|0x80)
#define MAMXFLL (0x0A|0x40|0x80)
#define MAMXFLH (0x0B|0x40|0x80)
#define MAPHSUP (0x0D|0x40|0x80)
#define MICON (0x11|0x40|0x80)
#define MICMD (0x12|0x40|0x80)
#define MIREGADR (0x14|0x40|0x80)
#define MIWRL (0x16|0x40|0x80)
#define MIWRH (0x17|0x40|0x80)
#define MIRDL (0x18|0x40|0x80)
#define MIRDH (0x19|0x40|0x80)
// Bank 3 registers
#define MAADR1 (0x00|0x60|0x80)
#define MAADR0 (0x01|0x60|0x80)
#define MAADR3 (0x02|0x60|0x80)
#define MAADR2 (0x03|0x60|0x80)
#define MAADR5 (0x04|0x60|0x80)
#define MAADR4 (0x05|0x60|0x80)
#define EBSTSD (0x06|0x60)
#define EBSTCON (0x07|0x60)
#define EBSTCSL (0x08|0x60)
#define EBSTCSH (0x09|0x60)
#define MISTAT (0x0A|0x60|0x80)
#define EREVID (0x12|0x60)
#define ECOCON (0x15|0x60)
#define EFLOCON (0x17|0x60)
#define EPAUSL (0x18|0x60)
#define EPAUSH (0x19|0x60)
// PHY registers
#define PHCON1 0x00
#define PHSTAT1 0x01
#define PHHID1 0x02
#define PHHID2 0x03
#define PHCON2 0x10
#define PHSTAT2 0x11
#define PHIE 0x12
#define PHIR 0x13
#define PHLCON 0x14
// ENC28J60 ERXFCON Register Bit Definitions
#define ERXFCON_UCEN 0x80
#define ERXFCON_ANDOR 0x40
#define ERXFCON_CRCEN 0x20
#define ERXFCON_PMEN 0x10
#define ERXFCON_MPEN 0x08
#define ERXFCON_HTEN 0x04
#define ERXFCON_MCEN 0x02
#define ERXFCON_BCEN 0x01
// ENC28J60 EIE Register Bit Definitions
#define EIE_INTIE 0x80
#define EIE_PKTIE 0x40
#define EIE_DMAIE 0x20
#define EIE_LINKIE 0x10
#define EIE_TXIE 0x08
#define EIE_WOLIE 0x04
#define EIE_TXERIE 0x02
#define EIE_RXERIE 0x01
// ENC28J60 EIR Register Bit Definitions
#define EIR_PKTIF 0x40
#define EIR_DMAIF 0x20
#define EIR_LINKIF 0x10
#define EIR_TXIF 0x08
#define EIR_WOLIF 0x04
#define EIR_TXERIF 0x02
#define EIR_RXERIF 0x01
// ENC28J60 ESTAT Register Bit Definitions
#define ESTAT_INT 0x80
#define ESTAT_LATECOL 0x10
#define ESTAT_RXBUSY 0x04
#define ESTAT_TXABRT 0x02
#define ESTAT_CLKRDY 0x01
// ENC28J60 ECON2 Register Bit Definitions
#define ECON2_AUTOINC 0x80
#define ECON2_PKTDEC 0x40
#define ECON2_PWRSV 0x20
#define ECON2_VRPS 0x08
// ENC28J60 ECON1 Register Bit Definitions
#define ECON1_TXRST 0x80
#define ECON1_RXRST 0x40
#define ECON1_DMAST 0x20
#define ECON1_CSUMEN 0x10
#define ECON1_TXRTS 0x08
#define ECON1_RXEN 0x04
#define ECON1_BSEL1 0x02
#define ECON1_BSEL0 0x01
// ENC28J60 MACON1 Register Bit Definitions
#define MACON1_LOOPBK 0x10
#define MACON1_TXPAUS 0x08
#define MACON1_RXPAUS 0x04
#define MACON1_PASSALL 0x02
#define MACON1_MARXEN 0x01
// ENC28J60 MACON2 Register Bit Definitions
#define MACON2_MARST 0x80
#define MACON2_RNDRST 0x40
#define MACON2_MARXRST 0x08
#define MACON2_RFUNRST 0x04
#define MACON2_MATXRST 0x02
#define MACON2_TFUNRST 0x01
// ENC28J60 MACON3 Register Bit Definitions
#define MACON3_PADCFG2 0x80
#define MACON3_PADCFG1 0x40
#define MACON3_PADCFG0 0x20
#define MACON3_TXCRCEN 0x10
#define MACON3_PHDRLEN 0x08
#define MACON3_HFRMLEN 0x04
#define MACON3_FRMLNEN 0x02
#define MACON3_FULDPX 0x01
// ENC28J60 MICMD Register Bit Definitions
#define MICMD_MIISCAN 0x02
#define MICMD_MIIRD 0x01
// ENC28J60 MISTAT Register Bit Definitions
#define MISTAT_NVALID 0x04
#define MISTAT_SCAN 0x02
#define MISTAT_BUSY 0x01
// ENC28J60 PHY PHCON1 Register Bit Definitions
#define PHCON1_PRST 0x8000
#define PHCON1_PLOOPBK 0x4000
#define PHCON1_PPWRSV 0x0800
#define PHCON1_PDPXMD 0x0100
// ENC28J60 PHY PHSTAT1 Register Bit Definitions
#define PHSTAT1_PFDPX 0x1000
#define PHSTAT1_PHDPX 0x0800
#define PHSTAT1_LLSTAT 0x0004
#define PHSTAT1_JBSTAT 0x0002
// ENC28J60 PHY PHCON2 Register Bit Definitions
#define PHCON2_FRCLINK 0x4000
#define PHCON2_TXDIS 0x2000
#define PHCON2_JABBER 0x0400
#define PHCON2_HDLDIS 0x0100
// ENC28J60 Packet Control Byte Bit Definitions
#define PKTCTRL_PHUGEEN 0x08
#define PKTCTRL_PPADEN 0x04
#define PKTCTRL_PCRCEN 0x02
#define PKTCTRL_POVERRIDE 0x01
// SPI operation codes
#define ENC28J60_READ_CTRL_REG 0x00
#define ENC28J60_READ_BUF_MEM 0x3A
#define ENC28J60_WRITE_CTRL_REG 0x40
#define ENC28J60_WRITE_BUF_MEM 0x7A
#define ENC28J60_BIT_FIELD_SET 0x80
#define ENC28J60_BIT_FIELD_CLR 0xA0
#define ENC28J60_SOFT_RESET 0xFF
// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata
// buffer boundaries applied to internal 8K ram
// the entire available packet buffer space is allocated
//
// start with recbuf at 0/
#define RXSTART_INIT 0x0
// receive buffer end
#define RXSTOP_INIT 0x800
// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (0~1518 bytes)
#define TXSTART_INIT (0x1FFF-3*1518)
// stp TX buffer at end of mem
#define TXSTOP_INIT 0x1FFF
// max frame length which the conroller will accept:
#define MAX_FRAMELEN 1518 // (note: maximum ethernet frame length would be 1518)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static inline u8 SPI2_ReadWriteByte(u8 TxData)
{
//Fill output buffer with data
SPI2->DR = TxData;
//Wait for transmission to complete
while ((SPI2->SR & (SPI_I2S_FLAG_RXNE | SPI_I2S_FLAG_TXE)) == RESET) {}
while (SPI2->SR & SPI_I2S_FLAG_BSY) {}
//Return data from buffer
return SPI2->DR;
}
/*CS Pin Definition*/
#define ENC28J60_CS_PORT GPIOB
#define ENC28J60_CS_CLK RCC_APB2Periph_GPIOB
#define ENC28J60_CS_PIN GPIO_Pin_12
#define ENC28J60_NO_SELECT() GPIOB->BSRR = GPIO_Pin_12
#define ENC28J60_SELECT() GPIOB->BRR = GPIO_Pin_12
/*RST Pin Definition*/
#define ENC28J60_RST_PORT GPIOC
#define ENC28J60_RST_CLK RCC_APB2Periph_GPIOC
#define ENC28J60_RST_PIN GPIO_Pin_5
#define ENC28J60_RST_SET() GPIOC->BSRR = GPIO_Pin_5
#define ENC28J60_RST_CLEAR() GPIOC->BRR = GPIO_Pin_5
//SPI1初始化
void ENC28J60_Reset(void);
u8 ENC28J60_Read_Op(u8 op,u8 addr);
void ENC28J60_Write_Op(u8 op,u8 addr,u8 data);
void ENC28J60_Read_Buf(u32 len,u8* data);
void ENC28J60_Write_Buf(u32 len,u8* data);
void ENC28J60_Set_Bank(u8 bank);
u8 ENC28J60_Read(u8 addr);
void ENC28J60_Write(u8 addr,u8 data);
void ENC28J60_PHY_Write(u8 addr,u32 data);
u8 ENC28J60_Init(u8* macaddr);
u8 ENC28J60_Get_EREVID(void);
void ENC28J60_Packet_Send(u32 len,u8* packet);
u32 ENC28J60_Packet_Receive(u32 maxlen,u8* packet);
extern int NextPacketPtr;
#endif

View File

@@ -0,0 +1,298 @@
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include "pcap_device.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#define PCAP_MAC_ADDR_LEN 6
static int mac_is_zero(const uint8_t* mac_addr) {
if (mac_addr == NULL) {
return 1;
}
for (int i = 0; i < PCAP_MAC_ADDR_LEN; i++) {
if (mac_addr[i]) {
return 0;
}
}
return 1;
}
static int read_interface_mac(const char* if_name, uint8_t* mac_addr) {
if ((if_name == NULL) || (mac_addr == NULL)) {
return -1;
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
return -1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
close(fd);
return -1;
}
memcpy(mac_addr, (uint8_t*)ifr.ifr_hwaddr.sa_data, PCAP_MAC_ADDR_LEN);
close(fd);
return 0;
}
static int load_pcap_lib() {
return 0;
}
/**
* 找到指定IP地址的网卡名
* @param ip 物理网卡或者由虚拟软件生成的虚拟刚卡, 字符串形式,如"192.168.1.1"
* @param name_buf 找到的对应网卡名称
*/
static int pcap_find_device(const char* ip, char* name_buf) {
char err_buf[PCAP_ERRBUF_SIZE];
pcap_if_t* pcap_if_list = NULL;
struct in_addr dest_ip;
pcap_if_t* item;
inet_pton(AF_INET, ip, &dest_ip);
int err = pcap_findalldevs(&pcap_if_list, err_buf);
if (err < 0) {
pcap_freealldevs(pcap_if_list);
return -1;
}
for (item = pcap_if_list; item != NULL; item = item->next) {
if (item->addresses == NULL) {
continue;
}
for (struct pcap_addr* pcap_addr = item->addresses; pcap_addr != NULL; pcap_addr = pcap_addr->next) {
struct sockaddr_in* curr_addr;
struct sockaddr* sock_addr = pcap_addr->addr;
if (sock_addr->sa_family != AF_INET) {
continue;
}
curr_addr = ((struct sockaddr_in*)sock_addr);
if (curr_addr->sin_addr.s_addr == dest_ip.s_addr) {
strcpy(name_buf, item->name);
pcap_freealldevs(pcap_if_list);
return 0;
}
}
}
pcap_freealldevs(pcap_if_list);
return -1;
}
/*
* 显示所有的网络接口列表
*/
static int pcap_show_list(void) {
char err_buf[PCAP_ERRBUF_SIZE];
pcap_if_t* pcapif_list = NULL;
int count = 0;
// 查找所有的网络接口
int err = pcap_findalldevs(&pcapif_list, err_buf);
if (err < 0) {
fprintf(stderr, "pcap_show_list: find all net list failed:%s\n", err_buf);
pcap_freealldevs(pcapif_list);
return -1;
}
printf("pcap_show_list: card list\n");
// 遍历所有的可用接口,输出其信息
for (pcap_if_t* item = pcapif_list; item != NULL; item = item->next) {
if (item->addresses == NULL) {
continue;
}
for (struct pcap_addr* pcap_addr = item->addresses; pcap_addr != NULL; pcap_addr = pcap_addr->next) {
char str[INET_ADDRSTRLEN];
struct sockaddr_in* ip_addr;
struct sockaddr* sockaddr = pcap_addr->addr;
if (sockaddr->sa_family != AF_INET) {
continue;
}
ip_addr = (struct sockaddr_in*)sockaddr;
printf("card %d: IP:%s name: %s, \n\n",
count++,
item->description == NULL ? "" : item->description,
inet_ntop(AF_INET, &ip_addr->sin_addr, str, sizeof(str))
);
break;
}
}
pcap_freealldevs(pcapif_list);
if ((pcapif_list == NULL) || (count == 0)) {
fprintf(stderr, "pcap_show_list: no available card!\n");
return -1;
}
return 0;
}
/**
* 打开pcap设备接口
* @param ip 打开网卡的指定ip
* @param 给网卡设置mac
*/
pcap_t* pcap_device_open(const char* ip, uint8_t * mac_addr, uint8_t poll_mode) {
char err_buf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
bpf_u_int32 mask;
bpf_u_int32 net;
char filter_exp[256];
char name_buf[256];
pcap_t* pcap;
if (load_pcap_lib() < 0) {
fprintf(stderr, "pcap_open: load pcap dll failed! install it first\n");
return (pcap_t*)0;
}
if (pcap_find_device(ip, name_buf) < 0) {
fprintf(stderr, "pcap_open: no net card has ip: %s, use the following:\n", ip);
pcap_show_list();
return (pcap_t*)0;
}
if (mac_addr == NULL) {
fprintf(stderr, "pcap_open: mac address buffer is null\n");
return (pcap_t*)0;
}
if (mac_is_zero(mac_addr)) {
if (read_interface_mac(name_buf, mac_addr) < 0) {
fprintf(stderr, "pcap_open: failed to query mac address of %s, please configure it manually.\n", name_buf);
return (pcap_t*)0;
}
printf("pcap_open: detected mac %02x:%02x:%02x:%02x:%02x:%02x on %s\n",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
name_buf);
fflush(stdout);
} else {
if (read_interface_mac(name_buf, mac_addr) < 0) {
printf("pcap_open: failed to query mac, using configured value %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
fflush(stdout);
} else {
printf("pcap_open: overriding configured mac with detected value %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
fflush(stdout);
}
}
if (pcap_lookupnet(name_buf, &net, &mask, err_buf) == -1) {
printf("pcap_open: can't find use net card: %s\n", name_buf);
net = 0;
mask = 0;
}
pcap = pcap_open_live(name_buf, // 设置字符串
65536, // 要捕获的最大字节数
1, // 混杂模式
1, // 读取超时(以毫秒为单位)
err_buf);
if (pcap == NULL) {
fprintf(stderr, "pcap_open: create pcap failed %s\n net card name: %s\n", err_buf, name_buf);
fprintf(stderr, "Use the following:\n");
pcap_show_list();
return (pcap_t*)0;
}
// 非阻塞模式读取,程序中使用查询的方式读
if (pcap_setnonblock(pcap, 1, err_buf) != 0) {
fprintf(stderr, "pcap_open: set none block failed: %s\n", pcap_geterr(pcap));
return (pcap_t*)0;
}
// 只捕获输入,不要捕获自己发出去的
// 注win平台似乎不支持这个选项
if (pcap_setdirection(pcap, PCAP_D_IN) != 0) {
// fprintf(stderr, "pcap_open: set direction not suppor: %s\n", pcap_geterr(pcap));
}
// 只捕获发往本接口与广播的数据帧。相当于只处理发往这张网卡的包
sprintf(filter_exp,
"(ether dst %02x:%02x:%02x:%02x:%02x:%02x or ether broadcast) and (not ether src %02x:%02x:%02x:%02x:%02x:%02x)",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
printf("pcap_open: BPF filter: %s\n", filter_exp);
fflush(stdout);
if (pcap_compile(pcap, &fp, filter_exp, 0, net) == -1) {
printf("pcap_open: couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap));
return (pcap_t*)0;
}
if (pcap_setfilter(pcap, &fp) == -1) {
printf("pcap_open: couldn't install filter %s: %s\n", filter_exp, pcap_geterr(pcap));
return (pcap_t*)0;
}
printf("pcap_open: Filter installed successfully\n");
fflush(stdout);
return pcap;
}
/**
* 关闭Pcapif接口
*/
void pcap_device_close(pcap_t* pcap) {
if (pcap == (pcap_t *)0) {
fprintf(stderr, "pcap = 0");
pcap_show_list();
return;
}
pcap_close(pcap);
}
/**
* 向网络接口发送数据包
*/
uint32_t pcap_device_send(pcap_t* pcap, const uint8_t* buffer, uint32_t length) {
if (pcap_sendpacket(pcap, buffer, length) == -1) {
fprintf(stderr, "pcap send: send packet failed!:%s\n", pcap_geterr(pcap));
fprintf(stderr, "pcap send: pcaket size %d\n", length);
return 0;
}
return 0;
}
/**
* 从网络接口读取数据包
*/
uint32_t pcap_device_read(pcap_t* pcap, uint8_t* buffer, uint32_t length) {
int err;
struct pcap_pkthdr* pkthdr;
const uint8_t* pkt_data;
err = pcap_next_ex(pcap, &pkthdr, &pkt_data);
if (err == 0) {
return 0;
} else if (err == 1) { // 1 - 成功读取数据包, 0 - 没有数据包,其它值-出错
memcpy(buffer, pkt_data, pkthdr->len);
return pkthdr->len;
}
fprintf(stderr, "pcap_read: reading packet failed!:%s", pcap_geterr(pcap));
return 0;
}

View File

@@ -0,0 +1,18 @@
#ifndef PCAP_DRIVER_H
#define PCAP_DRIVER_H
#include <pcap.h>
#include <stdint.h>
// 主-次版本号
#define NPCAP_VERSION_M 0
#define NPCAP_VERSION_N 9986
typedef void (*irq_handler_t)(void* arg, uint8_t is_rx, const uint8_t* data, uint32_t size);
pcap_t* pcap_device_open(const char* ip, uint8_t *mac_addr, uint8_t poll_mode);
void pcap_device_close(pcap_t* pcap);
uint32_t pcap_device_send(pcap_t* pcap, const uint8_t* buffer, uint32_t length);
uint32_t pcap_device_read(pcap_t* pcap, uint8_t* buffer, uint32_t length);
#endif //PCAP_DRIVER_H