ch32v307_camera/NetLib/eth_driver_RGMII.c
2026-03-15 16:22:19 +08:00

715 lines
23 KiB
C

/********************************** (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( &ETH_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 ******************************/