105
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
/********************************** (C) COPYRIGHT ************* ******************
|
||||
* File Name : eth_driver.h
|
||||
* Author : WCH
|
||||
* Version : V1.3.0
|
||||
* Date : 2022/06/02
|
||||
* Description : This file contains the headers of the ETH Driver.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __ETH_DRIVER__
|
||||
#define __ETH_DRIVER__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "wchnet.h"
|
||||
|
||||
/* 1: interrupt 0: polling in RMII or RGMII mode */
|
||||
#define LINK_STAT_ACQUISITION_METHOD 0
|
||||
|
||||
#define PHY_ADDRESS 1
|
||||
|
||||
#define ETH_DMARxDesc_FrameLengthShift 16
|
||||
|
||||
#define ROM_CFG_USERADR_ID 0x1FFFF7E8
|
||||
|
||||
#define PHY_LINK_TASK_PERIOD 50
|
||||
|
||||
#define PHY_ANLPAR_SELECTOR_FIELD 0x1F
|
||||
#define PHY_ANLPAR_SELECTOR_VALUE 0x01 /* 5B'00001 */
|
||||
|
||||
#define PHY_LINK_INIT 0x00
|
||||
#define PHY_LINK_SUC_P (1<<0)
|
||||
#define PHY_LINK_SUC_N (1<<1)
|
||||
#define PHY_LINK_WAIT_SUC (1<<7)
|
||||
|
||||
#define PHY_PN_SWITCH_P (0<<2)
|
||||
#define PHY_PN_SWITCH_N (1<<2)
|
||||
#define PHY_PN_SWITCH_AUTO (2<<2)
|
||||
|
||||
#ifndef WCHNETTIMERPERIOD
|
||||
#define WCHNETTIMERPERIOD 10 /* Timer period, in Ms. */
|
||||
#endif
|
||||
|
||||
#define GPIO_Output(a,b) \
|
||||
GPIO_InitStructure.GPIO_Pin = b;\
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;\
|
||||
GPIO_Init(a, &GPIO_InitStructure)
|
||||
|
||||
#define GPIO_Input(a,b) \
|
||||
GPIO_InitStructure.GPIO_Pin = b;\
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;\
|
||||
GPIO_Init(a, &GPIO_InitStructure)
|
||||
|
||||
#define QUERY_STAT_FLAG ((LastQueryPhyTime == (LocalTime / 1000)) ? 0 : 1)
|
||||
|
||||
#define ACCELERATE_LINK_PROCESS() do{\
|
||||
if((TRDetectStep < 2) && (ETH_ReadPHYRegister(gPHYAddress, PHY_ANLPAR) & PHY_ANLPAR_SELECTOR_FIELD))\
|
||||
LinkTaskPeriod = 0;\
|
||||
}while(0)
|
||||
|
||||
#define UPDATE_LINKTASKPERIOD() do{\
|
||||
if(TRDetectStep == 1)\
|
||||
{\
|
||||
RandVal = RandVal * 214017 + 2531017;\
|
||||
LinkTaskPeriod = RandVal%100 + 50;\
|
||||
}\
|
||||
else {\
|
||||
LinkTaskPeriod = 50;\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define PHY_RESTART_AUTONEGOTIATION() do{\
|
||||
RegVal = ETH_ReadPHYRegister(gPHYAddress, PHY_BCR);\
|
||||
RegVal &= ~0x01;\
|
||||
RegVal |= PHY_Restart_AutoNegotiation;\
|
||||
ETH_WritePHYRegister( gPHYAddress, PHY_BCR, RegVal);\
|
||||
RegVal = ETH_ReadPHYRegister(gPHYAddress, PHY_BCR);\
|
||||
RegVal |= 0x03 | PHY_Restart_AutoNegotiation;\
|
||||
ETH_WritePHYRegister( gPHYAddress, PHY_BCR, RegVal);\
|
||||
}while(0)
|
||||
|
||||
#define PHY_TR_SWITCH() do{\
|
||||
phy_mdix = ETH_ReadPHYRegister(gPHYAddress, PHY_MDIX);\
|
||||
if(phy_mdix & 0x01)\
|
||||
{\
|
||||
phy_mdix &= ~0x03;\
|
||||
phy_mdix |= 1 << 1;\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
phy_mdix &= ~0x03;\
|
||||
phy_mdix |= 1 << 0;\
|
||||
}\
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, phy_mdix);\
|
||||
PHY_RESTART_AUTONEGOTIATION();\
|
||||
}while(0)
|
||||
|
||||
#define PHY_TR_REVERSE() do{\
|
||||
if(phyStatus)\
|
||||
{\
|
||||
RegVal = ETH_ReadPHYRegister(gPHYAddress, PHY_MDIX);\
|
||||
if(RegVal & 0x01)\
|
||||
{\
|
||||
RegVal &= ~0x03;\
|
||||
RegVal |= 1 << 1;\
|
||||
}\
|
||||
else{\
|
||||
RegVal &= ~0x03;\
|
||||
RegVal |= 1 << 0;\
|
||||
}\
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, RegVal);\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define PHY_PN_SWITCH(PNMode) do{\
|
||||
if(PNMode == PHY_PN_SWITCH_AUTO)\
|
||||
{\
|
||||
phyPN = PHY_PN_SWITCH_AUTO;\
|
||||
}\
|
||||
else{\
|
||||
phyPN = (ETH_ReadPHYRegister(gPHYAddress, PHY_MDIX) & (~(0x03 << 2))) | PNMode;\
|
||||
}\
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, phyPN);\
|
||||
phyPN = PNMode;\
|
||||
PHY_RESTART_AUTONEGOTIATION();\
|
||||
}while(0)
|
||||
|
||||
#define PHY_NEGOTIATION_PARAM_INIT() do{\
|
||||
phyStatus = 0;\
|
||||
phySucCnt = 0;\
|
||||
phyLinkCnt = 0;\
|
||||
TRDetectStep = 0;\
|
||||
PhyPolarityDetect = 0;\
|
||||
phyLinkStatus = PHY_LINK_INIT;\
|
||||
phyPN = PHY_PN_SWITCH_AUTO;\
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, phyPN);\
|
||||
}while(0)
|
||||
|
||||
#define PHY_LINK_RESET() do{\
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_BCR, PHY_Reset);\
|
||||
PHY_NEGOTIATION_PARAM_INIT();\
|
||||
}while(0)
|
||||
|
||||
#define LAST_NEGO_STAT 1 //0:auto-negotiate 1:Parallel detection
|
||||
#define TURN_PN_POLARITY (1<<1) //0:P polarity 1:N polarity
|
||||
|
||||
extern ETH_DMADESCTypeDef *DMATxDescToSet;
|
||||
extern ETH_DMADESCTypeDef *DMARxDescToGet;
|
||||
extern SOCK_INF SocketInf[ ];
|
||||
|
||||
#define PHY_PAG_SEL 0x1F
|
||||
|
||||
void ETH_PHYLink( void );
|
||||
void WCHNET_ETHIsr( void );
|
||||
void WCHNET_MainTask( void );
|
||||
void ETH_LedConfiguration(void);
|
||||
void ETH_Init( uint8_t *macAddr );
|
||||
void ETH_LedLinkSet( uint8_t mode );
|
||||
void ETH_LedDataSet( uint8_t mode );
|
||||
void WCHNET_TimeIsr( uint16_t timperiod );
|
||||
void ETH_Configuration( uint8_t *macAddr );
|
||||
uint8_t ETH_LibInit( uint8_t *ip, uint8_t *gwip, uint8_t *mask, uint8_t *macaddr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,940 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : eth_driver.c
|
||||
* Author : WCH
|
||||
* Version : V1.3.0
|
||||
* Date : 2022/06/02
|
||||
* Description : eth program body.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "string.h"
|
||||
#include "eth_driver.h"
|
||||
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB]; /* MAC receive descriptor, 4-byte aligned*/
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMATxDscrTab[ETH_TXBUFNB]; /* MAC send descriptor, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) uint8_t MACRxBuf[ETH_RXBUFNB*ETH_RX_BUF_SZE]; /* MAC receive buffer, 4-byte aligned */
|
||||
__attribute__((__aligned__(4))) uint8_t MACTxBuf[ETH_TXBUFNB*ETH_TX_BUF_SZE]; /* MAC send buffer, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) SOCK_INF SocketInf[WCHNET_MAX_SOCKET_NUM]; /* Socket information table, 4-byte alignment */
|
||||
const uint16_t MemNum[8] = {WCHNET_NUM_IPRAW,
|
||||
WCHNET_NUM_UDP,
|
||||
WCHNET_NUM_TCP,
|
||||
WCHNET_NUM_TCP_LISTEN,
|
||||
WCHNET_NUM_TCP_SEG,
|
||||
WCHNET_NUM_IP_REASSDATA,
|
||||
WCHNET_NUM_PBUF,
|
||||
WCHNET_NUM_POOL_BUF
|
||||
};
|
||||
const uint16_t MemSize[8] = {WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IPRAW_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_UDP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB_LISTEN),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_SEG),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IP_REASSDATA),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_POOL_BUF)
|
||||
};
|
||||
__attribute__((__aligned__(4)))uint8_t Memp_Memory[WCHNET_MEMP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_Heap_Memory[WCHNET_RAM_HEAP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_ArpTable[WCHNET_RAM_ARP_TABLE_SIZE];
|
||||
|
||||
uint16_t gPHYAddress;
|
||||
uint32_t volatile LocalTime;
|
||||
uint32_t ChipId = 0;
|
||||
|
||||
ETH_DMADESCTypeDef *pDMARxSet;
|
||||
ETH_DMADESCTypeDef *pDMATxSet;
|
||||
|
||||
/* PHY negotiation function */
|
||||
uint8_t phyLinkStatus = 0;
|
||||
uint8_t phyStatus = 0;
|
||||
uint8_t phyLinkCnt = 0;
|
||||
uint8_t phySucCnt = 0;
|
||||
uint8_t phyPN = PHY_PN_SWITCH_AUTO;
|
||||
uint8_t TRDetectStep = 0;
|
||||
uint8_t TRDetectCnt = 0;
|
||||
uint8_t LinkTaskPeriod = 50;
|
||||
uint32_t RandVal = 0;
|
||||
uint8_t volatile phyLinkReset;
|
||||
uint32_t volatile phyLinkTime;
|
||||
|
||||
/* PHY receive processing */
|
||||
uint8_t ReInitMACFlag = 0;
|
||||
uint8_t PhyPolarityDetect = 0;
|
||||
uint32_t LinkSuccTime = 0;
|
||||
|
||||
/*Parameters used when connecting to
|
||||
* devices that do not support auto-negotiation.*/
|
||||
uint8_t phyNegoStat = 0;
|
||||
uint32_t phyNegoLinkTime = 0;
|
||||
|
||||
extern u8 MACAddr[6];
|
||||
void ReInitMACReg(void);
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_GetMacAddr
|
||||
*
|
||||
* @brief Get the MAC address
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_GetMacAddr( uint8_t *p )
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *macaddr=(uint8_t *)(ROM_CFG_USERADR_ID+5);
|
||||
|
||||
for(i=0;i<6;i++)
|
||||
{
|
||||
*p = *macaddr;
|
||||
p++;
|
||||
macaddr--;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_TimeIsr
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_TimeIsr( uint16_t timperiod )
|
||||
{
|
||||
LocalTime += timperiod;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_PhyPNProcess
|
||||
*
|
||||
* @brief Phy PN Polarity related processing
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_PhyPNProcess(void)
|
||||
{
|
||||
uint32_t PhyVal;
|
||||
|
||||
LinkSuccTime = LocalTime;
|
||||
if((ETH->MMCRGUFCR == 0) && (ETH->MMCRFCECR >= 3))
|
||||
{
|
||||
PhyVal = ETH_ReadPHYRegister(gPHYAddress, PHY_MDIX);
|
||||
if((PhyVal >> 2) & 0x01)
|
||||
PhyVal &= ~(3 << 2); //change PHY PN Polarity to normal
|
||||
else
|
||||
PhyVal |= 1 << 2; //change PHY PN Polarity to reverse
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, PhyVal);
|
||||
ETH->MMCCR |= ETH_MMCCR_CR; //Counters Reset
|
||||
while(ETH->MMCCR & ETH_MMCCR_CR); //Wait for counters reset to complete
|
||||
}
|
||||
if(ETH->MMCRGUFCR != 0)
|
||||
{
|
||||
PhyPolarityDetect = 0;
|
||||
/* enable Filter function */
|
||||
ETH->MACFFR &= ~(ETH_ReceiveAll_Enable | ETH_PromiscuousMode_Enable);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_RecProcess
|
||||
*
|
||||
* @brief Receiving related processing
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_RecProcess(void)
|
||||
{
|
||||
if(((ChipId & 0xf0) == 0x20) && \
|
||||
((ETH->DMAMFBOCR & 0x1FFE0000) != 0))
|
||||
{
|
||||
ReInitMACReg();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_LinkProcess
|
||||
*
|
||||
* @brief link process.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_LinkProcess( void )
|
||||
{
|
||||
uint16_t phy_anlpar, phy_bmsr, phy_mdix, RegVal;
|
||||
|
||||
phy_anlpar = ETH_ReadPHYRegister(gPHYAddress, PHY_ANLPAR);
|
||||
phy_bmsr = ETH_ReadPHYRegister( gPHYAddress, PHY_BMSR);
|
||||
|
||||
if( (phy_anlpar&PHY_ANLPAR_SELECTOR_FIELD) )
|
||||
{
|
||||
if(TRDetectStep == 0)
|
||||
{
|
||||
TRDetectStep = 1;
|
||||
TRDetectCnt = 1;
|
||||
PHY_TR_SWITCH();
|
||||
LinkTaskPeriod = RandVal%100 + 50;
|
||||
return;
|
||||
}
|
||||
else if(TRDetectStep == 1)
|
||||
{
|
||||
TRDetectStep = 2;
|
||||
TRDetectCnt = 0;
|
||||
}
|
||||
if( !(phyLinkStatus&PHY_LINK_WAIT_SUC) )
|
||||
{
|
||||
if( phyPN == PHY_PN_SWITCH_AUTO )
|
||||
{
|
||||
PHY_PN_SWITCH(PHY_PN_SWITCH_P);
|
||||
}
|
||||
else if( phyPN == PHY_PN_SWITCH_P )
|
||||
{
|
||||
phyLinkStatus = PHY_LINK_WAIT_SUC;
|
||||
}
|
||||
else
|
||||
{
|
||||
phyLinkStatus = PHY_LINK_WAIT_SUC;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if((phySucCnt++ == 5) && ((phy_bmsr&(1<<5)) == 0))
|
||||
{
|
||||
phySucCnt = 0;
|
||||
if(phyPN == PHY_PN_SWITCH_N)
|
||||
PHY_PN_SWITCH(PHY_PN_SWITCH_P);
|
||||
else PHY_PN_SWITCH(PHY_PN_SWITCH_N);
|
||||
}
|
||||
}
|
||||
phyLinkCnt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(TRDetectStep == 1)
|
||||
{
|
||||
TRDetectCnt++;
|
||||
if(TRDetectCnt == 8)
|
||||
{
|
||||
TRDetectCnt = 0;
|
||||
TRDetectStep = 0;
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, PHY_PN_SWITCH_AUTO);
|
||||
return;
|
||||
}
|
||||
PHY_TR_SWITCH();
|
||||
return;
|
||||
}
|
||||
if( phyLinkStatus == PHY_LINK_WAIT_SUC )
|
||||
{
|
||||
if(phyLinkCnt++ == 15 )
|
||||
{
|
||||
phyLinkCnt = 0;
|
||||
phySucCnt = 0;
|
||||
TRDetectStep = 0;
|
||||
phyLinkStatus = PHY_LINK_INIT;
|
||||
PHY_PN_SWITCH(PHY_PN_SWITCH_AUTO);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( phyPN == PHY_PN_SWITCH_P )
|
||||
{
|
||||
if(phyLinkCnt++ == 4 )
|
||||
{
|
||||
phyLinkCnt = 0;
|
||||
PHY_PN_SWITCH(PHY_PN_SWITCH_N);
|
||||
}
|
||||
}
|
||||
else if( phyPN == PHY_PN_SWITCH_N )
|
||||
{
|
||||
if(phyLinkCnt++ == 15 )
|
||||
{
|
||||
phyLinkCnt = 0;
|
||||
phySucCnt = 0;
|
||||
TRDetectStep = 0;
|
||||
phyLinkStatus = PHY_LINK_INIT;
|
||||
PHY_PN_SWITCH(PHY_PN_SWITCH_AUTO);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(phyLinkCnt++ == (5000 / PHY_LINK_TASK_PERIOD))
|
||||
PHY_LINK_RESET( );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_HandlePhyNegotiation
|
||||
*
|
||||
* @brief Handle PHY Negotiation.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_HandlePhyNegotiation(void)
|
||||
{
|
||||
if(phyLinkReset) /* After the PHY link is disconnected, wait 500ms before turning on the PHY clock*/
|
||||
{
|
||||
if( LocalTime - phyLinkTime >= 500 )
|
||||
{
|
||||
phyLinkReset = 0;
|
||||
EXTEN->EXTEN_CTR |= EXTEN_ETH_10M_EN;
|
||||
PHY_LINK_RESET();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( !phyStatus ) /* Handling PHY Negotiation Exceptions */
|
||||
{
|
||||
ACCELERATE_LINK_PROCESS();
|
||||
if( LocalTime - phyLinkTime >= LinkTaskPeriod )
|
||||
{
|
||||
UPDATE_LINKTASKPERIOD();
|
||||
phyLinkTime = LocalTime;
|
||||
WCHNET_LinkProcess( );
|
||||
}
|
||||
if(ReInitMACFlag) ReInitMACFlag = 0;
|
||||
}
|
||||
else{ /* PHY link complete */
|
||||
if(ReInitMACFlag)
|
||||
{
|
||||
if( LocalTime - phyLinkTime >= 5 * PHY_LINK_TASK_PERIOD ){
|
||||
u32 phy_stat;
|
||||
ReInitMACFlag = 0;
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, PHY_BMSR);
|
||||
if((phy_stat&PHY_Linked_Status) == 0)
|
||||
{
|
||||
WCHNET_PhyStatus( phy_stat );
|
||||
PHY_LINK_RESET();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(PhyPolarityDetect)
|
||||
{
|
||||
if( LocalTime - LinkSuccTime >= 2 * PHY_LINK_TASK_PERIOD )
|
||||
{
|
||||
WCHNET_PhyPNProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_MainTask
|
||||
*
|
||||
* @brief library main task function
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_MainTask(void)
|
||||
{
|
||||
WCHNET_NetInput( ); /* Ethernet data input */
|
||||
WCHNET_PeriodicHandle( ); /* Protocol stack time-related task processing */
|
||||
WCHNET_HandlePhyNegotiation();
|
||||
WCHNET_RecProcess();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LedLinkSet
|
||||
*
|
||||
* @brief set eth link led,setbit 0 or 1,the link led turn on or turn off
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_LedLinkSet( uint8_t mode )
|
||||
{
|
||||
if( mode == LED_OFF )
|
||||
{
|
||||
GPIO_SetBits(GPIOC, GPIO_Pin_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO_ResetBits(GPIOC, GPIO_Pin_0);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LedDataSet
|
||||
*
|
||||
* @brief set eth data led,setbit 0 or 1,the data led turn on or turn off
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_LedDataSet( uint8_t mode )
|
||||
{
|
||||
if( mode == LED_OFF )
|
||||
{
|
||||
GPIO_SetBits(GPIOC, GPIO_Pin_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIO_ResetBits(GPIOC, GPIO_Pin_1);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LedConfiguration
|
||||
*
|
||||
* @brief set eth data and link led pin
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_LedConfiguration(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO={0};
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
|
||||
GPIO.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
|
||||
GPIO.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
GPIO.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_Init(GPIOC,&GPIO);
|
||||
ETH_LedDataSet(LED_OFF);
|
||||
ETH_LedLinkSet(LED_OFF);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_SetClock
|
||||
*
|
||||
* @brief Set ETH Clock(60MHZ).
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_SetClock(void)
|
||||
{
|
||||
RCC_PLL3Cmd(DISABLE);
|
||||
RCC_PREDIV2Config(RCC_PREDIV2_Div2); /* HSE = 8M */
|
||||
RCC_PLL3Config(RCC_PLL3Mul_15); /* 4M*15 = 60MHz */
|
||||
RCC_PLL3Cmd(ENABLE);
|
||||
while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLL3RDY));
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LinkUpCfg
|
||||
*
|
||||
* @brief When the PHY is connected, configure the relevant functions.
|
||||
*
|
||||
* @param regval BMSR register value
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_LinkUpCfg(uint16_t regval)
|
||||
{
|
||||
WCHNET_PhyStatus( regval );
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
phyStatus = PHY_Linked_Status;
|
||||
|
||||
/* disable Filter function */
|
||||
ETH->MACFFR |= (ETH_ReceiveAll_Enable | ETH_PromiscuousMode_Enable);
|
||||
|
||||
ETH->MMCCR |= ETH_MMCCR_CR; //Counters Reset
|
||||
while(ETH->MMCCR & ETH_MMCCR_CR); //Wait for counters reset to complete
|
||||
PhyPolarityDetect = 1;
|
||||
LinkSuccTime = LocalTime;
|
||||
ETH_Start( );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_PHYLink
|
||||
*
|
||||
* @brief Configure MAC parameters after the PHY Link is successful.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_PHYLink( void )
|
||||
{
|
||||
u16 phy_bsr, phy_stat, phy_anlpar, phy_bcr;
|
||||
|
||||
phy_bsr = ETH_ReadPHYRegister( gPHYAddress, PHY_BSR);
|
||||
phy_bcr = ETH_ReadPHYRegister( gPHYAddress, PHY_BCR);
|
||||
phy_anlpar = ETH_ReadPHYRegister( gPHYAddress, PHY_ANLPAR);
|
||||
|
||||
if(phy_bsr & PHY_Linked_Status) //LinkUp
|
||||
{
|
||||
if(phy_bcr & PHY_AutoNegotiation) //determine whether auto-negotiation is enable
|
||||
{
|
||||
if(phy_anlpar == 0)
|
||||
{
|
||||
if(phy_bsr & PHY_AutoNego_Complete)
|
||||
{
|
||||
ETH->MACCR &= ~ETH_Mode_FullDuplex;
|
||||
ETH_LinkUpCfg(phy_bsr);
|
||||
if((ChipId & 0xf0) == 0x20)
|
||||
{
|
||||
if(phyNegoStat & TURN_PN_POLARITY)
|
||||
{
|
||||
//select N polarity
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, PHY_PN_SWITCH_N);
|
||||
}
|
||||
else {
|
||||
//select P polarity
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_MDIX, PHY_PN_SWITCH_P);
|
||||
phyNegoStat |= LAST_NEGO_STAT;
|
||||
}
|
||||
phyNegoLinkTime = LocalTime;
|
||||
}
|
||||
}
|
||||
else{
|
||||
PHY_LINK_RESET();
|
||||
}
|
||||
}
|
||||
else {
|
||||
phyNegoStat = 0;
|
||||
if(phy_bsr & PHY_AutoNego_Complete)
|
||||
{
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, PHY_STATUS );
|
||||
if( phy_stat & (1<<2) )
|
||||
{
|
||||
ETH->MACCR |= ETH_Mode_FullDuplex;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (phy_anlpar&PHY_ANLPAR_SELECTOR_FIELD) != PHY_ANLPAR_SELECTOR_VALUE )
|
||||
{
|
||||
ETH->MACCR |= ETH_Mode_FullDuplex;
|
||||
}
|
||||
else
|
||||
{
|
||||
ETH->MACCR &= ~ETH_Mode_FullDuplex;
|
||||
}
|
||||
}
|
||||
ETH_LinkUpCfg(phy_bsr);
|
||||
}
|
||||
else{
|
||||
EXTEN->EXTEN_CTR &= ~EXTEN_ETH_10M_EN;
|
||||
phyLinkReset = 1;
|
||||
phyLinkTime = LocalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ETH->MACCR &= ~ETH_Mode_FullDuplex;
|
||||
ETH_LinkUpCfg(phy_bsr);
|
||||
}
|
||||
}
|
||||
else { //LinkDown
|
||||
WCHNET_PhyStatus( phy_bsr );
|
||||
EXTEN->EXTEN_CTR &= ~EXTEN_ETH_10M_EN;
|
||||
phyLinkReset = 1;
|
||||
phyLinkTime = LocalTime;
|
||||
if((ChipId & 0xf0) == 0x20)
|
||||
{
|
||||
if(phyNegoStat & LAST_NEGO_STAT)
|
||||
{
|
||||
if(LocalTime - phyNegoLinkTime < 100)
|
||||
{
|
||||
phyNegoLinkTime = 0;
|
||||
//Clear any existing error count values.
|
||||
ETH->DMAMFBOCR;
|
||||
phyNegoStat ^= TURN_PN_POLARITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ReInitMACReg
|
||||
*
|
||||
* @brief Reinitialize MAC register.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ReInitMACReg(void)
|
||||
{
|
||||
uint16_t timeout = 10000;
|
||||
uint16_t RegVal;
|
||||
uint32_t maccr, macmiiar, macffr, machthr, machtlr;
|
||||
uint32_t macfcr, macvlantr, dmaomr;
|
||||
|
||||
/* Wait for sending data to complete */
|
||||
while((ETH->DMASR & (7 << 20)) != ETH_DMA_TransmitProcess_Suspended);
|
||||
|
||||
PHY_TR_REVERSE();
|
||||
|
||||
/* Record the register value */
|
||||
macmiiar = ETH->MACMIIAR;
|
||||
maccr = ETH->MACCR;
|
||||
macffr = ETH->MACFFR;
|
||||
machthr = ETH->MACHTHR;
|
||||
machtlr = ETH->MACHTLR;
|
||||
macfcr = ETH->MACFCR;
|
||||
macvlantr = ETH->MACVLANTR;
|
||||
dmaomr = ETH->DMAOMR;
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((MACAddr[5]<<8) | MACAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(MACAddr[0] | (MACAddr[1]<<8) | (MACAddr[2]<<16) | (MACAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU |\
|
||||
ETH_DMA_IT_PHYLINK,\
|
||||
ENABLE);
|
||||
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
|
||||
ETH->MACMIIAR = macmiiar;
|
||||
ETH->MACCR = maccr;
|
||||
ETH->MACFFR = macffr;
|
||||
ETH->MACHTHR = machthr;
|
||||
ETH->MACHTLR = machtlr;
|
||||
ETH->MACFCR = macfcr;
|
||||
ETH->MACVLANTR = macvlantr;
|
||||
ETH->DMAOMR = dmaomr;
|
||||
|
||||
ETH_Start( );
|
||||
|
||||
PHY_TR_REVERSE();
|
||||
|
||||
if(!phyStatus)
|
||||
{
|
||||
PHY_LINK_RESET();
|
||||
}
|
||||
|
||||
ReInitMACFlag = 1;
|
||||
phyLinkTime = LocalTime;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_RegInit
|
||||
*
|
||||
* @brief ETH register initialization.
|
||||
*
|
||||
* @param ETH_InitStruct:initialization struct.
|
||||
* PHYAddress:PHY address.
|
||||
*
|
||||
* @return Initialization status.
|
||||
*/
|
||||
uint32_t ETH_RegInit( ETH_InitTypeDef* ETH_InitStruct, uint16_t PHYAddress )
|
||||
{
|
||||
/* Set the SMI interface clock, set as the main frequency divided by 42 */
|
||||
ETH->MACMIIAR = (uint32_t)ETH_MACMIIAR_CR_Div42;
|
||||
|
||||
/*------------------------ MAC register configuration -------------------------------------------*/
|
||||
ETH->MACCR = (uint32_t)(ETH_InitStruct->ETH_Watchdog |
|
||||
ETH_InitStruct->ETH_Jabber |
|
||||
ETH_InitStruct->ETH_InterFrameGap |
|
||||
ETH_InitStruct->ETH_ChecksumOffload |
|
||||
ETH_InitStruct->ETH_AutomaticPadCRCStrip |
|
||||
ETH_InitStruct->ETH_LoopbackMode |
|
||||
ETH_Internal_Pull_Up_Res_Enable);
|
||||
|
||||
ETH->MACFFR = (uint32_t)(ETH_InitStruct->ETH_ReceiveAll |
|
||||
ETH_InitStruct->ETH_SourceAddrFilter |
|
||||
ETH_InitStruct->ETH_PassControlFrames |
|
||||
ETH_InitStruct->ETH_BroadcastFramesReception |
|
||||
ETH_InitStruct->ETH_DestinationAddrFilter |
|
||||
ETH_InitStruct->ETH_PromiscuousMode |
|
||||
ETH_InitStruct->ETH_MulticastFramesFilter |
|
||||
ETH_InitStruct->ETH_UnicastFramesFilter);
|
||||
|
||||
ETH->MACHTHR = (uint32_t)ETH_InitStruct->ETH_HashTableHigh;
|
||||
ETH->MACHTLR = (uint32_t)ETH_InitStruct->ETH_HashTableLow;
|
||||
|
||||
ETH->MACFCR = (uint32_t)((ETH_InitStruct->ETH_PauseTime << 16) |
|
||||
ETH_InitStruct->ETH_UnicastPauseFrameDetect |
|
||||
ETH_InitStruct->ETH_ReceiveFlowControl |
|
||||
ETH_InitStruct->ETH_TransmitFlowControl);
|
||||
|
||||
ETH->MACVLANTR = (uint32_t)(ETH_InitStruct->ETH_VLANTagComparison |
|
||||
ETH_InitStruct->ETH_VLANTagIdentifier);
|
||||
|
||||
ETH->DMAOMR = (uint32_t)(ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame |
|
||||
ETH_InitStruct->ETH_TransmitStoreForward |
|
||||
ETH_InitStruct->ETH_ForwardErrorFrames |
|
||||
ETH_InitStruct->ETH_ForwardUndersizedGoodFrames);
|
||||
|
||||
/* Reset the physical layer */
|
||||
ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_Reset);
|
||||
ETH_WritePHYRegister(PHYAddress, PHY_MDIX, PHY_PN_SWITCH_AUTO);
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Configuration
|
||||
*
|
||||
* @brief Ethernet configure.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Configuration( uint8_t *macAddr )
|
||||
{
|
||||
ETH_InitTypeDef ETH_InitStructure;
|
||||
uint16_t timeout = 10000;
|
||||
|
||||
/* Enable Ethernet MAC clock */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | \
|
||||
RCC_AHBPeriph_ETH_MAC_Tx | \
|
||||
RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
|
||||
|
||||
gPHYAddress = PHY_ADDRESS;
|
||||
ETH_SetClock( );
|
||||
|
||||
/* Enable internal 10BASE-T PHY*/
|
||||
EXTEN->EXTEN_CTR |= EXTEN_ETH_10M_EN; /* Enable 10M Ethernet physical layer */
|
||||
|
||||
/* Reset ETHERNET on AHB Bus */
|
||||
ETH_DeInit();
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* ETHERNET Configuration */
|
||||
/*------------------------ MAC -----------------------------------*/
|
||||
ETH_InitStructure.ETH_Watchdog = ETH_Watchdog_Enable;
|
||||
ETH_InitStructure.ETH_Jabber = ETH_Jabber_Enable;
|
||||
ETH_InitStructure.ETH_InterFrameGap = ETH_InterFrameGap_96Bit;
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
|
||||
#else
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;
|
||||
#endif
|
||||
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
|
||||
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
|
||||
|
||||
/* Filter function configuration */
|
||||
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
|
||||
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
|
||||
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
|
||||
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_PassControlFrames = ETH_PassControlFrames_BlockAll;
|
||||
ETH_InitStructure.ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal;
|
||||
ETH_InitStructure.ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable;
|
||||
|
||||
ETH_InitStructure.ETH_HashTableHigh = 0x0;
|
||||
ETH_InitStructure.ETH_HashTableLow = 0x0;
|
||||
|
||||
/* VLan function configuration */
|
||||
ETH_InitStructure.ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit;
|
||||
ETH_InitStructure.ETH_VLANTagIdentifier = 0x0;
|
||||
|
||||
/* Flow Control function configuration */
|
||||
ETH_InitStructure.ETH_PauseTime = 0x0;
|
||||
ETH_InitStructure.ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable;
|
||||
ETH_InitStructure.ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable;
|
||||
ETH_InitStructure.ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable;
|
||||
|
||||
/*------------------------ DMA -----------------------------------*/
|
||||
/* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
|
||||
the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
|
||||
if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
|
||||
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
|
||||
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
|
||||
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Enable;
|
||||
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Enable;
|
||||
|
||||
/* Configure Ethernet */
|
||||
ETH_RegInit( Ð_InitStructure, gPHYAddress );
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((macAddr[5]<<8) | macAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(macAddr[0] | (macAddr[1]<<8) | (macAddr[2]<<16) | (macAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU |\
|
||||
ETH_DMA_IT_PHYLINK,\
|
||||
ENABLE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_TxPktChainMode
|
||||
*
|
||||
* @brief Ethernet sends data frames in chain mode.
|
||||
*
|
||||
* @param len Send data length
|
||||
* pBuff send buffer pointer
|
||||
*
|
||||
* @return Send status.
|
||||
*/
|
||||
uint32_t ETH_TxPktChainMode(uint16_t len, uint32_t *pBuff )
|
||||
{
|
||||
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
|
||||
if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
/* Return ERROR: OWN bit set */
|
||||
return ETH_ERROR;
|
||||
}
|
||||
/* Setting the Frame Length: bits[12:0] */
|
||||
DMATxDescToSet->ControlBufferSize = (len & ETH_DMATxDesc_TBS1);
|
||||
DMATxDescToSet->Buffer1Addr = (uint32_t)pBuff;
|
||||
|
||||
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS | ETH_DMATxDesc_CIC_TCPUDPICMP_Full;
|
||||
#else
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
|
||||
#endif
|
||||
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_OWN;
|
||||
|
||||
/* Clear TBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_TBUS;
|
||||
/* Resume DMA transmission*/
|
||||
ETH->DMATPDR = 0;
|
||||
|
||||
/* Update the ETHERNET DMA global Tx descriptor with next Tx descriptor */
|
||||
/* Chained Mode */
|
||||
/* Selects the next DMA Tx descriptor list for next buffer to send */
|
||||
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr);
|
||||
/* Return SUCCESS */
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_ETHIsr
|
||||
*
|
||||
* @brief Ethernet Interrupt Service Routine
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_ETHIsr(void)
|
||||
{
|
||||
uint32_t int_sta;
|
||||
|
||||
int_sta = ETH->DMASR;
|
||||
if (int_sta & ETH_DMA_IT_AIS)
|
||||
{
|
||||
if (int_sta & ETH_DMA_IT_RBU)
|
||||
{
|
||||
if((ChipId & 0xf0) == 0x10)
|
||||
{
|
||||
((ETH_DMADESCTypeDef *)(((ETH_DMADESCTypeDef *)(ETH->DMACHRDR))->Buffer2NextDescAddr))->Status = ETH_DMARxDesc_OWN;
|
||||
|
||||
/* Resume DMA reception */
|
||||
ETH->DMARPDR = 0;
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_RBU);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
|
||||
}
|
||||
|
||||
if( int_sta & ETH_DMA_IT_NIS )
|
||||
{
|
||||
if( int_sta & ETH_DMA_IT_R )
|
||||
{
|
||||
/*If you don't use the Ethernet library,
|
||||
* you can do some data processing operations here*/
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
|
||||
}
|
||||
if( int_sta & ETH_DMA_IT_T )
|
||||
{
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
|
||||
}
|
||||
if( int_sta & ETH_DMA_IT_PHYLINK)
|
||||
{
|
||||
ETH_PHYLink( );
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_PHYLINK);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Init
|
||||
*
|
||||
* @brief Ethernet initialization.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Init( uint8_t *macAddr )
|
||||
{
|
||||
Delay_Ms(100);
|
||||
ChipId = DBGMCU_GetCHIPID();
|
||||
ETH_LedConfiguration( );
|
||||
RandVal = (macAddr[3]^macAddr[4]^macAddr[5]) * 214017 + 2531017;
|
||||
ETH_Configuration( macAddr );
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
NVIC_EnableIRQ(ETH_IRQn);
|
||||
NVIC_SetPriority(ETH_IRQn, 0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LibInit
|
||||
*
|
||||
* @brief Ethernet library initialization program
|
||||
*
|
||||
* @return command status
|
||||
*/
|
||||
uint8_t ETH_LibInit( uint8_t *ip, uint8_t *gwip, uint8_t *mask, uint8_t *macaddr )
|
||||
{
|
||||
uint8_t s;
|
||||
struct _WCH_CFG cfg;
|
||||
|
||||
memset(&cfg,0,sizeof(cfg));
|
||||
cfg.TxBufSize = ETH_TX_BUF_SZE;
|
||||
cfg.TCPMss = WCHNET_TCP_MSS;
|
||||
cfg.HeapSize = WCHNET_MEM_HEAP_SIZE;
|
||||
cfg.ARPTableNum = WCHNET_NUM_ARP_TABLE;
|
||||
cfg.MiscConfig0 = WCHNET_MISC_CONFIG0;
|
||||
cfg.MiscConfig1 = WCHNET_MISC_CONFIG1;
|
||||
cfg.led_link = ETH_LedLinkSet;
|
||||
cfg.led_data = ETH_LedDataSet;
|
||||
cfg.net_send = ETH_TxPktChainMode;
|
||||
cfg.CheckValid = WCHNET_CFG_VALID;
|
||||
s = WCHNET_ConfigLIB(&cfg);
|
||||
if( s ){
|
||||
return (s);
|
||||
}
|
||||
s = WCHNET_Init(ip,gwip,mask,macaddr);
|
||||
ETH_Init( macaddr );
|
||||
return (s);
|
||||
}
|
||||
|
||||
/******************************** endfile @ eth_driver ******************************/
|
||||
@@ -0,0 +1,794 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : eth_driver.c
|
||||
* Author : WCH
|
||||
* Version : V1.3.0
|
||||
* Date : 2022/06/02
|
||||
* Description : eth program body.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "string.h"
|
||||
#include "eth_driver.h"
|
||||
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB]; /* MAC receive descriptor, 4-byte aligned*/
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMATxDscrTab[ETH_TXBUFNB]; /* MAC send descriptor, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) uint8_t MACRxBuf[ETH_RXBUFNB*ETH_RX_BUF_SZE]; /* MAC receive buffer, 4-byte aligned */
|
||||
__attribute__((__aligned__(4))) uint8_t MACTxBuf[ETH_TXBUFNB*ETH_TX_BUF_SZE]; /* MAC send buffer, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) SOCK_INF SocketInf[WCHNET_MAX_SOCKET_NUM]; /* Socket information table, 4-byte alignment */
|
||||
const uint16_t MemNum[8] = {WCHNET_NUM_IPRAW,
|
||||
WCHNET_NUM_UDP,
|
||||
WCHNET_NUM_TCP,
|
||||
WCHNET_NUM_TCP_LISTEN,
|
||||
WCHNET_NUM_TCP_SEG,
|
||||
WCHNET_NUM_IP_REASSDATA,
|
||||
WCHNET_NUM_PBUF,
|
||||
WCHNET_NUM_POOL_BUF
|
||||
};
|
||||
const uint16_t MemSize[8] = {WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IPRAW_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_UDP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB_LISTEN),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_SEG),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IP_REASSDATA),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_POOL_BUF)
|
||||
};
|
||||
__attribute__((__aligned__(4)))uint8_t Memp_Memory[WCHNET_MEMP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_Heap_Memory[WCHNET_RAM_HEAP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_ArpTable[WCHNET_RAM_ARP_TABLE_SIZE];
|
||||
|
||||
uint16_t gPHYAddress;
|
||||
uint32_t volatile LocalTime;
|
||||
|
||||
ETH_DMADESCTypeDef *pDMARxSet;
|
||||
ETH_DMADESCTypeDef *pDMATxSet;
|
||||
|
||||
volatile uint8_t LinkSta = 0; //0:Link down 1:Link up
|
||||
uint8_t LinkVaildFlag = 0; //0:invalid 1:valid
|
||||
uint8_t AccelerateLinkStep = 0;
|
||||
uint8_t AccelerateLinkTime = 0;
|
||||
uint8_t LinkProcessingStep = 0;
|
||||
uint32_t LinkProcessingTime = 0;
|
||||
uint32_t TaskExecutionTime = 0;
|
||||
u16 LastPhyStat = 0;
|
||||
u32 LastQueryPhyTime = 0;
|
||||
void ETH_LinkDownCfg(void);
|
||||
void PHY_FuncInit(void);
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_GetMacAddr
|
||||
*
|
||||
* @brief Get the MAC address
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_GetMacAddr( uint8_t *p )
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *macaddr = (uint8_t *)(ROM_CFG_USERADR_ID+5);
|
||||
|
||||
for(i=0;i<6;i++)
|
||||
{
|
||||
*p = *macaddr;
|
||||
p++;
|
||||
macaddr--;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_TimeIsr
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_TimeIsr( uint16_t timperiod )
|
||||
{
|
||||
LocalTime += timperiod;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_QueryPhySta
|
||||
*
|
||||
* @brief Query external PHY status
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_QueryPhySta(void)
|
||||
{
|
||||
u16 phy_stat;
|
||||
if(QUERY_STAT_FLAG){ /* Query the PHY link status every 1s */
|
||||
LastQueryPhyTime = LocalTime / 1000;
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BSR );
|
||||
if((phy_stat != LastPhyStat) && (phy_stat != 0xffff)){
|
||||
ETH_PHYLink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_CheckPHYPN
|
||||
*
|
||||
* @brief check PHY PN polarity
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_CheckPHYPN(uint16_t time)
|
||||
{
|
||||
u16 phy_stat;
|
||||
|
||||
//check PHY PN
|
||||
if((LinkProcessingStep == 0)||(LocalTime >= LinkProcessingTime))
|
||||
{
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0 );
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x10);
|
||||
if(phy_stat & (1<<12))
|
||||
{
|
||||
if(LinkProcessingStep == 0)
|
||||
{
|
||||
LinkProcessingStep = 1;
|
||||
LinkProcessingTime = LocalTime + time;
|
||||
}
|
||||
else {
|
||||
LinkProcessingStep = 0;
|
||||
LinkProcessingTime = 0;
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, PHY_ANER);
|
||||
if((time == 200) || ((phy_stat & 1) == 0))
|
||||
{
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0 );
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x16);
|
||||
phy_stat |= 1<<5;
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x16, phy_stat );
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x16);
|
||||
phy_stat &= ~(1<<5);
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x16, phy_stat );
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x1E); /* Clear the Interrupt status */
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LinkProcessingStep = 0;
|
||||
LinkProcessingTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_AccelerateLink
|
||||
*
|
||||
* @brief accelerate Link processing
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_AccelerateLink(void)
|
||||
{
|
||||
uint16_t phy_stat;
|
||||
|
||||
switch(AccelerateLinkStep)
|
||||
{
|
||||
case 0:
|
||||
AccelerateLinkStep++;
|
||||
AccelerateLinkTime = 0;
|
||||
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x18);
|
||||
phy_stat &= ~(1<<15);
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x18, phy_stat );
|
||||
|
||||
//power down
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
phy_stat |= (1<<11);
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, phy_stat );
|
||||
|
||||
//decrease Link Time
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x13, 0x4 );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(AccelerateLinkTime++ > 120) //unit:10ms,total time:1.2s~1.5s
|
||||
{
|
||||
AccelerateLinkStep++;
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x18);
|
||||
phy_stat |= 1<<15;
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x18, phy_stat );
|
||||
// power up
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
phy_stat &= ~(1<<11);
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, phy_stat );
|
||||
|
||||
Delay_Us(300);
|
||||
PHY_FuncInit();
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 99 );
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x19);
|
||||
if((phy_stat & 0xf) == 2)
|
||||
{
|
||||
AccelerateLinkStep++;
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x13, 0x0 );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*do nothing*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_CheckLinkVaild
|
||||
*
|
||||
* @brief check whether Link is valid
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_CheckLinkVaild(void)
|
||||
{
|
||||
uint16_t phy_stat, phy_bcr;
|
||||
|
||||
if(LinkVaildFlag == 0)
|
||||
{
|
||||
phy_bcr = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
if((phy_bcr & (1<<13)) == 0) //Do nothing if Link mode is 10M.
|
||||
{
|
||||
LinkVaildFlag = 1;
|
||||
LinkProcessingTime = 0;
|
||||
return;
|
||||
}
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0 );
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x10);
|
||||
if((phy_stat & (1<<9)) == 0)
|
||||
{
|
||||
LinkProcessingTime++;
|
||||
if(LinkProcessingTime == 5)
|
||||
{
|
||||
LinkProcessingTime = 0;
|
||||
phy_stat = ETH_ReadPHYRegister(gPHYAddress, PHY_BCR);
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_BCR, PHY_Reset );
|
||||
Delay_Us(100);
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_BCR, phy_stat );
|
||||
ETH_LinkDownCfg();
|
||||
}
|
||||
}
|
||||
else {
|
||||
LinkVaildFlag = 1;
|
||||
LinkProcessingTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_LinkProcessing
|
||||
*
|
||||
* @brief process Link stage task
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_LinkProcessing(void)
|
||||
{
|
||||
u16 phy_bcr;
|
||||
|
||||
if(LocalTime >= TaskExecutionTime)
|
||||
{
|
||||
TaskExecutionTime = LocalTime + 10; //execution cycle:10ms
|
||||
if(LinkSta == 0) //Link down
|
||||
{
|
||||
phy_bcr = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
if(phy_bcr & PHY_AutoNegotiation) //auto-negotiation is enabled
|
||||
{
|
||||
WCHNET_CheckPHYPN(300); //check PHY PN
|
||||
WCHNET_AccelerateLink(); //accelerate Link processing
|
||||
}
|
||||
else { //auto-negotiation is disabled
|
||||
if((phy_bcr & (1<<13)) == 0) // 10M
|
||||
{
|
||||
WCHNET_CheckPHYPN(200); //check PHY PN
|
||||
}
|
||||
}
|
||||
}
|
||||
else { //Link up
|
||||
WCHNET_CheckLinkVaild(); //check whether Link is valid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_MainTask
|
||||
*
|
||||
* @brief library main task function
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_MainTask(void)
|
||||
{
|
||||
WCHNET_NetInput( ); /* Ethernet data input */
|
||||
WCHNET_PeriodicHandle( ); /* Protocol stack time-related task processing */
|
||||
WCHNET_QueryPhySta(); /* Query external PHY status */
|
||||
WCHNET_LinkProcessing(); /* process Link stage task */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_SetClock
|
||||
*
|
||||
* @brief Set the Ethernet related clock
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_SetClock(void)
|
||||
{
|
||||
/* Only support HSE_VALUE: 8MHz.
|
||||
* If you select other HSE value,you should
|
||||
* change the configuration below*/
|
||||
RCC_PLL3Cmd(DISABLE);
|
||||
RCC_PREDIV2Config(RCC_PREDIV2_Div1); // HSE = 8M
|
||||
RCC_PLL3Config(RCC_PLL3Mul_12_5); // 8M*12.5 = 100MHz
|
||||
RCC_PLL3Cmd(ENABLE);
|
||||
while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLL3RDY));
|
||||
Delay_Us(300);//Wait for the PHY clock to stabilize
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_RMIIPinInit
|
||||
*
|
||||
* @brief PHY RMII interface GPIO initialization.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_RMIIPinInit(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE);
|
||||
GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII);
|
||||
GPIO_Output(GPIOD, GPIO_Pin_8); /* MDIO */
|
||||
GPIO_Output(GPIOE, GPIO_Pin_15); /* MDC */
|
||||
|
||||
GPIO_Output(GPIOE, GPIO_Pin_8); /* TXEN */
|
||||
GPIO_Output(GPIOE, GPIO_Pin_11); /* TXD0 */
|
||||
GPIO_Output(GPIOE, GPIO_Pin_10); /* TXD1 */
|
||||
|
||||
GPIO_Output(GPIOE, GPIO_Pin_12); /* REFCLK */
|
||||
GPIO_Input(GPIOE, GPIO_Pin_9); /* CRSDV */
|
||||
GPIO_Input(GPIOE, GPIO_Pin_14); /* RXD0 */
|
||||
GPIO_Input(GPIOE, GPIO_Pin_13); /* RXD1 */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LinkUpCfg
|
||||
*
|
||||
* @brief When the PHY is connected, configure the relevant functions.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_LinkUpCfg(void)
|
||||
{
|
||||
uint16_t phy_stat;
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR );
|
||||
/* PHY negotiation result */
|
||||
if(phy_stat & (1<<13)) /* 100M */
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
ETH->MACCR |= ETH_Speed_100M;
|
||||
}
|
||||
else /* 10M */
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
}
|
||||
if(phy_stat & (1<<8)) /* full duplex */
|
||||
{
|
||||
ETH->MACCR |= ETH_Mode_FullDuplex;
|
||||
}
|
||||
else /* half duplex */
|
||||
{
|
||||
ETH->MACCR &= ~ETH_Mode_FullDuplex;
|
||||
}
|
||||
|
||||
LinkSta = 1;
|
||||
AccelerateLinkStep = 0;
|
||||
LinkProcessingStep = 0;
|
||||
LinkProcessingTime = 0;
|
||||
ETH_Start( );
|
||||
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0 );
|
||||
phy_stat = 0x0;
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x13, phy_stat );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LinkDownCfg
|
||||
*
|
||||
* @brief When the PHY is disconnected, configure the relevant functions.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_LinkDownCfg(void)
|
||||
{
|
||||
LinkSta = 0;
|
||||
LinkVaildFlag = 0;
|
||||
LinkProcessingTime = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_PHYLink
|
||||
*
|
||||
* @brief Configure MAC parameters after the PHY Link is successful.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_PHYLink( void )
|
||||
{
|
||||
u32 phy_stat, phy_anlpar, phy_bcr;
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BSR );
|
||||
phy_anlpar = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_ANLPAR);
|
||||
phy_bcr = ETH_ReadPHYRegister( gPHYAddress, PHY_BCR);
|
||||
LastPhyStat = phy_stat;
|
||||
|
||||
WCHNET_PhyStatus( phy_stat );
|
||||
if(phy_stat & PHY_Linked_Status) //LinkUp
|
||||
{
|
||||
if(phy_bcr & PHY_AutoNegotiation)
|
||||
{
|
||||
if(phy_anlpar == 0)
|
||||
{
|
||||
ETH_LinkUpCfg();
|
||||
}
|
||||
else {
|
||||
if(phy_stat & PHY_AutoNego_Complete)
|
||||
{
|
||||
ETH_LinkUpCfg();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ETH_LinkUpCfg();
|
||||
}
|
||||
}
|
||||
else { //LinkDown
|
||||
/*Link down*/
|
||||
ETH_LinkDownCfg();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn PHY_FuncInit
|
||||
*
|
||||
* @brief PHY register initialization.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void PHY_FuncInit(void)
|
||||
{
|
||||
uint16_t regval;
|
||||
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x00 );
|
||||
/* Configure Repeater mode */
|
||||
regval = ETH_ReadPHYRegister(gPHYAddress, 28);
|
||||
regval |= 1<<13;
|
||||
ETH_WritePHYRegister(gPHYAddress, 28, regval );
|
||||
|
||||
/*rmii rx&tx clock change */
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x07 );
|
||||
regval = ETH_ReadPHYRegister( gPHYAddress, 16);
|
||||
regval &= ~(0xff<<4);
|
||||
regval |= 0x23<<4;
|
||||
ETH_WritePHYRegister(gPHYAddress, 16, regval );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_RegInit
|
||||
*
|
||||
* @brief ETH register initialization.
|
||||
*
|
||||
* @param ETH_InitStruct:initialization struct.
|
||||
* PHYAddress:PHY address.
|
||||
*
|
||||
* @return Initialization status.
|
||||
*/
|
||||
uint32_t ETH_RegInit( ETH_InitTypeDef* ETH_InitStruct, uint16_t PHYAddress )
|
||||
{
|
||||
/* Set the SMI interface clock, set as the main frequency divided by 42 */
|
||||
ETH->MACMIIAR = (uint32_t)ETH_MACMIIAR_CR_Div42;
|
||||
|
||||
/*------------------------ MAC register configuration -------------------------------------------*/
|
||||
ETH->MACCR = (uint32_t)(ETH_InitStruct->ETH_Watchdog |
|
||||
ETH_InitStruct->ETH_Jabber |
|
||||
ETH_InitStruct->ETH_InterFrameGap |
|
||||
ETH_InitStruct->ETH_ChecksumOffload |
|
||||
ETH_InitStruct->ETH_AutomaticPadCRCStrip |
|
||||
ETH_InitStruct->ETH_LoopbackMode);
|
||||
|
||||
ETH->MACFFR = (uint32_t)(ETH_InitStruct->ETH_ReceiveAll |
|
||||
ETH_InitStruct->ETH_SourceAddrFilter |
|
||||
ETH_InitStruct->ETH_PassControlFrames |
|
||||
ETH_InitStruct->ETH_BroadcastFramesReception |
|
||||
ETH_InitStruct->ETH_DestinationAddrFilter |
|
||||
ETH_InitStruct->ETH_PromiscuousMode |
|
||||
ETH_InitStruct->ETH_MulticastFramesFilter |
|
||||
ETH_InitStruct->ETH_UnicastFramesFilter);
|
||||
|
||||
ETH->MACHTHR = (uint32_t)ETH_InitStruct->ETH_HashTableHigh;
|
||||
ETH->MACHTLR = (uint32_t)ETH_InitStruct->ETH_HashTableLow;
|
||||
|
||||
ETH->MACFCR = (uint32_t)((ETH_InitStruct->ETH_PauseTime << 16) |
|
||||
ETH_InitStruct->ETH_UnicastPauseFrameDetect |
|
||||
ETH_InitStruct->ETH_ReceiveFlowControl |
|
||||
ETH_InitStruct->ETH_TransmitFlowControl);
|
||||
|
||||
ETH->MACVLANTR = (uint32_t)(ETH_InitStruct->ETH_VLANTagComparison |
|
||||
ETH_InitStruct->ETH_VLANTagIdentifier);
|
||||
|
||||
ETH->DMAOMR = (uint32_t)(ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame |
|
||||
ETH_InitStruct->ETH_TransmitStoreForward |
|
||||
ETH_InitStruct->ETH_ForwardErrorFrames |
|
||||
ETH_InitStruct->ETH_ForwardUndersizedGoodFrames);
|
||||
|
||||
/* Reset the physical layer */
|
||||
ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_Reset);
|
||||
Delay_Ms(1);
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Configuration
|
||||
*
|
||||
* @brief Ethernet configure.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Configuration( uint8_t *macAddr )
|
||||
{
|
||||
ETH_InitTypeDef ETH_InitStructure;
|
||||
uint16_t timeout = 10000;
|
||||
|
||||
/* Enable Ethernet MAC clock */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | \
|
||||
RCC_AHBPeriph_ETH_MAC_Tx | \
|
||||
RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
|
||||
|
||||
gPHYAddress = PHY_ADDRESS;
|
||||
|
||||
/* Enable RMII GPIO */
|
||||
ETH_RMIIPinInit();
|
||||
|
||||
/* Set the Ethernet related clock */
|
||||
ETH_SetClock();
|
||||
|
||||
/* Reset ETHERNET on AHB Bus */
|
||||
ETH_DeInit();
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* ETHERNET Configuration */
|
||||
/*------------------------ MAC -----------------------------------*/
|
||||
ETH_InitStructure.ETH_Watchdog = ETH_Watchdog_Enable;
|
||||
ETH_InitStructure.ETH_Jabber = ETH_Jabber_Enable;
|
||||
ETH_InitStructure.ETH_InterFrameGap = ETH_InterFrameGap_96Bit;
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
|
||||
#else
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;
|
||||
#endif
|
||||
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
|
||||
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
|
||||
|
||||
/* Filter function configuration */
|
||||
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
|
||||
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
|
||||
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
|
||||
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_PassControlFrames = ETH_PassControlFrames_BlockAll;
|
||||
ETH_InitStructure.ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal;
|
||||
ETH_InitStructure.ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable;
|
||||
|
||||
ETH_InitStructure.ETH_HashTableHigh = 0x0;
|
||||
ETH_InitStructure.ETH_HashTableLow = 0x0;
|
||||
|
||||
/* VLan function configuration */
|
||||
ETH_InitStructure.ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit;
|
||||
ETH_InitStructure.ETH_VLANTagIdentifier = 0x0;
|
||||
|
||||
/* Flow Control function configuration */
|
||||
ETH_InitStructure.ETH_PauseTime = 0x0;
|
||||
ETH_InitStructure.ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable;
|
||||
ETH_InitStructure.ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable;
|
||||
ETH_InitStructure.ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable;
|
||||
|
||||
/*------------------------ DMA -----------------------------------*/
|
||||
/* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
|
||||
the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
|
||||
if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
|
||||
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
|
||||
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
|
||||
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Enable;
|
||||
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Enable;
|
||||
/* Configure Ethernet */
|
||||
ETH_RegInit( Ð_InitStructure, gPHYAddress );
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((macAddr[5]<<8) | macAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(macAddr[0] | (macAddr[1]<<8) | (macAddr[2]<<16) | (macAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU,\
|
||||
ENABLE);
|
||||
|
||||
PHY_FuncInit();
|
||||
/*Reads the default value of the PHY_BSR register*/
|
||||
LastPhyStat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BSR );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_TxPktChainMode
|
||||
*
|
||||
* @brief Ethernet sends data frames in chain mode.
|
||||
*
|
||||
* @param len Send data length
|
||||
* pBuff send buffer pointer
|
||||
*
|
||||
* @return Send status.
|
||||
*/
|
||||
uint32_t ETH_TxPktChainMode(uint16_t len, uint32_t *pBuff )
|
||||
{
|
||||
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
|
||||
if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
/* Return ERROR: OWN bit set */
|
||||
return ETH_ERROR;
|
||||
}
|
||||
/* Setting the Frame Length: bits[12:0] */
|
||||
DMATxDescToSet->ControlBufferSize = (len & ETH_DMATxDesc_TBS1);
|
||||
DMATxDescToSet->Buffer1Addr = (uint32_t)pBuff;
|
||||
|
||||
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS | ETH_DMATxDesc_CIC_TCPUDPICMP_Full;
|
||||
#else
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
|
||||
#endif
|
||||
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_OWN;
|
||||
|
||||
/* Clear TBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_TBUS;
|
||||
/* Resume DMA transmission*/
|
||||
ETH->DMATPDR = 0;
|
||||
|
||||
/* Update the ETHERNET DMA global Tx descriptor with next Tx descriptor */
|
||||
/* Chained Mode */
|
||||
/* Selects the next DMA Tx descriptor list for next buffer to send */
|
||||
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr);
|
||||
/* Return SUCCESS */
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_ETHIsr
|
||||
*
|
||||
* @brief Ethernet Interrupt Service Routine
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_ETHIsr(void)
|
||||
{
|
||||
uint32_t int_sta;
|
||||
|
||||
int_sta = ETH->DMASR;
|
||||
if (int_sta & ETH_DMA_IT_AIS)
|
||||
{
|
||||
if (int_sta & ETH_DMA_IT_RBU)
|
||||
{
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_RBU);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
|
||||
}
|
||||
|
||||
if( int_sta & ETH_DMA_IT_NIS )
|
||||
{
|
||||
if( int_sta & ETH_DMA_IT_R )
|
||||
{
|
||||
/*If you don't use the Ethernet library,
|
||||
* you can do some data processing operations here*/
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
|
||||
}
|
||||
if( int_sta & ETH_DMA_IT_T )
|
||||
{
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Init
|
||||
*
|
||||
* @brief Ethernet initialization.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Init( uint8_t *macAddr )
|
||||
{
|
||||
ETH_Configuration( macAddr );
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
NVIC_EnableIRQ(ETH_IRQn);
|
||||
NVIC_SetPriority(ETH_IRQn, 0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LibInit
|
||||
*
|
||||
* @brief Ethernet library initialization program
|
||||
*
|
||||
* @return command status
|
||||
*/
|
||||
uint8_t ETH_LibInit( uint8_t *ip, uint8_t *gwip, uint8_t *mask, uint8_t *macaddr )
|
||||
{
|
||||
uint8_t s;
|
||||
struct _WCH_CFG cfg;
|
||||
|
||||
memset(&cfg,0,sizeof(cfg));
|
||||
cfg.TxBufSize = ETH_TX_BUF_SZE;
|
||||
cfg.TCPMss = WCHNET_TCP_MSS;
|
||||
cfg.HeapSize = WCHNET_MEM_HEAP_SIZE;
|
||||
cfg.ARPTableNum = WCHNET_NUM_ARP_TABLE;
|
||||
cfg.MiscConfig0 = WCHNET_MISC_CONFIG0;
|
||||
cfg.MiscConfig1 = WCHNET_MISC_CONFIG1;
|
||||
cfg.net_send = ETH_TxPktChainMode;
|
||||
cfg.CheckValid = WCHNET_CFG_VALID;
|
||||
s = WCHNET_ConfigLIB(&cfg);
|
||||
if( s ){
|
||||
return (s);
|
||||
}
|
||||
s = WCHNET_Init(ip,gwip,mask,macaddr);
|
||||
ETH_Init( macaddr );
|
||||
return (s);
|
||||
}
|
||||
|
||||
/******************************** endfile @ eth_driver ******************************/
|
||||
@@ -0,0 +1,876 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : eth_driver.c
|
||||
* Author : WCH
|
||||
* Version : V1.3.0
|
||||
* Date : 2022/06/02
|
||||
* Description : eth program body.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "string.h"
|
||||
#include "eth_driver.h"
|
||||
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB]; /* MAC receive descriptor, 4-byte aligned*/
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMATxDscrTab[ETH_TXBUFNB]; /* MAC send descriptor, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) uint8_t MACRxBuf[ETH_RXBUFNB*ETH_RX_BUF_SZE]; /* MAC receive buffer, 4-byte aligned */
|
||||
__attribute__((__aligned__(4))) uint8_t MACTxBuf[ETH_TXBUFNB*ETH_TX_BUF_SZE]; /* MAC send buffer, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) SOCK_INF SocketInf[WCHNET_MAX_SOCKET_NUM]; /* Socket information table, 4-byte alignment */
|
||||
const uint16_t MemNum[8] = {WCHNET_NUM_IPRAW,
|
||||
WCHNET_NUM_UDP,
|
||||
WCHNET_NUM_TCP,
|
||||
WCHNET_NUM_TCP_LISTEN,
|
||||
WCHNET_NUM_TCP_SEG,
|
||||
WCHNET_NUM_IP_REASSDATA,
|
||||
WCHNET_NUM_PBUF,
|
||||
WCHNET_NUM_POOL_BUF
|
||||
};
|
||||
const uint16_t MemSize[8] = {WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IPRAW_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_UDP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB_LISTEN),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_SEG),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IP_REASSDATA),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_POOL_BUF)
|
||||
};
|
||||
__attribute__((__aligned__(4)))uint8_t Memp_Memory[WCHNET_MEMP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_Heap_Memory[WCHNET_RAM_HEAP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_ArpTable[WCHNET_RAM_ARP_TABLE_SIZE];
|
||||
|
||||
uint16_t gPHYAddress;
|
||||
uint32_t ChipId = 0;
|
||||
uint32_t volatile LocalTime;
|
||||
|
||||
ETH_DMADESCTypeDef *pDMARxSet;
|
||||
ETH_DMADESCTypeDef *pDMATxSet;
|
||||
|
||||
extern u8 MACAddr[6];
|
||||
volatile uint8_t LinkSta = 0; //0:Link down 1:Link up
|
||||
uint8_t LinkVaildFlag = 0; //0:invalid 1:valid
|
||||
uint8_t AccelerateLinkStep = 0;
|
||||
uint8_t AccelerateLinkTime = 0;
|
||||
uint8_t LinkProcessingStep = 0;
|
||||
uint32_t LinkProcessingTime = 0;
|
||||
uint32_t TaskExecutionTime = 0;
|
||||
u16 LastPhyStat = 0;
|
||||
u32 LastQueryPhyTime = 0;
|
||||
void ETH_LinkDownCfg(void);
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_GetMacAddr
|
||||
*
|
||||
* @brief Get the MAC address
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_GetMacAddr( uint8_t *p )
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *macaddr = (uint8_t *)(ROM_CFG_USERADR_ID+5);
|
||||
|
||||
for(i=0;i<6;i++)
|
||||
{
|
||||
*p = *macaddr;
|
||||
p++;
|
||||
macaddr--;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_TimeIsr
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_TimeIsr( uint16_t timperiod )
|
||||
{
|
||||
LocalTime += timperiod;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_QueryPhySta
|
||||
*
|
||||
* @brief Query external PHY status
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_QueryPhySta(void)
|
||||
{
|
||||
u16 phy_stat;
|
||||
if(QUERY_STAT_FLAG){ /* Query the PHY link status every 1s */
|
||||
LastQueryPhyTime = LocalTime / 1000;
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BSR );
|
||||
if((phy_stat != LastPhyStat) && (phy_stat != 0xffff)){
|
||||
ETH_PHYLink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_CheckPHYPN
|
||||
*
|
||||
* @brief check PHY PN polarity
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_CheckPHYPN(uint16_t time)
|
||||
{
|
||||
u16 phy_stat;
|
||||
|
||||
//check PHY PN
|
||||
if((LinkProcessingStep == 0)||(LocalTime >= LinkProcessingTime))
|
||||
{
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0 );
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x10);
|
||||
if(phy_stat & (1<<12))
|
||||
{
|
||||
if(LinkProcessingStep == 0)
|
||||
{
|
||||
LinkProcessingStep = 1;
|
||||
LinkProcessingTime = LocalTime + time;
|
||||
}
|
||||
else {
|
||||
LinkProcessingStep = 0;
|
||||
LinkProcessingTime = 0;
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, PHY_ANER);
|
||||
if((time == 200) || ((phy_stat & 1) == 0))
|
||||
{
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0 );
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x16);
|
||||
phy_stat |= 1<<5;
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x16, phy_stat );
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x16);
|
||||
phy_stat &= ~(1<<5);
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x16, phy_stat );
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x1E); /* Clear the Interrupt status */
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LinkProcessingStep = 0;
|
||||
LinkProcessingTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_AccelerateLink
|
||||
*
|
||||
* @brief accelerate Link processing
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_AccelerateLink(void)
|
||||
{
|
||||
uint16_t phy_stat;
|
||||
|
||||
switch(AccelerateLinkStep)
|
||||
{
|
||||
case 0:
|
||||
AccelerateLinkStep++;
|
||||
AccelerateLinkTime = 0;
|
||||
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x18);
|
||||
phy_stat &= ~(1<<15);
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x18, phy_stat );
|
||||
|
||||
//power down
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
phy_stat |= (1<<11);
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, phy_stat );
|
||||
|
||||
//decrease Link Time
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x13, 0x4 );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(AccelerateLinkTime++ > 120) //unit:10ms,total time:1.2s~1.5s
|
||||
{
|
||||
AccelerateLinkStep++;
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x18);
|
||||
phy_stat |= 1<<15;
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x18, phy_stat );
|
||||
// power up
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
phy_stat &= ~(1<<11);
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, phy_stat );
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 99 );
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x19);
|
||||
if((phy_stat & 0xf) == 2)
|
||||
{
|
||||
AccelerateLinkStep++;
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, PHY_PAG_SEL, 0x00 );
|
||||
ETH_WritePHYRegister(PHY_ADDRESS, 0x13, 0x0 );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/*do nothing*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_CheckLinkVaild
|
||||
*
|
||||
* @brief check whether Link is valid
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_CheckLinkVaild(void)
|
||||
{
|
||||
uint16_t phy_stat, phy_bcr;
|
||||
|
||||
if(LinkVaildFlag == 0)
|
||||
{
|
||||
phy_bcr = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
if((phy_bcr & (1<<13)) == 0) //Do nothing if Link mode is 10M.
|
||||
{
|
||||
LinkVaildFlag = 1;
|
||||
LinkProcessingTime = 0;
|
||||
return;
|
||||
}
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0 );
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x10);
|
||||
if((phy_stat & (1<<9)) == 0)
|
||||
{
|
||||
LinkProcessingTime++;
|
||||
if(LinkProcessingTime == 5)
|
||||
{
|
||||
LinkProcessingTime = 0;
|
||||
phy_stat = ETH_ReadPHYRegister(gPHYAddress, PHY_BCR);
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_BCR, PHY_Reset );
|
||||
Delay_Us(100);
|
||||
ETH_WritePHYRegister(gPHYAddress, PHY_BCR, phy_stat );
|
||||
ETH_LinkDownCfg();
|
||||
}
|
||||
}
|
||||
else {
|
||||
LinkVaildFlag = 1;
|
||||
LinkProcessingTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_LinkProcessing
|
||||
*
|
||||
* @brief process Link stage task
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_LinkProcessing(void)
|
||||
{
|
||||
u16 phy_bcr;
|
||||
|
||||
if(LocalTime >= TaskExecutionTime)
|
||||
{
|
||||
TaskExecutionTime = LocalTime + 10; //execution cycle:10ms
|
||||
if(LinkSta == 0) //Link down
|
||||
{
|
||||
phy_bcr = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR);
|
||||
if(phy_bcr & PHY_AutoNegotiation) //auto-negotiation is enabled
|
||||
{
|
||||
WCHNET_CheckPHYPN(300); //check PHY PN
|
||||
WCHNET_AccelerateLink(); //accelerate Link processing
|
||||
}
|
||||
else { //auto-negotiation is disabled
|
||||
if((phy_bcr & (1<<13)) == 0) // 10M
|
||||
{
|
||||
WCHNET_CheckPHYPN(200); //check PHY PN
|
||||
}
|
||||
}
|
||||
}
|
||||
else { //Link up
|
||||
WCHNET_CheckLinkVaild(); //check whether Link is valid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_MainTask
|
||||
*
|
||||
* @brief library main task function
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_MainTask(void)
|
||||
{
|
||||
WCHNET_NetInput( ); /* Ethernet data input */
|
||||
WCHNET_PeriodicHandle( ); /* Protocol stack time-related task processing */
|
||||
|
||||
WCHNET_QueryPhySta(); /* Query external PHY status */
|
||||
WCHNET_LinkProcessing(); /* process Link stage task */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_MIIPinInit
|
||||
*
|
||||
* @brief PHY MII interface GPIO initialization.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_MIIPinInit(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
|
||||
|
||||
GPIO_Output(GPIOA, GPIO_Pin_2); /* MDIO */
|
||||
GPIO_Output(GPIOC, GPIO_Pin_1); /* MDC */
|
||||
|
||||
GPIO_Input(GPIOC, GPIO_Pin_3); /* TXCLK */
|
||||
GPIO_Output(GPIOB, GPIO_Pin_11); /* TXEN */
|
||||
GPIO_Output(GPIOB, GPIO_Pin_12); /* TXD0 */
|
||||
GPIO_Output(GPIOB, GPIO_Pin_13); /* TXD1 */
|
||||
GPIO_Output(GPIOC, GPIO_Pin_2); /* TXD2 */
|
||||
GPIO_Output(GPIOB, GPIO_Pin_8); /* TXD3 */
|
||||
GPIO_Input(GPIOA, GPIO_Pin_1); /* RXC */
|
||||
GPIO_Input(GPIOA, GPIO_Pin_7); /* RXDV */
|
||||
GPIO_Input(GPIOC, GPIO_Pin_4); /* RXD0 */
|
||||
GPIO_Input(GPIOC, GPIO_Pin_5); /* RXD1 */
|
||||
GPIO_Input(GPIOB, GPIO_Pin_0); /* RXD2 */
|
||||
GPIO_Input(GPIOB, GPIO_Pin_1); /* RXD3 */
|
||||
GPIO_Input(GPIOB, GPIO_Pin_10); /* RXER */
|
||||
|
||||
GPIO_Output(GPIOA, GPIO_Pin_0); /* CRS */
|
||||
GPIO_Output(GPIOA, GPIO_Pin_3); /* COL */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LinkUpCfg
|
||||
*
|
||||
* @brief When the PHY is connected, configure the relevant functions.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_LinkUpCfg(void)
|
||||
{
|
||||
uint16_t phy_stat;
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BCR );
|
||||
/* PHY negotiation result */
|
||||
if(phy_stat & (1<<13)) /* 100M */
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
ETH->MACCR |= ETH_Speed_100M;
|
||||
}
|
||||
else /* 10M */
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
}
|
||||
if(phy_stat & (1<<8)) /* full duplex */
|
||||
{
|
||||
ETH->MACCR |= ETH_Mode_FullDuplex;
|
||||
}
|
||||
else /* half duplex */
|
||||
{
|
||||
ETH->MACCR &= ~ETH_Mode_FullDuplex;
|
||||
}
|
||||
|
||||
LinkSta = 1;
|
||||
AccelerateLinkStep = 0;
|
||||
LinkProcessingStep = 0;
|
||||
LinkProcessingTime = 0;
|
||||
ETH_Start( );
|
||||
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0 );
|
||||
phy_stat = 0x0;
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x13, phy_stat );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LinkDownCfg
|
||||
*
|
||||
* @brief When the PHY is disconnected, configure the relevant functions.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_LinkDownCfg(void)
|
||||
{
|
||||
LinkSta = 0;
|
||||
LinkVaildFlag = 0;
|
||||
LinkProcessingTime = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_PHYLink
|
||||
*
|
||||
* @brief Configure MAC parameters after the PHY Link is successful.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_PHYLink( void )
|
||||
{
|
||||
u32 phy_stat, phy_anlpar, phy_bcr;
|
||||
uint8_t timeout = 0;
|
||||
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BSR );
|
||||
phy_anlpar = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_ANLPAR);
|
||||
phy_bcr = ETH_ReadPHYRegister( gPHYAddress, PHY_BCR);
|
||||
|
||||
if((ChipId & 0xf0) <= 0x20)
|
||||
{
|
||||
while(phy_stat == 0)
|
||||
{
|
||||
Delay_Us(100);
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, PHY_BSR);
|
||||
if(timeout++ == 15) break;
|
||||
}
|
||||
if(LastPhyStat == phy_stat) return;
|
||||
}
|
||||
LastPhyStat = phy_stat;
|
||||
|
||||
WCHNET_PhyStatus( phy_stat );
|
||||
if(phy_stat & PHY_Linked_Status) //LinkUp
|
||||
{
|
||||
if(phy_bcr & PHY_AutoNegotiation)
|
||||
{
|
||||
if(phy_anlpar == 0)
|
||||
{
|
||||
ETH_LinkUpCfg();
|
||||
}
|
||||
else {
|
||||
if(phy_stat & PHY_AutoNego_Complete)
|
||||
{
|
||||
ETH_LinkUpCfg();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ETH_LinkUpCfg();
|
||||
}
|
||||
}
|
||||
else { //LinkDown
|
||||
/*Link down*/
|
||||
ETH_LinkDownCfg();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_RegInit
|
||||
*
|
||||
* @brief ETH register initialization.
|
||||
*
|
||||
* @param ETH_InitStruct:initialization struct.
|
||||
* PHYAddress:PHY address.
|
||||
*
|
||||
* @return Initialization status.
|
||||
*/
|
||||
uint32_t ETH_RegInit( ETH_InitTypeDef* ETH_InitStruct, uint16_t PHYAddress )
|
||||
{
|
||||
uint16_t tmpreg;
|
||||
/* Set the SMI interface clock, set as the main frequency divided by 42 */
|
||||
ETH->MACMIIAR = (uint32_t)ETH_MACMIIAR_CR_Div42;
|
||||
|
||||
/*------------------------ MAC register configuration -------------------------------------------*/
|
||||
ETH->MACCR = (uint32_t)(ETH_InitStruct->ETH_Watchdog |
|
||||
ETH_InitStruct->ETH_Jabber |
|
||||
ETH_InitStruct->ETH_InterFrameGap |
|
||||
ETH_InitStruct->ETH_ChecksumOffload |
|
||||
ETH_InitStruct->ETH_AutomaticPadCRCStrip |
|
||||
ETH_InitStruct->ETH_LoopbackMode);
|
||||
|
||||
ETH->MACFFR = (uint32_t)(ETH_InitStruct->ETH_ReceiveAll |
|
||||
ETH_InitStruct->ETH_SourceAddrFilter |
|
||||
ETH_InitStruct->ETH_PassControlFrames |
|
||||
ETH_InitStruct->ETH_BroadcastFramesReception |
|
||||
ETH_InitStruct->ETH_DestinationAddrFilter |
|
||||
ETH_InitStruct->ETH_PromiscuousMode |
|
||||
ETH_InitStruct->ETH_MulticastFramesFilter |
|
||||
ETH_InitStruct->ETH_UnicastFramesFilter);
|
||||
|
||||
ETH->MACHTHR = (uint32_t)ETH_InitStruct->ETH_HashTableHigh;
|
||||
ETH->MACHTLR = (uint32_t)ETH_InitStruct->ETH_HashTableLow;
|
||||
|
||||
ETH->MACFCR = (uint32_t)((ETH_InitStruct->ETH_PauseTime << 16) |
|
||||
ETH_InitStruct->ETH_UnicastPauseFrameDetect |
|
||||
ETH_InitStruct->ETH_ReceiveFlowControl |
|
||||
ETH_InitStruct->ETH_TransmitFlowControl);
|
||||
|
||||
ETH->MACVLANTR = (uint32_t)(ETH_InitStruct->ETH_VLANTagComparison |
|
||||
ETH_InitStruct->ETH_VLANTagIdentifier);
|
||||
|
||||
ETH->DMAOMR = (uint32_t)(ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame |
|
||||
ETH_InitStruct->ETH_TransmitStoreForward |
|
||||
ETH_InitStruct->ETH_ForwardErrorFrames |
|
||||
ETH_InitStruct->ETH_ForwardUndersizedGoodFrames);
|
||||
|
||||
/* Reset the physical layer */
|
||||
ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_Reset);
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x00 );
|
||||
tmpreg = ETH_ReadPHYRegister(gPHYAddress, 24);
|
||||
if(tmpreg & (1<<1)) ETH_WritePHYRegister(PHYAddress, PHY_BCR, 0x3100);
|
||||
|
||||
/*Reads the default value of the PHY_BSR register*/
|
||||
LastPhyStat = ETH_ReadPHYRegister( PHY_ADDRESS, PHY_BSR );
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Configuration
|
||||
*
|
||||
* @brief Ethernet configure.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Configuration( uint8_t *macAddr )
|
||||
{
|
||||
ETH_InitTypeDef ETH_InitStructure;
|
||||
uint16_t timeout = 10000;
|
||||
|
||||
/* Enable Ethernet MAC clock */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | \
|
||||
RCC_AHBPeriph_ETH_MAC_Tx | \
|
||||
RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
|
||||
|
||||
gPHYAddress = PHY_ADDRESS;
|
||||
|
||||
/* Enable MII GPIO */
|
||||
ETH_MIIPinInit( );
|
||||
|
||||
/* Reset ETHERNET on AHB Bus */
|
||||
ETH_DeInit();
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* ETHERNET Configuration */
|
||||
/*------------------------ MAC -----------------------------------*/
|
||||
ETH_InitStructure.ETH_Watchdog = ETH_Watchdog_Enable;
|
||||
ETH_InitStructure.ETH_Jabber = ETH_Jabber_Enable;
|
||||
ETH_InitStructure.ETH_InterFrameGap = ETH_InterFrameGap_96Bit;
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
|
||||
#else
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;
|
||||
#endif
|
||||
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
|
||||
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
|
||||
|
||||
/* Filter function configuration */
|
||||
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
|
||||
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
|
||||
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
|
||||
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_PassControlFrames = ETH_PassControlFrames_BlockAll;
|
||||
ETH_InitStructure.ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal;
|
||||
ETH_InitStructure.ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable;
|
||||
|
||||
ETH_InitStructure.ETH_HashTableHigh = 0x0;
|
||||
ETH_InitStructure.ETH_HashTableLow = 0x0;
|
||||
|
||||
/* VLan function configuration */
|
||||
ETH_InitStructure.ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit;
|
||||
ETH_InitStructure.ETH_VLANTagIdentifier = 0x0;
|
||||
|
||||
/* Flow Control function configuration */
|
||||
ETH_InitStructure.ETH_PauseTime = 0x0;
|
||||
ETH_InitStructure.ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable;
|
||||
ETH_InitStructure.ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable;
|
||||
ETH_InitStructure.ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable;
|
||||
|
||||
/*------------------------ DMA -----------------------------------*/
|
||||
/* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
|
||||
the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
|
||||
if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
|
||||
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
|
||||
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
|
||||
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Enable;
|
||||
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Enable;
|
||||
/* Configure Ethernet */
|
||||
ETH_RegInit( Ð_InitStructure, gPHYAddress );
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((macAddr[5]<<8) | macAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(macAddr[0] | (macAddr[1]<<8) | (macAddr[2]<<16) | (macAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU,\
|
||||
ENABLE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_TxPktChainMode
|
||||
*
|
||||
* @brief Ethernet sends data frames in chain mode.
|
||||
*
|
||||
* @param len Send data length
|
||||
* pBuff send buffer pointer
|
||||
*
|
||||
* @return Send status.
|
||||
*/
|
||||
uint32_t ETH_TxPktChainMode(uint16_t len, uint32_t *pBuff )
|
||||
{
|
||||
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
|
||||
if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
/* Return ERROR: OWN bit set */
|
||||
return ETH_ERROR;
|
||||
}
|
||||
/* Setting the Frame Length: bits[12:0] */
|
||||
DMATxDescToSet->ControlBufferSize = (len & ETH_DMATxDesc_TBS1);
|
||||
DMATxDescToSet->Buffer1Addr = (uint32_t)pBuff;
|
||||
|
||||
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS | ETH_DMATxDesc_CIC_TCPUDPICMP_Full;
|
||||
#else
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
|
||||
#endif
|
||||
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_OWN;
|
||||
|
||||
/* Clear TBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_TBUS;
|
||||
/* Resume DMA transmission*/
|
||||
ETH->DMATPDR = 0;
|
||||
|
||||
/* Update the ETHERNET DMA global Tx descriptor with next Tx descriptor */
|
||||
/* Chained Mode */
|
||||
/* Selects the next DMA Tx descriptor list for next buffer to send */
|
||||
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr);
|
||||
/* Return SUCCESS */
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Stop
|
||||
*
|
||||
* @brief Disables ENET MAC and DMA reception/transmission.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Stop(void)
|
||||
{
|
||||
ETH_MACTransmissionCmd(DISABLE);
|
||||
ETH_FlushTransmitFIFO();
|
||||
ETH_MACReceptionCmd(DISABLE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ReInitMACReg
|
||||
*
|
||||
* @brief Reinitialize MAC register.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ReInitMACReg(void)
|
||||
{
|
||||
uint16_t timeout = 10000;
|
||||
uint32_t maccr, macmiiar, macffr, machthr, machtlr;
|
||||
uint32_t macfcr, macvlantr, dmaomr;
|
||||
|
||||
/* Wait for sending data to complete */
|
||||
while((ETH->DMASR & (7 << 20)) != ETH_DMA_TransmitProcess_Suspended);
|
||||
|
||||
ETH_Stop();
|
||||
|
||||
/* Record the register value */
|
||||
macmiiar = ETH->MACMIIAR;
|
||||
maccr = ETH->MACCR;
|
||||
macffr = ETH->MACFFR;
|
||||
machthr = ETH->MACHTHR;
|
||||
machtlr = ETH->MACHTLR;
|
||||
macfcr = ETH->MACFCR;
|
||||
macvlantr = ETH->MACVLANTR;
|
||||
dmaomr = ETH->DMAOMR;
|
||||
|
||||
/* Reset ETHERNET on AHB Bus */
|
||||
ETH_DeInit();
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((MACAddr[5]<<8) | MACAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(MACAddr[0] | (MACAddr[1]<<8) | (MACAddr[2]<<16) | (MACAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU,\
|
||||
ENABLE);
|
||||
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
|
||||
ETH->MACMIIAR = macmiiar;
|
||||
ETH->MACCR = maccr;
|
||||
ETH->MACFFR = macffr;
|
||||
ETH->MACHTHR = machthr;
|
||||
ETH->MACHTLR = machtlr;
|
||||
ETH->MACFCR = macfcr;
|
||||
ETH->MACVLANTR = macvlantr;
|
||||
ETH->DMAOMR = dmaomr;
|
||||
|
||||
ETH_Start( );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_RecProcess
|
||||
*
|
||||
* @brief Receiving related processing
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_RecProcess(void)
|
||||
{
|
||||
if(((ChipId & 0xf0) <= 0x20) && \
|
||||
((ETH->DMAMFBOCR & 0x1FFE0000) != 0))
|
||||
{
|
||||
ReInitMACReg();
|
||||
/* Resume DMA transport */
|
||||
ETH->DMARPDR = 0;
|
||||
ETH->DMATPDR = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_ETHIsr
|
||||
*
|
||||
* @brief Ethernet Interrupt Service Routine
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_ETHIsr(void)
|
||||
{
|
||||
uint32_t int_sta;
|
||||
|
||||
int_sta = ETH->DMASR;
|
||||
if (int_sta & ETH_DMA_IT_AIS)
|
||||
{
|
||||
if (int_sta & ETH_DMA_IT_RBU)
|
||||
{
|
||||
WCHNET_RecProcess();
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_RBU);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
|
||||
}
|
||||
|
||||
if( int_sta & ETH_DMA_IT_NIS )
|
||||
{
|
||||
if( int_sta & ETH_DMA_IT_R )
|
||||
{
|
||||
/*If you don't use the Ethernet library,
|
||||
* you can do some data processing operations here*/
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
|
||||
}
|
||||
if( int_sta & ETH_DMA_IT_T )
|
||||
{
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Init
|
||||
*
|
||||
* @brief Ethernet initialization.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Init( uint8_t *macAddr )
|
||||
{
|
||||
ChipId = DBGMCU_GetCHIPID();
|
||||
ETH_Configuration( macAddr );
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
NVIC_EnableIRQ(ETH_IRQn);
|
||||
NVIC_SetPriority(ETH_IRQn, 0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LibInit
|
||||
*
|
||||
* @brief Ethernet library initialization program
|
||||
*
|
||||
* @return command status
|
||||
*/
|
||||
uint8_t ETH_LibInit( uint8_t *ip, uint8_t *gwip, uint8_t *mask, uint8_t *macaddr )
|
||||
{
|
||||
uint8_t s;
|
||||
struct _WCH_CFG cfg;
|
||||
|
||||
memset(&cfg,0,sizeof(cfg));
|
||||
cfg.TxBufSize = ETH_TX_BUF_SZE;
|
||||
cfg.TCPMss = WCHNET_TCP_MSS;
|
||||
cfg.HeapSize = WCHNET_MEM_HEAP_SIZE;
|
||||
cfg.ARPTableNum = WCHNET_NUM_ARP_TABLE;
|
||||
cfg.MiscConfig0 = WCHNET_MISC_CONFIG0;
|
||||
cfg.MiscConfig1 = WCHNET_MISC_CONFIG1;
|
||||
cfg.net_send = ETH_TxPktChainMode;
|
||||
cfg.CheckValid = WCHNET_CFG_VALID;
|
||||
s = WCHNET_ConfigLIB(&cfg);
|
||||
if( s ){
|
||||
return (s);
|
||||
}
|
||||
s = WCHNET_Init(ip,gwip,mask,macaddr);
|
||||
ETH_Init( macaddr );
|
||||
return (s);
|
||||
}
|
||||
|
||||
/******************************** endfile @ eth_driver ******************************/
|
||||
@@ -0,0 +1,714 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : eth_driver.c
|
||||
* Author : WCH
|
||||
* Version : V1.3.0
|
||||
* Date : 2022/06/02
|
||||
* Description : eth program body.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "string.h"
|
||||
#include "eth_driver.h"
|
||||
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB]; /* MAC receive descriptor, 4-byte aligned*/
|
||||
__attribute__((__aligned__(4))) ETH_DMADESCTypeDef DMATxDscrTab[ETH_TXBUFNB]; /* MAC send descriptor, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) uint8_t MACRxBuf[ETH_RXBUFNB*ETH_RX_BUF_SZE]; /* MAC receive buffer, 4-byte aligned */
|
||||
__attribute__((__aligned__(4))) uint8_t MACTxBuf[ETH_TXBUFNB*ETH_TX_BUF_SZE]; /* MAC send buffer, 4-byte aligned */
|
||||
|
||||
__attribute__((__aligned__(4))) SOCK_INF SocketInf[WCHNET_MAX_SOCKET_NUM]; /* Socket information table, 4-byte alignment */
|
||||
const uint16_t MemNum[8] = {WCHNET_NUM_IPRAW,
|
||||
WCHNET_NUM_UDP,
|
||||
WCHNET_NUM_TCP,
|
||||
WCHNET_NUM_TCP_LISTEN,
|
||||
WCHNET_NUM_TCP_SEG,
|
||||
WCHNET_NUM_IP_REASSDATA,
|
||||
WCHNET_NUM_PBUF,
|
||||
WCHNET_NUM_POOL_BUF
|
||||
};
|
||||
const uint16_t MemSize[8] = {WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IPRAW_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_UDP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB_LISTEN),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_SEG),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IP_REASSDATA),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF),
|
||||
WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_POOL_BUF)
|
||||
};
|
||||
__attribute__((__aligned__(4)))uint8_t Memp_Memory[WCHNET_MEMP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_Heap_Memory[WCHNET_RAM_HEAP_SIZE];
|
||||
__attribute__((__aligned__(4)))uint8_t Mem_ArpTable[WCHNET_RAM_ARP_TABLE_SIZE];
|
||||
|
||||
uint16_t gPHYAddress;
|
||||
uint32_t volatile LocalTime;
|
||||
|
||||
ETH_DMADESCTypeDef *pDMARxSet;
|
||||
ETH_DMADESCTypeDef *pDMATxSet;
|
||||
|
||||
u32 ChipId = 0;
|
||||
#if !LINK_STAT_ACQUISITION_METHOD
|
||||
u16 LastPhyStat = 0;
|
||||
u32 LastQueryPhyTime = 0;
|
||||
#endif
|
||||
extern u8 MACAddr[6];
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_GetMacAddr
|
||||
*
|
||||
* @brief Get the MAC address
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_GetMacAddr( uint8_t *p )
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *macaddr = (uint8_t *)(ROM_CFG_USERADR_ID+5);
|
||||
|
||||
for(i=0;i<6;i++)
|
||||
{
|
||||
*p = *macaddr;
|
||||
p++;
|
||||
macaddr--;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_TimeIsr
|
||||
*
|
||||
* @brief
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_TimeIsr( uint16_t timperiod )
|
||||
{
|
||||
LocalTime += timperiod;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_QueryPhySta
|
||||
*
|
||||
* @brief Query external PHY status
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
#if !LINK_STAT_ACQUISITION_METHOD
|
||||
void WCHNET_QueryPhySta(void)
|
||||
{
|
||||
u16 phy_stat;
|
||||
if(QUERY_STAT_FLAG){ /* Query the PHY link status every 1s */
|
||||
LastQueryPhyTime = LocalTime / 1000;
|
||||
ETH_WritePHYRegister( PHY_ADDRESS, 0x1F, 0x0a43 );
|
||||
/*In some cases the status is not updated in time,
|
||||
* so read this register twice to get the correct status value.*/
|
||||
ETH_ReadPHYRegister( PHY_ADDRESS, 0x1A);
|
||||
phy_stat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x1A) & 0x04;
|
||||
if((phy_stat != LastPhyStat) && (phy_stat != 0xffff)){
|
||||
ETH_PHYLink();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_MainTask
|
||||
*
|
||||
* @brief library main task function
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_MainTask(void)
|
||||
{
|
||||
WCHNET_NetInput( ); /* Ethernet data input */
|
||||
WCHNET_PeriodicHandle( ); /* Protocol stack time-related task processing */
|
||||
|
||||
#if !LINK_STAT_ACQUISITION_METHOD
|
||||
WCHNET_QueryPhySta(); /* Query external PHY status */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_RGMIIPinInit
|
||||
*
|
||||
* @brief PHY RGMII interface GPIO initialization.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_RGMIIPinInit(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
|
||||
GPIOB->CFGHR &= ~(0xff<<16);
|
||||
GPIOB->CFGHR |= (0xbb<<16);
|
||||
GPIOB->CFGLR &= ~(0xff<<4);
|
||||
|
||||
GPIO_Output(GPIOA, GPIO_Pin_2);
|
||||
GPIO_Output(GPIOA, GPIO_Pin_3);
|
||||
GPIO_Output(GPIOA, GPIO_Pin_7);
|
||||
GPIO_Output(GPIOC, GPIO_Pin_4);
|
||||
GPIO_Output(GPIOC, GPIO_Pin_5);
|
||||
GPIO_Output(GPIOB, GPIO_Pin_0);
|
||||
|
||||
GPIO_Input(GPIOC, GPIO_Pin_0);
|
||||
GPIO_Input(GPIOC, GPIO_Pin_1);
|
||||
GPIO_Input(GPIOC, GPIO_Pin_2);
|
||||
GPIO_Input(GPIOC, GPIO_Pin_3);
|
||||
GPIO_Input(GPIOA, GPIO_Pin_0);
|
||||
GPIO_Input(GPIOA, GPIO_Pin_1);
|
||||
|
||||
GPIO_Input(GPIOB, GPIO_Pin_1); /* 125m in */
|
||||
GPIO_Input(GPIOC, GPIO_Pin_7); /* interrupt pin */
|
||||
}
|
||||
|
||||
#if LINK_STAT_ACQUISITION_METHOD
|
||||
/*********************************************************************
|
||||
* @fn EXTI_Line_Init
|
||||
*
|
||||
* @brief Configure EXTI Line7.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void EXTI_Line_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
||||
EXTI_InitTypeDef EXTI_InitStructure = {0};
|
||||
NVIC_InitTypeDef NVIC_InitStructure = {0};
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOC 7 ----> EXTI_Line7 */
|
||||
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, 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 = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn PHY_InterruptInit
|
||||
*
|
||||
* @brief Configure PHY interrupt function,Supported chip is:RTL8211FS
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void PHY_InterruptInit(void)
|
||||
{
|
||||
uint16_t RegValue;
|
||||
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x1F, 0x0a42 );
|
||||
RegValue = ETH_ReadPHYRegister(gPHYAddress, 0x12);
|
||||
/* enable Link Status Change Interrupt and
|
||||
* Auto-Negotiation Completed Interrupt*/
|
||||
RegValue |= (1<<4)|(1<<3);
|
||||
ETH_WritePHYRegister(gPHYAddress, 0x12, RegValue );
|
||||
/* Clear the Interrupt status */
|
||||
ETH_WritePHYRegister( gPHYAddress, 0x1F, 0x0a43 );
|
||||
ETH_ReadPHYRegister( gPHYAddress, 0x1D);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_PHYLink
|
||||
*
|
||||
* @brief Configure MAC parameters after the PHY Link is successful.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ETH_PHYLink( void )
|
||||
{
|
||||
u32 phy_stat;
|
||||
#if !LINK_STAT_ACQUISITION_METHOD
|
||||
uint8_t timeout = 0;
|
||||
#endif
|
||||
|
||||
ETH_WritePHYRegister( gPHYAddress, 0x1F, 0x0a43 );
|
||||
/*In some cases the status is not updated in time,
|
||||
* so read this register twice to get the correct status value.*/
|
||||
ETH_ReadPHYRegister( gPHYAddress, 0x1A);
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x1A);
|
||||
#if !LINK_STAT_ACQUISITION_METHOD
|
||||
if((ChipId & 0xf0) <= 0x20)
|
||||
{
|
||||
while(phy_stat == 0)
|
||||
{
|
||||
Delay_Us(100);
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x1A);
|
||||
if(timeout++ == 15) break;
|
||||
}
|
||||
if(LastPhyStat == (phy_stat & 0x04)) return;
|
||||
}
|
||||
LastPhyStat = phy_stat & 0x04;
|
||||
#endif
|
||||
WCHNET_PhyStatus( phy_stat );
|
||||
|
||||
if( phy_stat & 0x04 )
|
||||
{
|
||||
/* Configure the polarity and delay of TXC */
|
||||
RGMII_TXC_Delay(0, 4);
|
||||
if( phy_stat & 0x08 )
|
||||
{
|
||||
ETH->MACCR |= ETH_Mode_FullDuplex;
|
||||
}
|
||||
else
|
||||
{
|
||||
ETH->MACCR &= ~ETH_Mode_FullDuplex;
|
||||
}
|
||||
if( (phy_stat & 0x30) == 0x00 )
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
}
|
||||
else if( (phy_stat & 0x30) == 0x10 )
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
ETH->MACCR |= ETH_Speed_100M;
|
||||
}
|
||||
else if( (phy_stat & 0x30) == 0x20 )
|
||||
{
|
||||
ETH->MACCR &= ~(ETH_Speed_100M|ETH_Speed_1000M);
|
||||
ETH->MACCR |= ETH_Speed_1000M;
|
||||
/* Configure the polarity and delay of TXC */
|
||||
if((ChipId & 0xf0) >= 0x60)
|
||||
RGMII_TXC_Delay(1, 2);
|
||||
}
|
||||
ETH_Start( );
|
||||
}
|
||||
phy_stat = ETH_ReadPHYRegister( gPHYAddress, 0x1D); /* Clear the Interrupt status */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_RegInit
|
||||
*
|
||||
* @brief ETH register initialization.
|
||||
*
|
||||
* @param ETH_InitStruct:initialization struct.
|
||||
* PHYAddress:PHY address.
|
||||
*
|
||||
* @return Initialization status.
|
||||
*/
|
||||
uint32_t ETH_RegInit( ETH_InitTypeDef* ETH_InitStruct, uint16_t PHYAddress )
|
||||
{
|
||||
/* Set the SMI interface clock, set as the main frequency divided by 42 */
|
||||
ETH->MACMIIAR = (uint32_t)ETH_MACMIIAR_CR_Div42;
|
||||
|
||||
/*------------------------ MAC register configuration -------------------------------------------*/
|
||||
ETH->MACCR = (uint32_t)(ETH_InitStruct->ETH_Watchdog |
|
||||
ETH_InitStruct->ETH_Jabber |
|
||||
ETH_InitStruct->ETH_InterFrameGap |
|
||||
ETH_InitStruct->ETH_ChecksumOffload |
|
||||
ETH_InitStruct->ETH_AutomaticPadCRCStrip |
|
||||
ETH_InitStruct->ETH_LoopbackMode);
|
||||
|
||||
ETH->MACFFR = (uint32_t)(ETH_InitStruct->ETH_ReceiveAll |
|
||||
ETH_InitStruct->ETH_SourceAddrFilter |
|
||||
ETH_InitStruct->ETH_PassControlFrames |
|
||||
ETH_InitStruct->ETH_BroadcastFramesReception |
|
||||
ETH_InitStruct->ETH_DestinationAddrFilter |
|
||||
ETH_InitStruct->ETH_PromiscuousMode |
|
||||
ETH_InitStruct->ETH_MulticastFramesFilter |
|
||||
ETH_InitStruct->ETH_UnicastFramesFilter);
|
||||
|
||||
ETH->MACHTHR = (uint32_t)ETH_InitStruct->ETH_HashTableHigh;
|
||||
ETH->MACHTLR = (uint32_t)ETH_InitStruct->ETH_HashTableLow;
|
||||
|
||||
ETH->MACFCR = (uint32_t)((ETH_InitStruct->ETH_PauseTime << 16) |
|
||||
ETH_InitStruct->ETH_UnicastPauseFrameDetect |
|
||||
ETH_InitStruct->ETH_ReceiveFlowControl |
|
||||
ETH_InitStruct->ETH_TransmitFlowControl);
|
||||
|
||||
ETH->MACVLANTR = (uint32_t)(ETH_InitStruct->ETH_VLANTagComparison |
|
||||
ETH_InitStruct->ETH_VLANTagIdentifier);
|
||||
|
||||
ETH->DMAOMR = (uint32_t)(ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame |
|
||||
ETH_InitStruct->ETH_TransmitStoreForward |
|
||||
ETH_InitStruct->ETH_ForwardErrorFrames |
|
||||
ETH_InitStruct->ETH_ForwardUndersizedGoodFrames);
|
||||
|
||||
/* Reset the physical layer */
|
||||
ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_Reset);
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Configuration
|
||||
*
|
||||
* @brief Ethernet configure.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Configuration( uint8_t *macAddr )
|
||||
{
|
||||
ETH_InitTypeDef ETH_InitStructure;
|
||||
uint16_t timeout = 10000;
|
||||
|
||||
/* Enable Ethernet MAC clock */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | \
|
||||
RCC_AHBPeriph_ETH_MAC_Tx | \
|
||||
RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
|
||||
|
||||
gPHYAddress = PHY_ADDRESS;
|
||||
|
||||
/* Enable 1G MAC*/
|
||||
EXTEN->EXTEN_CTR |= EXTEN_ETH_RGMII_SEL;
|
||||
RCC_ETH1GCLKConfig(RCC_ETH1GCLKSource_PB1_IN);
|
||||
RCC_ETH1G_125Mcmd(ENABLE);
|
||||
/* Enable RGMII GPIO */
|
||||
ETH_RGMIIPinInit();
|
||||
|
||||
/* Reset ETHERNET on AHB Bus */
|
||||
ETH_DeInit();
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* ETHERNET Configuration */
|
||||
/*------------------------ MAC -----------------------------------*/
|
||||
ETH_InitStructure.ETH_Watchdog = ETH_Watchdog_Enable;
|
||||
ETH_InitStructure.ETH_Jabber = ETH_Jabber_Enable;
|
||||
ETH_InitStructure.ETH_InterFrameGap = ETH_InterFrameGap_96Bit;
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
|
||||
#else
|
||||
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;
|
||||
#endif
|
||||
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
|
||||
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
|
||||
|
||||
/* Filter function configuration */
|
||||
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
|
||||
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
|
||||
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
|
||||
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
|
||||
ETH_InitStructure.ETH_PassControlFrames = ETH_PassControlFrames_BlockAll;
|
||||
ETH_InitStructure.ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal;
|
||||
ETH_InitStructure.ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable;
|
||||
|
||||
ETH_InitStructure.ETH_HashTableHigh = 0x0;
|
||||
ETH_InitStructure.ETH_HashTableLow = 0x0;
|
||||
|
||||
/* VLan function configuration */
|
||||
ETH_InitStructure.ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit;
|
||||
ETH_InitStructure.ETH_VLANTagIdentifier = 0x0;
|
||||
|
||||
/* Flow Control function configuration */
|
||||
ETH_InitStructure.ETH_PauseTime = 0x0;
|
||||
ETH_InitStructure.ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable;
|
||||
ETH_InitStructure.ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable;
|
||||
ETH_InitStructure.ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable;
|
||||
|
||||
/*------------------------ DMA -----------------------------------*/
|
||||
/* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
|
||||
the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
|
||||
if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
|
||||
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
|
||||
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
|
||||
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Enable;
|
||||
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Enable;
|
||||
/* Configure Ethernet */
|
||||
ETH_RegInit( Ð_InitStructure, gPHYAddress );
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((macAddr[5]<<8) | macAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(macAddr[0] | (macAddr[1]<<8) | (macAddr[2]<<16) | (macAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU,\
|
||||
ENABLE);
|
||||
|
||||
#if LINK_STAT_ACQUISITION_METHOD
|
||||
/* Configure the PHY interrupt function, the supported chip is: RTL8211FS */
|
||||
PHY_InterruptInit( );
|
||||
/* Configure EXTI Line7. */
|
||||
EXTI_Line_Init( );
|
||||
#else
|
||||
ETH_WritePHYRegister( PHY_ADDRESS, 0x1F, 0x0a43 );
|
||||
/*In some cases the status is not updated in time,
|
||||
* so read this register twice to get the correct status value.*/
|
||||
ETH_ReadPHYRegister( PHY_ADDRESS, 0x1A);
|
||||
LastPhyStat = ETH_ReadPHYRegister( PHY_ADDRESS, 0x1A) & 0x04;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_TxPktChainMode
|
||||
*
|
||||
* @brief Ethernet sends data frames in chain mode.
|
||||
*
|
||||
* @param len Send data length
|
||||
* pBuff send buffer pointer
|
||||
*
|
||||
* @return Send status.
|
||||
*/
|
||||
uint32_t ETH_TxPktChainMode(uint16_t len, uint32_t *pBuff )
|
||||
{
|
||||
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
|
||||
if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (u32)RESET)
|
||||
{
|
||||
/* Return ERROR: OWN bit set */
|
||||
return ETH_ERROR;
|
||||
}
|
||||
/* Setting the Frame Length: bits[12:0] */
|
||||
DMATxDescToSet->ControlBufferSize = (len & ETH_DMATxDesc_TBS1);
|
||||
DMATxDescToSet->Buffer1Addr = (uint32_t)pBuff;
|
||||
|
||||
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
|
||||
#if HARDWARE_CHECKSUM_CONFIG
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS | ETH_DMATxDesc_CIC_TCPUDPICMP_Full;
|
||||
#else
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
|
||||
#endif
|
||||
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
DMATxDescToSet->Status |= ETH_DMATxDesc_OWN;
|
||||
|
||||
/* Clear TBUS ETHERNET DMA flag */
|
||||
ETH->DMASR = ETH_DMASR_TBUS;
|
||||
/* Resume DMA transmission*/
|
||||
ETH->DMATPDR = 0;
|
||||
|
||||
/* Update the ETHERNET DMA global Tx descriptor with next Tx descriptor */
|
||||
/* Chained Mode */
|
||||
/* Selects the next DMA Tx descriptor list for next buffer to send */
|
||||
DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr);
|
||||
/* Return SUCCESS */
|
||||
return ETH_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Stop
|
||||
*
|
||||
* @brief Disables ENET MAC and DMA reception/transmission.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Stop(void)
|
||||
{
|
||||
ETH_MACTransmissionCmd(DISABLE);
|
||||
ETH_FlushTransmitFIFO();
|
||||
ETH_MACReceptionCmd(DISABLE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ReInitMACReg
|
||||
*
|
||||
* @brief Reinitialize MAC register.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void ReInitMACReg(void)
|
||||
{
|
||||
uint16_t timeout = 10000;
|
||||
uint32_t maccr, macmiiar, macffr, machthr, machtlr;
|
||||
uint32_t macfcr, macvlantr, dmaomr;
|
||||
|
||||
/* Wait for sending data to complete */
|
||||
while((ETH->DMASR & (7 << 20)) != ETH_DMA_TransmitProcess_Suspended);
|
||||
|
||||
ETH_Stop();
|
||||
|
||||
/* Record the register value */
|
||||
macmiiar = ETH->MACMIIAR;
|
||||
maccr = ETH->MACCR;
|
||||
macffr = ETH->MACFFR;
|
||||
machthr = ETH->MACHTHR;
|
||||
machtlr = ETH->MACHTLR;
|
||||
macfcr = ETH->MACFCR;
|
||||
macvlantr = ETH->MACVLANTR;
|
||||
dmaomr = ETH->DMAOMR;
|
||||
|
||||
/* Reset ETHERNET on AHB Bus */
|
||||
ETH_DeInit();
|
||||
|
||||
/* Software reset */
|
||||
ETH_SoftwareReset();
|
||||
|
||||
/* Wait for software reset */
|
||||
do{
|
||||
Delay_Us(10);
|
||||
if( !--timeout ) break;
|
||||
}while(ETH->DMABMR & ETH_DMABMR_SR);
|
||||
|
||||
/* Configure MAC address */
|
||||
ETH->MACA0HR = (uint32_t)((MACAddr[5]<<8) | MACAddr[4]);
|
||||
ETH->MACA0LR = (uint32_t)(MACAddr[0] | (MACAddr[1]<<8) | (MACAddr[2]<<16) | (MACAddr[3]<<24));
|
||||
|
||||
/* Mask the interrupt that Tx good frame count counter reaches half the maximum value */
|
||||
ETH->MMCTIMR = ETH_MMCTIMR_TGFM;
|
||||
/* Mask the interrupt that Rx good unicast frames counter reaches half the maximum value */
|
||||
/* Mask the interrupt that Rx crc error counter reaches half the maximum value */
|
||||
ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFCEM;
|
||||
|
||||
ETH_DMAITConfig(ETH_DMA_IT_NIS |\
|
||||
ETH_DMA_IT_R |\
|
||||
ETH_DMA_IT_T |\
|
||||
ETH_DMA_IT_AIS |\
|
||||
ETH_DMA_IT_RBU,\
|
||||
ENABLE);
|
||||
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
|
||||
ETH->MACMIIAR = macmiiar;
|
||||
ETH->MACCR = maccr;
|
||||
ETH->MACFFR = macffr;
|
||||
ETH->MACHTHR = machthr;
|
||||
ETH->MACHTLR = machtlr;
|
||||
ETH->MACFCR = macfcr;
|
||||
ETH->MACVLANTR = macvlantr;
|
||||
ETH->DMAOMR = dmaomr;
|
||||
|
||||
ETH_Start( );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_RecProcess
|
||||
*
|
||||
* @brief Receiving related processing
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return none.
|
||||
*/
|
||||
void WCHNET_RecProcess(void)
|
||||
{
|
||||
if(((ChipId & 0xf0) <= 0x20) && \
|
||||
((ETH->DMAMFBOCR & 0x1FFE0000) != 0))
|
||||
{
|
||||
ReInitMACReg();
|
||||
/* Resume DMA transport */
|
||||
ETH->DMARPDR = 0;
|
||||
ETH->DMATPDR = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_ETHIsr
|
||||
*
|
||||
* @brief Ethernet Interrupt Service Routine
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_ETHIsr(void)
|
||||
{
|
||||
uint32_t int_sta;
|
||||
|
||||
int_sta = ETH->DMASR;
|
||||
if (int_sta & ETH_DMA_IT_AIS)
|
||||
{
|
||||
if (int_sta & ETH_DMA_IT_RBU)
|
||||
{
|
||||
WCHNET_RecProcess();
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_RBU);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
|
||||
}
|
||||
|
||||
if( int_sta & ETH_DMA_IT_NIS )
|
||||
{
|
||||
if( int_sta & ETH_DMA_IT_R )
|
||||
{
|
||||
/*If you don't use the Ethernet library,
|
||||
* you can do some data processing operations here*/
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
|
||||
}
|
||||
if( int_sta & ETH_DMA_IT_T )
|
||||
{
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
|
||||
}
|
||||
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_Init
|
||||
*
|
||||
* @brief Ethernet initialization.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ETH_Init( uint8_t *macAddr )
|
||||
{
|
||||
ChipId = DBGMCU_GetCHIPID();
|
||||
ETH_Configuration( macAddr );
|
||||
ETH_DMATxDescChainInit(DMATxDscrTab, MACTxBuf, ETH_TXBUFNB);
|
||||
ETH_DMARxDescChainInit(DMARxDscrTab, MACRxBuf, ETH_RXBUFNB);
|
||||
pDMARxSet = DMARxDscrTab;
|
||||
pDMATxSet = DMATxDscrTab;
|
||||
NVIC_EnableIRQ(ETH_IRQn);
|
||||
NVIC_SetPriority(ETH_IRQn, 0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn ETH_LibInit
|
||||
*
|
||||
* @brief Ethernet library initialization program
|
||||
*
|
||||
* @return command status
|
||||
*/
|
||||
uint8_t ETH_LibInit( uint8_t *ip, uint8_t *gwip, uint8_t *mask, uint8_t *macaddr )
|
||||
{
|
||||
uint8_t s;
|
||||
struct _WCH_CFG cfg;
|
||||
|
||||
memset(&cfg,0,sizeof(cfg));
|
||||
cfg.TxBufSize = ETH_TX_BUF_SZE;
|
||||
cfg.TCPMss = WCHNET_TCP_MSS;
|
||||
cfg.HeapSize = WCHNET_MEM_HEAP_SIZE;
|
||||
cfg.ARPTableNum = WCHNET_NUM_ARP_TABLE;
|
||||
cfg.MiscConfig0 = WCHNET_MISC_CONFIG0;
|
||||
cfg.MiscConfig1 = WCHNET_MISC_CONFIG1;
|
||||
cfg.net_send = ETH_TxPktChainMode;
|
||||
cfg.CheckValid = WCHNET_CFG_VALID;
|
||||
s = WCHNET_ConfigLIB(&cfg);
|
||||
if( s ){
|
||||
return (s);
|
||||
}
|
||||
s = WCHNET_Init(ip,gwip,mask,macaddr);
|
||||
ETH_Init( macaddr );
|
||||
return (s);
|
||||
}
|
||||
|
||||
/******************************** endfile @ eth_driver ******************************/
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
+630
@@ -0,0 +1,630 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : wchnet.h
|
||||
* Author : WCH
|
||||
* Version : V1.90
|
||||
* Date : 2023/05/12
|
||||
* Description : This file contains the headers of
|
||||
* the Ethernet protocol stack library.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __WCHNET_H__
|
||||
#define __WCHNET_H__
|
||||
|
||||
#include "stdint.h"
|
||||
#ifndef NET_LIB
|
||||
#include "net_config.h"
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WCHNET_LIB_VER 0x1B //the library version number
|
||||
#define WCHNET_CFG_VALID 0x12345678 //Configuration value valid flag
|
||||
|
||||
/* LED state @LED_STAT */
|
||||
#define LED_ON 0
|
||||
#define LED_OFF 1
|
||||
|
||||
/* PHY state @PHY_STAT */
|
||||
#define PHY_LINK_SUCCESS (1 << 2) //PHY connection success
|
||||
#define PHY_AUTO_SUCCESS (1 << 5) //PHY auto negotiation completed
|
||||
|
||||
/* Library initialization state @CFG_INIT_STAT */
|
||||
#define INIT_OK 0x00
|
||||
#define INIT_ERR_RX_BUF_SIZE 0x01
|
||||
#define INIT_ERR_TCP_MSS 0x02
|
||||
#define INIT_ERR_HEAP_SIZE 0x03
|
||||
#define INIT_ERR_ARP_TABLE_NEM 0x04
|
||||
#define INIT_ERR_MISC_CONFIG0 0x05
|
||||
#define INIT_ERR_MISC_CONFIG1 0x06
|
||||
#define INIT_ERR_FUNC_SEND 0x09
|
||||
#define INIT_ERR_CHECK_VALID 0xFF
|
||||
|
||||
/* Socket protocol type */
|
||||
#define PROTO_TYPE_IP_RAW 0 //IP layer raw data
|
||||
#define PROTO_TYPE_UDP 2 //UDP protocol
|
||||
#define PROTO_TYPE_TCP 3 //TCP protocol
|
||||
|
||||
/* interrupt status */
|
||||
/* The following are the states
|
||||
* that GLOB_INT will generate */
|
||||
#define GINT_STAT_UNREACH (1 << 0) //unreachable interrupt
|
||||
#define GINT_STAT_IP_CONFLI (1 << 1) //IP conflict interrupt
|
||||
#define GINT_STAT_PHY_CHANGE (1 << 2) //PHY state change interrupt
|
||||
#define GINT_STAT_SOCKET (1 << 4) //socket related interrupt
|
||||
|
||||
/* The following are the states
|
||||
* that Sn_INT will generate*/
|
||||
#define SINT_STAT_RECV (1 << 2) //the socket receives data or the receive buffer is not empty
|
||||
#define SINT_STAT_CONNECT (1 << 3) //connect successfully,generated in TCP mode
|
||||
#define SINT_STAT_DISCONNECT (1 << 4) //disconnect,generated in TCP mode
|
||||
#define SINT_STAT_TIM_OUT (1 << 6) //timeout disconnect,generated in TCP mode
|
||||
|
||||
|
||||
/* Definitions for error constants. @ERR_T */
|
||||
#define ERR_T
|
||||
#define WCHNET_ERR_SUCCESS 0x00 //No error, everything OK
|
||||
#define WCHNET_ERR_BUSY 0x10 //busy
|
||||
#define WCHNET_ERR_MEM 0x11 //Out of memory error
|
||||
#define WCHNET_ERR_BUF 0x12 //Buffer error
|
||||
#define WCHNET_ERR_TIMEOUT 0x13 //Timeout
|
||||
#define WCHNET_ERR_RTE 0x14 //Routing problem
|
||||
#define WCHNET_ERR_ABRT 0x15 //Connection aborted
|
||||
#define WCHNET_ERR_RST 0x16 //Connection reset
|
||||
#define WCHNET_ERR_CLSD 0x17 //Connection closed
|
||||
#define WCHNET_ERR_CONN 0x18 //Not connected
|
||||
#define WCHNET_ERR_VAL 0x19 //Illegal value
|
||||
#define WCHNET_ERR_ARG 0x1a //Illegal argument
|
||||
#define WCHNET_ERR_USE 0x1b //Address in use
|
||||
#define WCHNET_ERR_IF 0x1c //Low-level netif error
|
||||
#define WCHNET_ERR_ISCONN 0x1d //Already connected
|
||||
#define WCHNET_ERR_INPROGRESS 0x1e //Operation in progress
|
||||
#define WCHNET_ERR_SOCKET_MEM 0X20 //Socket information error
|
||||
#define WCHNET_ERR_UNSUPPORT_PROTO 0X21 //unsupported protocol type
|
||||
#define WCHNET_RET_ABORT 0x5F //command process fail
|
||||
#define WCHNET_ERR_UNKNOW 0xFA //unknow
|
||||
|
||||
/* unreachable condition related codes */
|
||||
#define UNREACH_CODE_HOST 0 //host unreachable
|
||||
#define UNREACH_CODE_NET 1 //network unreachable
|
||||
#define UNREACH_CODE_PROTOCOL 2 //protocol unreachable
|
||||
#define UNREACH_CODE_PROT 3 //port unreachable
|
||||
/*For other values, please refer to the RFC792 document*/
|
||||
|
||||
/* TCP disconnect related codes */
|
||||
#define TCP_CLOSE_NORMAL 0 //normal disconnect,a four-way handshake
|
||||
#define TCP_CLOSE_RST 1 //reset the connection and close
|
||||
#define TCP_CLOSE_ABANDON 2 //drop connection, and no termination message is sent
|
||||
|
||||
/* socket state code */
|
||||
#define SOCK_STAT_CLOSED 0X00 //socket close
|
||||
#define SOCK_STAT_OPEN 0X05 //socket open
|
||||
|
||||
/* TCP state code */
|
||||
#define TCP_CLOSED 0 //TCP close
|
||||
#define TCP_LISTEN 1 //TCP listening
|
||||
#define TCP_SYN_SENT 2 //SYN send, connect request
|
||||
#define TCP_SYN_RCVD 3 //SYN received, connection request received
|
||||
#define TCP_ESTABLISHED 4 //TCP connection establishment
|
||||
#define TCP_FIN_WAIT_1 5 //WAIT_1 state
|
||||
#define TCP_FIN_WAIT_2 6 //WAIT_2 state
|
||||
#define TCP_CLOSE_WAIT 7 //wait to close
|
||||
#define TCP_CLOSING 8 //closing
|
||||
#define TCP_LAST_ACK 9 //LAST_ACK
|
||||
#define TCP_TIME_WAIT 10 //2MSL wait
|
||||
|
||||
/* The following values are fixed and cannot be changed */
|
||||
#define WCHNET_MEM_ALIGN_SIZE(size) (((size) + WCHNET_MEM_ALIGNMENT - 1) & ~(WCHNET_MEM_ALIGNMENT - 1))
|
||||
#define WCHNET_SIZE_IPRAW_PCB 0x1C //IPRAW PCB size
|
||||
#define WCHNET_SIZE_UDP_PCB 0x20 //UDP PCB size
|
||||
#define WCHNET_SIZE_TCP_PCB 0xB4 //TCP PCB size
|
||||
#define WCHNET_SIZE_TCP_PCB_LISTEN 0x24 //TCP LISTEN PCB size
|
||||
#define WCHNET_SIZE_IP_REASSDATA 0x20 //IP reassembled Management
|
||||
#define WCHNET_SIZE_PBUF 0x10 //Packet Buf
|
||||
#define WCHNET_SIZE_TCP_SEG 0x14 //TCP SEG structure
|
||||
#define WCHNET_SIZE_MEM 0x08 //sizeof(struct mem)
|
||||
#define WCHNET_SIZE_ARP_TABLE 0x18 //sizeof ARP table
|
||||
|
||||
#define WCHNET_MEMP_SIZE ((WCHNET_MEM_ALIGNMENT - 1) + \
|
||||
(WCHNET_NUM_IPRAW * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IPRAW_PCB)) + \
|
||||
(WCHNET_NUM_UDP * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_UDP_PCB)) + \
|
||||
(WCHNET_NUM_TCP * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB)) + \
|
||||
(WCHNET_NUM_TCP_LISTEN * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_PCB_LISTEN)) + \
|
||||
(WCHNET_NUM_TCP_SEG * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_TCP_SEG)) + \
|
||||
(WCHNET_NUM_IP_REASSDATA * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_IP_REASSDATA)) + \
|
||||
(WCHNET_NUM_PBUF * WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF)) + \
|
||||
(WCHNET_NUM_POOL_BUF * (WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_PBUF) + WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_POOL_BUF))))
|
||||
|
||||
#define HEAP_MEM_ALIGN_SIZE (WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_MEM))
|
||||
#define WCHNET_RAM_HEAP_SIZE (WCHNET_MEM_ALIGN_SIZE(WCHNET_MEM_HEAP_SIZE) + HEAP_MEM_ALIGN_SIZE )
|
||||
#define WCHNET_RAM_ARP_TABLE_SIZE (WCHNET_MEM_ALIGN_SIZE(WCHNET_SIZE_ARP_TABLE) * WCHNET_NUM_ARP_TABLE)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t length;
|
||||
uint32_t buffer;
|
||||
}ETHFrameType;
|
||||
|
||||
/* LED callback type */
|
||||
typedef void (*led_callback)( uint8_t setbit );
|
||||
|
||||
/* net send callback type */
|
||||
typedef uint32_t (*eth_tx_set )( uint16_t len, uint32_t *pBuff );
|
||||
|
||||
/* net receive callback type */
|
||||
typedef uint32_t (*eth_rx_set )( ETHFrameType *pkt );
|
||||
|
||||
/* DNS callback type */
|
||||
typedef void (*dns_callback)( const char *name, uint8_t *ipaddr, void *callback_arg );
|
||||
|
||||
/* DHCP callback type */
|
||||
typedef uint8_t (*dhcp_callback)( uint8_t status, void * );
|
||||
|
||||
/* socket receive callback type */
|
||||
struct _SOCK_INF;
|
||||
typedef void (*pSockRecv)( struct _SOCK_INF *, uint32_t, uint16_t, uint8_t *, uint32_t);
|
||||
|
||||
typedef uint8_t (*pTcpVerifyConnection)(uint32_t src_ip, uint16_t src_port, uint16_t dest_port);
|
||||
|
||||
/* Socket information struct */
|
||||
typedef struct _SOCK_INF
|
||||
{
|
||||
uint32_t IntStatus; //interrupt state
|
||||
uint32_t SockIndex; //Socket index value
|
||||
uint32_t RecvStartPoint; //Start pointer of the receive buffer
|
||||
uint32_t RecvBufLen; //Receive buffer length
|
||||
uint32_t RecvCurPoint; //current pointer to receive buffer
|
||||
uint32_t RecvReadPoint; //The read pointer of the receive buffer
|
||||
uint32_t RecvRemLen; //The length of the remaining data in the receive buffer
|
||||
uint32_t ProtoType; //protocol type
|
||||
uint32_t SockStatus; //Low byte Socket state, the next low byte is TCP state, only meaningful in TCP mode
|
||||
uint32_t DesPort; //destination port
|
||||
uint32_t SourPort; //Source port, protocol type in IPRAW mode
|
||||
uint8_t IPAddr[4]; //Socket destination IP address
|
||||
void *Resv1; //Reserved, for internal use, for saving individual PCBs
|
||||
void *Resv2; //Reserved, used internally, used by TCP Server
|
||||
pSockRecv AppCallBack; //receive callback function
|
||||
} SOCK_INF;
|
||||
|
||||
struct _WCH_CFG
|
||||
{
|
||||
uint32_t TxBufSize; //MAC send buffer size, reserved for use
|
||||
uint32_t TCPMss; //TCP MSS size
|
||||
uint32_t HeapSize; //heap memory size
|
||||
uint32_t ARPTableNum; //Number of ARP lists
|
||||
uint32_t MiscConfig0; //Miscellaneous Configuration 0
|
||||
/* Bit 0 TCP send buffer copy 1: copy, 0: not copy */
|
||||
/* Bit 1 TCP receive replication optimization, used for internal debugging */
|
||||
/* bit 2 delete oldest TCP connection 1: enable, 0: disable */
|
||||
/* Bits 3-7 Number of PBUFs of IP segments */
|
||||
/* Bit 8 TCP Delay ACK disable */
|
||||
uint32_t MiscConfig1; //Miscellaneous Configuration 1
|
||||
/* Bits 0-7 Number of Sockets*/
|
||||
/* Bits 8-12 Reserved */
|
||||
/* Bit 13 PING enable, 1: On 0: Off */
|
||||
/* Bits 14-18 TCP retransmission times */
|
||||
/* Bits 19-23 TCP retransmission period, in 50 milliseconds */
|
||||
/* bit 25 send failed retry, 1: enable, 0: disable */
|
||||
/* bit 26 Select whether to perform IPv4 checksum check on
|
||||
* the TCP/UDP/ICMP header of the received frame payload by hardware,
|
||||
* and calculate and insert the checksum of the IP header and payload of the sent frame by hardware.*/
|
||||
/* Bits 27-31 period (in 250 milliseconds) of Fine DHCP periodic process */
|
||||
led_callback led_link; //PHY Link Status Indicator
|
||||
led_callback led_data; //Ethernet communication indicator
|
||||
eth_tx_set net_send; //Ethernet send
|
||||
eth_rx_set net_recv; //Ethernet receive
|
||||
uint32_t CheckValid; //Configuration value valid flag, fixed value @WCHNET_CFG_VALID
|
||||
};
|
||||
|
||||
struct _NET_SYS
|
||||
{
|
||||
uint8_t IPAddr[4]; //IP address
|
||||
uint8_t GWIPAddr[4]; //Gateway IP address
|
||||
uint8_t MASKAddr[4]; //subnet mask
|
||||
uint8_t MacAddr[8]; //MAC address
|
||||
uint8_t UnreachIPAddr[4]; //Unreachable IP address
|
||||
uint32_t RetranCount; //number of retries,default is 10 times
|
||||
uint32_t RetranPeriod; //Retry period, unit MS, default 500MS
|
||||
uint32_t PHYStat; //PHY state code
|
||||
uint32_t NetStat; //The status of the Ethernet, including whether it is open, etc.
|
||||
uint32_t MackFilt; //MAC filtering, the default is to receive broadcasts, receive local MAC
|
||||
uint32_t GlobIntStatus; //global interrupt
|
||||
uint32_t UnreachCode; //unreachable code
|
||||
uint32_t UnreachProto; //unreachable protocol
|
||||
uint32_t UnreachPort; //unreachable port
|
||||
uint32_t SendFlag;
|
||||
uint32_t Flags;
|
||||
};
|
||||
|
||||
/* KEEP LIVE configuration structure */
|
||||
struct _KEEP_CFG
|
||||
{
|
||||
uint32_t KLIdle; //KEEPLIVE idle time, in ms
|
||||
uint32_t KLIntvl; //KEEPLIVE period, in ms
|
||||
uint32_t KLCount; //KEEPLIVE times
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Library initialization .
|
||||
*
|
||||
* @param ip - IP address pointer
|
||||
* @param gwip - Gateway address pointer
|
||||
* @param mask - Subnet mask pointer
|
||||
* @param macaddr - MAC address pointer
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_Init(const uint8_t *ip, const uint8_t *gwip, const uint8_t *mask, const uint8_t *macaddr);
|
||||
|
||||
/**
|
||||
* @brief get library version
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return library version
|
||||
*/
|
||||
uint8_t WCHNET_GetVer(void);
|
||||
|
||||
/**
|
||||
* @brief Get MAC address.
|
||||
*
|
||||
* @param(in) macaddr - MAC address
|
||||
*
|
||||
* @param(out) MAC address
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_GetMacAddr(uint8_t *macaddr);
|
||||
|
||||
/**
|
||||
* @brief Library parameter configuration.
|
||||
*
|
||||
* @param cfg - Configuration parameter @_WCH_CFG
|
||||
*
|
||||
* @return Library configuration initialization state @CFG_INIT_STAT
|
||||
*/
|
||||
uint8_t WCHNET_ConfigLIB(struct _WCH_CFG *cfg);
|
||||
|
||||
/**
|
||||
* @brief Handle periodic tasks in the protocol stack
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_PeriodicHandle(void);
|
||||
|
||||
/**
|
||||
* @brief Ethernet data input. Always called in the main program,
|
||||
* or called after the reception interrupt is detected.
|
||||
*
|
||||
* @param
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_NetInput( void );
|
||||
|
||||
/**
|
||||
* @brief Ethernet interrupt service function. Called after
|
||||
* Ethernet interrupt is generated.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_ETHIsr(void);
|
||||
|
||||
/**
|
||||
* @brief Get PHY status
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return PHY status @PHY_STAT
|
||||
*/
|
||||
uint8_t WCHNET_GetPHYStatus(void);
|
||||
|
||||
/**
|
||||
* @brief Query global interrupt status.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return GLOB_INT
|
||||
*/
|
||||
uint8_t WCHNET_QueryGlobalInt(void);
|
||||
|
||||
/**
|
||||
* @brief Read global interrupt and clear it.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return GLOB_INT
|
||||
*/
|
||||
uint8_t WCHNET_GetGlobalInt(void);
|
||||
|
||||
/**
|
||||
* @brief create socket
|
||||
*
|
||||
* @param(in) *socketid - socket variable pointer
|
||||
* @param socinf - Configuration parameters for creating sockets @SOCK_INF
|
||||
*
|
||||
* @param(out) *socketid - socket value
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketCreat( uint8_t *socketid, SOCK_INF *socinf);
|
||||
|
||||
/**
|
||||
* @brief Socket sends data.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param *buf - the first address of send buffer
|
||||
* @param(in) *len - pointer to the length of the data expected to be sent
|
||||
*
|
||||
* @param(out) *len - pointer to the length of the data sent actually
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketSend( uint8_t socketid, uint8_t *buf, uint32_t *len);
|
||||
|
||||
/**
|
||||
* @brief Socket receives data.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param *buf - the first address of receive buffer
|
||||
* @param(in) *len - pointer to the length of the data expected to be read
|
||||
*
|
||||
* @param(out) *buf - the first address of data buffer
|
||||
* @param(out) *len - pointer to the length of the data read actually
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketRecv( uint8_t socketid, uint8_t *buf, uint32_t *len);
|
||||
|
||||
/**
|
||||
* @brief Get socket interrupt, and clear socket interrupt.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
*
|
||||
* @return Sn_INT
|
||||
*/
|
||||
uint8_t WCHNET_GetSocketInt( uint8_t socketid );
|
||||
|
||||
/**
|
||||
* @brief Get the length of the data received by socket.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param(in) *bufaddr - the first address of receive buffer
|
||||
*
|
||||
* @param(out) *bufaddr - the first address of data buffer
|
||||
*
|
||||
* @return the length of the data
|
||||
*/
|
||||
uint32_t WCHNET_SocketRecvLen( uint8_t socketid, uint32_t *bufaddr);
|
||||
|
||||
/**
|
||||
* @brief TCP connect. Used in TCP Client mode.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketConnect( uint8_t socketid);
|
||||
|
||||
/**
|
||||
* @brief TCP listen. Used in TCP SERVER mode.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketListen( uint8_t socketid);
|
||||
|
||||
/**
|
||||
* @brief Close socket.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param mode - the way of disconnection.Used in TCP connection.
|
||||
* @TCP disconnect related codes
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketClose( uint8_t socketid, uint8_t mode );
|
||||
|
||||
/**
|
||||
* @brief Modify socket receive buffer.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param bufaddr - Address of the receive buffer
|
||||
* @param bufsize - Size of the receive buffer
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_ModifyRecvBuf( uint8_t socketid, uint32_t bufaddr, uint32_t bufsize);
|
||||
|
||||
/**
|
||||
* @brief UDP send, specify the target IP and target port
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param *buf - Address of the sent data
|
||||
* @param(in) *slen - Address of the sent length
|
||||
* @param *sip - destination IP address
|
||||
* @param port - destination port
|
||||
*
|
||||
* @param(out) *slen - actual length sent
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketUdpSendTo( uint8_t socketid, uint8_t *buf, uint32_t *slen, uint8_t *sip, uint16_t port);
|
||||
|
||||
/**
|
||||
* @brief Convert ASCII address to network address.
|
||||
*
|
||||
* @param *cp - ASCII address to be converted, such as "192.168.1.2"
|
||||
* @param(in) *addr - First address of the memory stored in the converted network address
|
||||
* @param(out) *addr - Converted network address, such as 0xC0A80102
|
||||
* @return 0 - Success. Others - Failure.
|
||||
*/
|
||||
uint8_t WCHNET_Aton(const char *cp, uint8_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Convert network address to ASCII address.
|
||||
*
|
||||
* @param *ipaddr - socket id value
|
||||
*
|
||||
* @return Converted ASCII address
|
||||
*/
|
||||
uint8_t *WCHNET_Ntoa( uint8_t *ipaddr);
|
||||
|
||||
/**
|
||||
* @brief Set socket TTL.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param ttl - TTL value
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SetSocketTTL( uint8_t socketid, uint8_t ttl);
|
||||
|
||||
/**
|
||||
* @brief Start TCP retry sending immediately.
|
||||
*
|
||||
* @param socketid - TTL value
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_RetrySendUnack( uint8_t socketid);
|
||||
|
||||
/**
|
||||
* @brief Query the packets that are not sent successfully.
|
||||
*
|
||||
* @param socketid - TTL value
|
||||
* @param(in) *addrlist - pointer to the address of the address list
|
||||
* @param lislen - Length of the list
|
||||
*
|
||||
* @param(out) *addrlist - Address list of the data packets that are not sent successfully
|
||||
*
|
||||
* @return Number of unsent and unacknowledged segments
|
||||
*/
|
||||
uint8_t WCHNET_QueryUnack( uint8_t socketid, uint32_t *addrlist, uint16_t lislen );
|
||||
|
||||
/**
|
||||
* @brief Start DHCP.
|
||||
*
|
||||
* @param dhcp - Application layer callback function
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_DHCPStart( dhcp_callback dhcp );
|
||||
|
||||
/**
|
||||
* @brief Stop DHCP.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_DHCPStop( void );
|
||||
|
||||
/**
|
||||
* @brief Configure DHCP host name.
|
||||
*
|
||||
* @param *name - First address of DHCP host name
|
||||
*
|
||||
* @return 0 - Success. Others - Failure.
|
||||
*/
|
||||
uint8_t WCHNET_DHCPSetHostname(char *name);
|
||||
|
||||
/**
|
||||
* @brief Initialize the resolver: set up the UDP pcb and configure the default server
|
||||
*
|
||||
* @param *dnsip - the IP address of dns server
|
||||
* @param port - the port number of dns server
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_InitDNS( uint8_t *dnsip, uint16_t port);
|
||||
|
||||
/**
|
||||
* @brief Stop DNS.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_DNSStop(void);
|
||||
|
||||
/**
|
||||
* Resolve a hostname (string) into an IP address.
|
||||
*
|
||||
* @param hostname - the hostname that is to be queried
|
||||
* @param addr - pointer to a struct ip_addr where to store the address if it is already
|
||||
* cached in the dns_table (only valid if ERR_OK is returned!)
|
||||
* @param found - a callback function to be called on success, failure or timeout (only if
|
||||
* ERR_INPROGRESS is returned!)
|
||||
* @param arg - argument to pass to the callback function
|
||||
*
|
||||
* @return @ERR_T
|
||||
* WCHNET_ERR_SUCCESS if hostname is a valid IP address string or the host name is already in the local names table.
|
||||
* ERR_INPROGRESS enqueue a request to be sent to the DNS server for resolution if no errors are present.
|
||||
*/
|
||||
uint8_t WCHNET_HostNameGetIp( const char *hostname, uint8_t *addr, dns_callback found, void *arg );
|
||||
|
||||
/**
|
||||
* @brief Configure KEEP LIVE parameter.
|
||||
*
|
||||
* @param *cfg - KEEPLIVE configuration parameter
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_ConfigKeepLive( struct _KEEP_CFG *cfg );
|
||||
|
||||
/**
|
||||
* @brief Configure ARP retransmission parameters.
|
||||
*
|
||||
* @param retry_period - ARP retransmission period, the default value is 10, the unit is 100ms
|
||||
* retry_cnt - The number of ARP retransmissions, the default value is 3.
|
||||
* When the value of the retry_cnt is 0xff, it will be retried
|
||||
* until the MAC address of the device is obtained.
|
||||
* Arp_Entry_timeout_s - the time an ARP entry stays valid after its last update.
|
||||
* the default value is 300, the unit is 1s
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_ARPRetryCfg(uint8_t retry_period, uint8_t retry_cnt, uint16_t Arp_Entry_timeout_s);
|
||||
|
||||
/**
|
||||
* @brief Configure socket KEEP LIVE enable.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param enable - 1: Enabled. 0: Disabled.
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketSetKeepLive( uint8_t socketid, uint8_t enable );
|
||||
|
||||
/**
|
||||
* @brief Configure PHY state
|
||||
*
|
||||
* @param phy_stat - PHY state
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void WCHNET_PhyStatus( uint32_t phy_stat );
|
||||
|
||||
/**
|
||||
* @brief Configure socket Nagle Func.
|
||||
*
|
||||
* @param socketid - socket id value
|
||||
* @param enable - 1: Enabled. 0: Disabled.
|
||||
*
|
||||
* @return @ERR_T
|
||||
*/
|
||||
uint8_t WCHNET_SocketSetNagle( uint8_t socketid, uint8_t enable );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user