123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770 |
- /*
- * Copyright (c) 2006-2024, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-09-09 WCH the first version
- */
- #include "board.h"
- #include <rtdevice.h>
- #ifdef BSP_USING_ETH
- #include <netif/ethernetif.h>
- #include "lwipopts.h"
- #include <drv_eth.h>
- #define LOG_TAG "drv.eth"
- #include <drv_log.h>
- #define MAX_ADDR_LEN 6
- #define ETH_DMARxDesc_FrameLengthShift 16
- #define define_O(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 define_I(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)
- /* globe variable */
- extern ETH_DMADESCTypeDef *DMATxDescToSet; //set tx Desc then send it
- extern ETH_DMADESCTypeDef *DMARxDescToGet; //current rx Desc
- /* rt-thread eth */
- struct rt_ch32_eth
- {
- /* inherit from ethernet device */
- struct eth_device parent;
- #ifndef PHY_USING_INTERRUPT_MODE
- rt_timer_t poll_link_timer;
- #endif
- /* interface address info, hw address */
- rt_uint8_t dev_addr[MAX_ADDR_LEN];
- /* ETH_Speed */
- uint32_t ETH_Speed;
- /* ETH_Duplex_Mode */
- uint32_t ETH_Mode;
- };
- static ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
- static rt_uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE],Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE];
- struct rt_ch32_eth ch32v30x_eth_device;
- //#define ETH_RX_DUMP
- #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
- #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
- static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
- {
- unsigned char *buf = (unsigned char *)ptr;
- int i, j;
- for (i = 0; i < buflen; i += 16)
- {
- rt_kprintf("%08X: ", i);
- for (j = 0; j < 16; j++)
- if (i + j < buflen)
- rt_kprintf("%02X ", buf[i + j]);
- else
- rt_kprintf(" ");
- rt_kprintf(" ");
- for (j = 0; j < 16; j++)
- if (i + j < buflen)
- rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
- rt_kprintf("\r\n");
- }
- }
- #endif
- /* received data */
- FrameTypeDef ETH_RxPkt_ChainMode(void)
- {
- u32 framelength = 0;
- FrameTypeDef frame = {0,0,NULL};
- /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
- if((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) != (u32)RESET)
- {
- frame.length = ETH_ERROR;
- if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
- {
- /* Clear RBUS ETHERNET DMA flag */
- ETH->DMASR = ETH_DMASR_RBUS;
- /* Resume DMA reception */
- ETH->DMARPDR = 0;
- }
- LOG_E("Error:ETH_DMARxDesc_OWN.\r\n");
- /* Return error: OWN bit set */
- return frame;
- }
- if(
- ((DMARxDescToGet->Status & ETH_DMARxDesc_ES) == (u32)RESET) &&
- ((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (u32)RESET) &&
- ((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (u32)RESET))
- {
- /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
- framelength = ((DMARxDescToGet->Status & ETH_DMARxDesc_FL) >> ETH_DMARxDesc_FrameLengthShift) - 4;
- /* Get the addrees of the actual buffer */
- frame.buffer = DMARxDescToGet->Buffer1Addr;
- }
- else
- {
- /* Return ERROR */
- framelength = ETH_ERROR;
- rt_kprintf("Error:recv error frame,status:0x%08x.\r\n",DMARxDescToGet->Status);
- }
- DMARxDescToGet->Status|=ETH_DMARxDesc_OWN;
- frame.length = framelength;
- frame.descriptor = DMARxDescToGet;
- /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */
- /* Chained Mode */
- /* Selects the next DMA Rx descriptor list for next buffer to read */
- DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr);
- /* Return Frame */
- return (frame);
- }
- /*******************************************************************************
- * Function Name : GETH_pin_init
- * Description : PHY RGMII interface GPIO initialization.
- * Input : None.
- * Return : None.
- *******************************************************************************/
- void GETH_pin_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- /* PB12/13 set AF_PP_OUT */
- 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);
- define_O(GPIOA,GPIO_Pin_2);
- define_O(GPIOA,GPIO_Pin_3);
- define_O(GPIOA,GPIO_Pin_7);
- define_O(GPIOC,GPIO_Pin_4);
- define_O(GPIOC,GPIO_Pin_5);
- define_O(GPIOB,GPIO_Pin_0);
- define_I(GPIOC,GPIO_Pin_0);
- define_I(GPIOC,GPIO_Pin_1);
- define_I(GPIOC,GPIO_Pin_2);
- define_I(GPIOC,GPIO_Pin_3);
- define_I(GPIOA,GPIO_Pin_0);
- define_I(GPIOA,GPIO_Pin_1);
- define_I(GPIOB,GPIO_Pin_1);/* 125m in */
- }
- /*******************************************************************************
- * Function Name : GETH_pin_init
- * Description : PHY MII/RMII interface GPIO initialization.
- * Input : None.
- * Return : None.
- *******************************************************************************/
- void FETH_pin_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- #ifdef USE_RMII
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
- GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII);
- define_O(GPIOA,GPIO_Pin_2);/* MDC */
- define_O(GPIOC,GPIO_Pin_1);/* MDIO */
- define_O(GPIOB,GPIO_Pin_11);//txen
- define_O(GPIOB,GPIO_Pin_12);//txd0
- define_O(GPIOB,GPIO_Pin_13);//txd1
- define_I(GPIOA,GPIO_Pin_1);/* PA1 REFCLK */
- define_I(GPIOA,GPIO_Pin_7);/* PA7 CRSDV */
- define_I(GPIOC,GPIO_Pin_4);/* RXD0 */
- define_I(GPIOC,GPIO_Pin_5);/* RXD1 */
- #else
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);
- /* tx */
- define_O(GPIOA,GPIO_Pin_2);/* MDC */
- define_O(GPIOC,GPIO_Pin_1);/* MDIO */
- define_I(GPIOC,GPIO_Pin_3);//txclk
- define_O(GPIOB,GPIO_Pin_11);//txen
- define_O(GPIOB,GPIO_Pin_12);//txd0
- define_O(GPIOB,GPIO_Pin_13);//txd1
- define_O(GPIOC,GPIO_Pin_2); //txd2
- define_O(GPIOB,GPIO_Pin_8);//txd3
- /* tx */
- define_I(GPIOA,GPIO_Pin_1);/* PA1 RXC */
- define_I(GPIOA,GPIO_Pin_7);/* PA7 RXDV */
- define_I(GPIOC,GPIO_Pin_4);/* RXD0 */
- define_I(GPIOC,GPIO_Pin_5);/* RXD1 */
- define_I(GPIOB,GPIO_Pin_0);/* RXD2 */
- define_I(GPIOB,GPIO_Pin_1);/* RXD3 */
- define_I(GPIOB,GPIO_Pin_10);/* RXER */
- define_O(GPIOA,GPIO_Pin_0);/* PA0 */
- define_O(GPIOA,GPIO_Pin_3);/* PA3 */
- #endif
- }
- /*******************************************************************************
- * Function Name : ETH_Init
- * Description : ETH initialization.
- * Input : ETH_InitStruct:initialization struct.
- * PHYAddress:PHY address.
- * Return : Initialization status.
- *******************************************************************************/
- uint32_t ETH_Init(ETH_InitTypeDef* ETH_InitStruct, uint16_t PHYAddress)
- {
- uint32_t tmpreg = 0;
- uint16_t RegValue = 0;
- uint32_t tickstart=0;
- /* config phy */
- tmpreg = ETH->MACMIIAR;
- tmpreg &= MACMIIAR_CR_MASK;
- /* set SMI clock */
- tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div42;
- ETH->MACMIIAR = (uint32_t)tmpreg;
- /* reset phy */
- ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_Reset);
- tickstart= rt_tick_get_millisecond();
- do{
- asm("nop"); /* waiting for finish */
- }while((rt_tick_get_millisecond()-tickstart)<1000);
- tickstart= rt_tick_get_millisecond();
- RegValue = 0;
- while( (RegValue&(PHY_Reset)) )
- {
- RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_BCR);
- if((rt_tick_get_millisecond()-tickstart)>10000)
- {
- LOG_E("Error:Wait phy reset timeout!\r\n");
- while(1);
- }
- }
- /* waiting for link up */
- tickstart= rt_tick_get_millisecond();
- RegValue = 0;
- while((RegValue&(PHY_Linked_Status)) == 0)
- {
- RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_BSR);
- if((rt_tick_get_millisecond()-tickstart)>10000)
- {
- LOG_E("Error:Wait phy linking timeout!\r\n");
- while(1);
- }
- }
- /* waiting for auto-negotiation */
- tickstart= rt_tick_get_millisecond();
- RegValue = 0;
- while((RegValue&PHY_AutoNego_Complete) == 0)
- {
- RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_BSR);
- if((rt_tick_get_millisecond()-tickstart)>10000)
- {
- LOG_E("Error:Wait phy auto-negotiation complete timeout!\r\n");
- while(1);
- }
- }
- #ifdef USE10BASE_T
- RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_BMCR);
- LOG_D("PHY_BMCR:%d,value:%04x.\n",PHY_BMCR,RegValue);
- if((RegValue & (1<<8)) != (uint32_t)RESET)
- {
- ETH_InitStruct->ETH_Mode = ETH_Mode_FullDuplex;
- ch32v30x_eth_device.ETH_Mode=ETH_Mode_FullDuplex;
- LOG_D("Full-Duplex.\n");
- }
- else
- {
- ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex;
- ch32v30x_eth_device.ETH_Mode=ETH_Mode_HalfDuplex;
- LOG_D("Half-Duplex.\n");
- }
- if(RegValue & (1<<13))
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_100M;
- ch32v30x_eth_device.ETH_Speed=ETH_Speed_100M;
- /* send link up. */
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:100M.\n");
- }
- else
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_10M;
- ch32v30x_eth_device.ETH_Speed=ETH_Speed_10M;
- /* send link up. */
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:10M.\n");
- }
- #endif
- #ifdef USE_FAST_MAC
- /* 100M MAC,RMII */
- RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_BMCR);
- LOG_D("PHY_BMCR:%d,value:%04x.\n",PHY_BMCR,RegValue);
- if((RegValue & (1<<8)) != (uint32_t)RESET)
- {
- ETH_InitStruct->ETH_Mode = ETH_Mode_FullDuplex;
- ch32v30x_eth_device.ETH_Mode = ETH_Mode_FullDuplex;
- LOG_D("Full-Duplex.\n");
- }
- else
- {
- ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex;
- ch32v30x_eth_device.ETH_Mode = ETH_Mode_HalfDuplex;
- LOG_D("Half-Duplex.\n");
- }
- if(RegValue & (1<<13))
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_100M;
- ch32v30x_eth_device.ETH_Speed=ETH_Speed_100M;
- /* send link up. */
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:100M.\n");
- }
- else
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_10M;
- ch32v30x_eth_device.ETH_Speed=ETH_Speed_10M;
- /* send link up. */
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:10M.\n");
- }
- #endif
- #ifdef USE_GIGA_MAC
- /* GMAC,RGMI */
- ETH_WritePHYRegister(PHYAddress, 31,0x0a43 );
- RegValue = ETH_ReadPHYRegister(PHYAddress, 26);
- if( RegValue & 0x0008 )
- {
- ETH_InitStruct->ETH_Mode = ETH_Mode_FullDuplex;
- ch32v30x_eth_device.ETH_Mode = ETH_Mode_FullDuplex;
- LOG_D("full duplex.\n");
- }
- else
- {
- ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex;
- ch32v30x_eth_device.ETH_Mode = ETH_Mode_HalfDuplex;
- LOG_D("half duplex!\n");
- }
- if(( RegValue & 0x0030 ) == 0x0000)
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_10M;
- ch32v30x_eth_device.ETH_Speed= ETH_Speed_10M;
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:10Mbps.\n");
- }
- else if(( RegValue & 0x0030 ) == 0x0010)
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_100M;
- ch32v30x_eth_device.ETH_Speed= ETH_Speed_100M;
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:100Mbps.\n");
- }
- else if(( RegValue & 0x0030 ) == 0x0020)
- {
- ETH_InitStruct->ETH_Speed = ETH_Speed_1000M;
- ch32v30x_eth_device.ETH_Speed= ETH_Speed_1000M;
- eth_device_linkchange(&ch32v30x_eth_device.parent, RT_TRUE);
- LOG_D("Link speed:1000Mbps.\n");
- }
- #endif
- tickstart= rt_tick_get_millisecond();
- do{
- asm("nop");
- }while((rt_tick_get_millisecond()-tickstart)<1000);
- /* MAC config */
- /* if use RGMII,should config RGMII clock delay register */
- tmpreg = ETH->MACCR;
- tmpreg &= MACCR_CLEAR_MASK;
- tmpreg |= (uint32_t)(ETH_InitStruct->ETH_Watchdog |
- ETH_InitStruct->ETH_Jabber |
- ETH_InitStruct->ETH_InterFrameGap |
- ETH_InitStruct->ETH_CarrierSense |
- ETH_InitStruct->ETH_Speed |
- ETH_InitStruct->ETH_ReceiveOwn |
- ETH_InitStruct->ETH_LoopbackMode |
- ETH_InitStruct->ETH_Mode |
- ETH_InitStruct->ETH_ChecksumOffload |
- ETH_InitStruct->ETH_RetryTransmission |
- ETH_InitStruct->ETH_AutomaticPadCRCStrip |
- ETH_InitStruct->ETH_BackOffLimit |
- ETH_InitStruct->ETH_DeferralCheck);
- ETH->MACCR = (uint32_t)tmpreg;
- #ifdef USE10BASE_T
- /* enable internal pull up resistance,50Ω */
- ETH->MACCR|=ETH_Internal_Pull_Up_Res_Enable;
- #endif
- 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);
- /* Write to ETHERNET MACHTHR */
- ETH->MACHTHR = (uint32_t)ETH_InitStruct->ETH_HashTableHigh;
- /* Write to ETHERNET MACHTLR */
- ETH->MACHTLR = (uint32_t)ETH_InitStruct->ETH_HashTableLow;
- /* Get the ETHERNET MACFCR value */
- tmpreg = ETH->MACFCR;
- /* Clear xx bits */
- tmpreg &= MACFCR_CLEAR_MASK;
- tmpreg |= (uint32_t)((ETH_InitStruct->ETH_PauseTime << 16) |
- ETH_InitStruct->ETH_ZeroQuantaPause |
- ETH_InitStruct->ETH_PauseLowThreshold |
- ETH_InitStruct->ETH_UnicastPauseFrameDetect |
- ETH_InitStruct->ETH_ReceiveFlowControl |
- ETH_InitStruct->ETH_TransmitFlowControl);
- ETH->MACFCR = (uint32_t)tmpreg;
- ETH->MACVLANTR = (uint32_t)(ETH_InitStruct->ETH_VLANTagComparison |
- ETH_InitStruct->ETH_VLANTagIdentifier);
- tmpreg = ETH->DMAOMR;
- /* Clear xx bits */
- tmpreg &= DMAOMR_CLEAR_MASK;
- tmpreg |= (uint32_t)(ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame |
- ETH_InitStruct->ETH_ReceiveStoreForward |
- ETH_InitStruct->ETH_FlushReceivedFrame |
- ETH_InitStruct->ETH_TransmitStoreForward |
- ETH_InitStruct->ETH_TransmitThresholdControl |
- ETH_InitStruct->ETH_ForwardErrorFrames |
- ETH_InitStruct->ETH_ForwardUndersizedGoodFrames |
- ETH_InitStruct->ETH_ReceiveThresholdControl |
- ETH_InitStruct->ETH_SecondFrameOperate);
- ETH->DMAOMR = (uint32_t)tmpreg;
- ETH->DMABMR = (uint32_t)(ETH_InitStruct->ETH_AddressAlignedBeats |
- ETH_InitStruct->ETH_FixedBurst |
- ETH_InitStruct->ETH_RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
- ETH_InitStruct->ETH_TxDMABurstLength |
- (ETH_InitStruct->ETH_DescriptorSkipLength << 2) |
- ETH_InitStruct->ETH_DMAArbitration |
- ETH_DMABMR_USP);
- return ETH_SUCCESS;
- }
- /* eth initialization function */
- static rt_err_t rt_ch32_eth_init(rt_device_t dev)
- {
- ETH_InitTypeDef ETH_InitStructure={0};
- RCC_PLL3Cmd(DISABLE);
- RCC_PREDIV2Config(RCC_PREDIV2_Div2);
- RCC_PLL3Config(RCC_PLL3Mul_15);
- RCC_PLL3Cmd(ENABLE);
- while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLL3RDY));
- LOG_D("PLL3 Init Finish\r\n");
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC|RCC_AHBPeriph_ETH_MAC_Tx|RCC_AHBPeriph_ETH_MAC_Rx,ENABLE);
- #ifdef USE10BASE_T
- /* Enable internal 10BASE-T PHY*/
- EXTEN->EXTEN_CTR |=EXTEN_ETH_10M_EN;
- #endif
- #ifdef USE_GIGA_MAC
- /* Enable 1G MAC*/
- EXTEN->EXTEN_CTR |= EXTEN_ETH_RGMII_SEL;
- /* mac clock use external 125MHz,input from PB1 */
- RCC_ETH1GCLKConfig(RCC_ETH1GCLKSource_PB1_IN);
- RCC_ETH1G_125Mcmd(ENABLE);
- /* Enable RGMII GPIO */
- GETH_pin_init();
- #endif
- #ifdef USE_FAST_MAC
- /* Enable MII or RMII GPIO */
- FETH_pin_init();
- #endif
- /* Reset ETHERNET on AHB Bus */
- ETH_DeInit();
- /* Software reset */
- ETH_SoftwareReset();
- /* Wait for software reset */
- while(ETH->DMABMR & ETH_DMABMR_SR);
- LOG_D("ETH RST Finish\r\n");
- ETH_StructInit(Ð_InitStructure);
- ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
- ETH_InitStructure.ETH_Speed = ETH_Speed_1000M;
- ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable ;
- ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
- ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
- ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
- ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable;
- ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
- ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Enable;
- ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
- ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
- #ifdef CHECKSUM_BY_HARDWARE
- ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
- #endif
- /*------------------------ 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_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
- ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
- ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Enable;
- ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Enable;
- ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Disable;
- ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
- ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
- ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
- ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
- ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
- /* Configure Ethernet */
- ETH_Init(Ð_InitStructure, PHY_ADDRESS);
- /* Enable the Ethernet Rx Interrupt */
- ETH_DMAITConfig(ETH_DMA_IT_NIS
- | ETH_DMA_IT_R
- | ETH_DMA_IT_T
- ,ENABLE);
- NVIC_SetPriority(ETH_IRQn,1<<4);
- NVIC_EnableIRQ(ETH_IRQn);
- ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
- ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
- #ifdef USE_GIGA_MAC
- RGMII_TXC_Delay(0,2);
- #endif
- ETH_Start();
- return RT_EOK;
- }
- static rt_err_t rt_ch32_eth_open(rt_device_t dev, rt_uint16_t oflag)
- {
- LOG_D("eth open\r\n");
- return RT_EOK;
- }
- static rt_err_t rt_ch32_eth_close(rt_device_t dev)
- {
- LOG_D("eth close\r\n");
- return RT_EOK;
- }
- static rt_ssize_t rt_ch32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
- {
- LOG_D("eth read\r\n");
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- static rt_ssize_t rt_ch32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
- {
- LOG_D("eth write\r\n");
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- static rt_err_t rt_ch32_eth_control(rt_device_t dev, int cmd, void *args)
- {
- switch (cmd)
- {
- case NIOCTL_GADDR:
- /* get mac address */
- if (args) rt_memcpy(args, ch32v30x_eth_device.dev_addr, 6);
- else return -RT_ERROR;
- break;
- default :
- break;
- }
- return RT_EOK;
- }
- rt_err_t rt_ch32_eth_tx(rt_device_t dev, struct pbuf *p)
- {
- rt_err_t ret = RT_ERROR;
- struct pbuf *q;
- uint8_t *buffer = (uint8_t *)(DMATxDescToSet->Buffer1Addr);
- uint8_t *pdata;
- uint32_t framelength = 0,len=0;
- /* copy frame from pbufs to driver buffers */
- for (q = p; q != NULL; q = q->next)
- {
- /* Is this buffer available? If not, goto error */
- if ((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET)
- {
- LOG_E("buffer not valid\r\n");
- ret = ERR_USE;
- goto Tx_error;
- }
- pdata = q->payload;
- len = q->len;
- framelength += len;
- rt_memcpy(buffer,pdata,len);
- buffer += len;
- }
- #ifdef ETH_TX_DUMP
- dump_hex(buffer, p->tot_len);
- #endif
- DMATxDescToSet->ControlBufferSize = (framelength & ETH_DMATxDesc_TBS1);
- DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
- DMATxDescToSet->Status |= ETH_DMATxDesc_OWN;
- ret = ERR_OK;
- Tx_error:
- /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
- if ((ETH->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET)
- {
- /* Clear TUS ETHERNET DMA flag */
- ETH->DMASR = ETH_DMASR_TUS;
- /* Resume DMA transmission*/
- ETH->DMATPDR = 0;
- }
- DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr);
- return ret;
- }
- volatile FrameTypeDef frame;
- struct pbuf *rt_ch32_eth_rx(rt_device_t dev)
- {
- struct pbuf *p = NULL;
- struct pbuf *q = NULL;
- uint16_t len = 0;
- uint8_t *buffer;
- uint8_t *pdata;
- if(!frame.length)
- {
- return NULL;
- }
- len=frame.length;
- frame.length=0;
- buffer=(uint8_t *)frame.buffer;
- if (len > 0)
- {
- /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
- p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- }
- #ifdef ETH_RX_DUMP
- dump_hex(buffer, p->tot_len);
- #endif
- if (p != NULL)
- {
- for (q = p; q != NULL; q = q->next)
- {
- pdata = q->payload;
- rt_memcpy(pdata,buffer,q->len);
- pdata += (q->len);
- buffer += (q->len);
- }
- }
- else
- {
- LOG_E("p=null\r\n");
- }
- return p;
- }
- /* interrupt service routine */
- void ETH_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
- void ETH_IRQHandler(void)
- {
- GET_INT_SP();
- /* enter interrupt */
- rt_err_t result;
- rt_interrupt_enter();
- if(ETH->DMASRÐ_DMA_IT_R)
- {
- ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
- frame = ETH_RxPkt_ChainMode();
- result = eth_device_ready(&(ch32v30x_eth_device.parent));
- if (result != RT_EOK)
- rt_kprintf("RxCpltCallback err = %d\r\n", result);
- }
- if(ETH->DMASRÐ_DMA_IT_T)
- {
- ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
- }
- ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
- /* leave interrupt */
- rt_interrupt_leave();
- FREE_INT_SP();
- }
- /* Register the EMAC device */
- static int rt_hw_ch32_eth_init(void)
- {
- rt_err_t state = RT_EOK;
- /* 84-c2-e4 WCH. */
- ch32v30x_eth_device.dev_addr[0] = 0x84;
- ch32v30x_eth_device.dev_addr[1] = 0xc2;
- ch32v30x_eth_device.dev_addr[2] = 0xe4;
- /* generate MAC (only for test). */
- ch32v30x_eth_device.dev_addr[3] = 0x1;
- ch32v30x_eth_device.dev_addr[4] = 0x2;
- ch32v30x_eth_device.dev_addr[5] = 0x3;
- ch32v30x_eth_device.parent.parent.init = rt_ch32_eth_init;
- ch32v30x_eth_device.parent.parent.open = rt_ch32_eth_open;
- ch32v30x_eth_device.parent.parent.close = rt_ch32_eth_close;
- ch32v30x_eth_device.parent.parent.read = rt_ch32_eth_read;
- ch32v30x_eth_device.parent.parent.write = rt_ch32_eth_write;
- ch32v30x_eth_device.parent.parent.control = rt_ch32_eth_control;
- ch32v30x_eth_device.parent.parent.user_data = RT_NULL;
- ch32v30x_eth_device.parent.eth_rx = rt_ch32_eth_rx;
- ch32v30x_eth_device.parent.eth_tx = rt_ch32_eth_tx;
- /* register eth device */
- state = eth_device_init(&(ch32v30x_eth_device.parent), "e0");
- if (RT_EOK == state)
- {
- LOG_D("emac device init success");
- }
- else
- {
- LOG_E("emac device init faild: %d\r\n", state);
- state = -RT_ERROR;
- }
- return state;
- }
- INIT_DEVICE_EXPORT(rt_hw_ch32_eth_init);
- #endif /* BSP_USING_ETH */
|