123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-05-19 Joe first version
- */
- #include "at32f4xx_eth.h"
- #include "board.h"
- #include <netif/ethernetif.h>
- #include "lwipopts.h"
- #include "drv_eth.h"
- #include <drv_log.h>
- /* EMAC Interface */
- #define PHY_ADDRESS 0x00 /* Relative to AT32F407-EVAL Board */
- //#define MII_MODE /* MII mode for AT32F407-EVAL Board (MB784) (check jumpers setting) */
- #define RMII_MODE /* RMII mode for AT32F407-EVAL Board (MB784) (check jumpers setting) */
- //#define CRYSTAL_ON_PHY
- #define MII_RX_REMAP 1
- /* debug option */
- //#define ETH_RX_DUMP
- //#define ETH_TX_DUMP
- //#define DRV_DEBUG
- #define LOG_TAG "drv.emac"
- #define ETH_RXBUFNB 4
- #define ETH_TXBUFNB 2
- #define LINK_THREAD_STACK_SIZE 256
- #define LINK_THREAD_PREORITY 21
- extern ETH_DMADESCTypeDef *DMATxDescToSet;
- extern ETH_DMADESCTypeDef *DMARxDescToGet;
- extern ETH_DMADESCTypeDef *DMAPTPTxDescToSet;
- extern ETH_DMADESCTypeDef *DMAPTPRxDescToGet;
- 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];
- static struct rt_thread eth_link_thread;
- static rt_uint8_t eth_link_stack[LINK_THREAD_STACK_SIZE];
- #define MAX_ADDR_LEN 6
- /* Gloable variables ---------------------------------------------------------*/
- void static Reset_Phy(void);
- void NVIC_Configuration(void);
- void GPIO_Configuration(void);
- struct rt_at32_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]; /* Ethernet Rx & Tx DMA Descriptors */
- static uint8_t Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE], Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE]; /* Ethernet buffers */
- //static ETH_HandleTypeDef EthHandle;
- static struct rt_at32_eth at32_eth_device;
- static struct rt_semaphore tx_wait;
- static rt_bool_t tx_is_waiting = RT_FALSE;
- #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("\n");
- }
- }
- #endif
- /**
- * @brief reset the phy
- * @param None
- * @retval None
- */
- void static Reset_Phy(void)
- {
- GPIO_InitType GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- GPIO_ResetBits(GPIOC, GPIO_Pins_8);
- rt_thread_mdelay(2);
- GPIO_SetBits(GPIOC, GPIO_Pins_8);
- rt_thread_mdelay(2000);
- }
- /**
- * @brief Configure NVIC for ISR
- * @param None
- * @retval None
- */
- void NVIC_Configuration(void)
- {
- NVIC_InitType NVIC_InitStructure;
- /* Set the Vector Table base location at 0x08000000 */
- NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
- /* 2 bit for pre-emption priority, 2 bits for subpriority */
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- /* Enable the Ethernet global Interrupt */
- NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- /**
- * @brief Configure GPIO for ethernet
- * @param None
- * @retval None
- */
- void GPIO_Configuration(void)
- {
- GPIO_InitType GPIO_InitStructure;
- #if MII_RX_REMAP
- GPIO_PinsRemapConfig(GPIO_Remap_ETH, ENABLE);
- #endif
- RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOA | RCC_APB2PERIPH_GPIOB | RCC_APB2PERIPH_GPIOC |
- RCC_APB2PERIPH_GPIOD | RCC_APB2PERIPH_GPIOE | RCC_APB2PERIPH_AFIO, ENABLE);
- /* ETHERNET pins configuration */
- /* AF Output Push Pull:
- ETH_MII_MDIO / ETH_RMII_MDIO: PA2
- ETH_MII_MDC / ETH_RMII_MDC: PC1
- */
- /* Configure PA2 as alternate function push-pull MDIO*/
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_2;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- /*PC1-->MDC*/
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_1;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- /*MII Mode GPIO configuration*/
- #ifdef MII_MODE
- /**********************MII Tx Pin Define****************************/
- /*
- ETH_MII_TX0-->PB12 AF-PP
- ETH_MII_TX1-->PB13 AF-PP
- ETH_MII_TX2-->PC2 AF-PP
- ETH_MII_TX3-->PB8 AF-PP
- ETH_MII_TX_EN-->PB11 AF-PP
- ETH_MII_TX_CLK-->PC3
- */
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8 | GPIO_Pins_11 | GPIO_Pins_12 | GPIO_Pins_13;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_2 | GPIO_Pins_3;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- /**********************MII Rx Pin Define****************************/
- #if MII_RX_REMAP /*IO PIN remaped*/
- /*
- ETH_MII_RX_DV-->PD8
- ETH_MII_RXD0-->PD9
- ETH_MII_RXD1-->PD10
- ETH_MII_RXD2-->PD11
- ETH_MII_RXD3-->PD12
- ETH_MII_RXCLK-->PA1
- ETH_MII_CRS-->PA0
- ETH_MII_COL-->PA3
- ETH_MII_RX_ER-->PB10
- */
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8 | GPIO_Pins_9 | GPIO_Pins_10 | GPIO_Pins_11 | GPIO_Pins_12;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_0 | GPIO_Pins_1 | GPIO_Pins_3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- #else
- /*
- ETH_MII_RX_DV-->PA7
- ETH_MII_RXD0-->PC4
- ETH_MII_RXD1-->PC5
- ETH_MII_RXD2-->PB0
- ETH_MII_RXD3-->PB1
- ETH_MII_RXCLK-->PA1
- ETH_MII_CRS-->PA0
- ETH_MII_COL-->PA3
- ETH_MII_RX_ER-->PB10
- */
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_0 | GPIO_Pins_1 | GPIO_Pins_3 | GPIO_Pins_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_4 | GPIO_Pins_5;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_0 | GPIO_Pins_1 | GPIO_Pins_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- #endif //End MII RX REMAP
- #endif //End MII mode
- #ifdef RMII_MODE
- /**********************RMII Tx Pin Define****************************/
- /*
- ETH_RMII_TX0-->PB12 AF-PP
- ETH_RMII_TX1-->PB13 AF-PP
- ETH_RMII_TX_EN-->PB11 AF-PP
- */
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_11 | GPIO_Pins_12 | GPIO_Pins_13;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- /**********************RMII Rx Pin Define****************************/
- #if MII_RX_REMAP /*IO PIN remaped*/
- /*
- ETH_RMII_RX_DV-->PD8
- ETH_RMII_RXD0-->PD9
- ETH_RMII_RXD1-->PD10
- ETH_RMII_REF_CLK-->PA1
- */
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8 | GPIO_Pins_9 | GPIO_Pins_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- #else
- /*
- ETH_RMII_RX_DV-->PA7
- ETH_RMII_RXD0-->PC4
- ETH_RMII_RXD1-->PC5
- ETH_RMII_REF_CLK-->PA1
- */
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_1 | GPIO_Pins_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_4 | GPIO_Pins_5;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- #endif //End RMII RX REMAP
- #endif //End RMII mode
- /* ADC Channel4 config --------------------------------------------------------*/
- /* Configure PA4(ADC Channel4) as analog input -------------------------*/
- #ifdef ADC_NECESSARY
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_4;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_ANALOG;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- #endif
- /* MCO pin configuration------------------------------------------------- */
- /* Configure MCO (PA8) as alternate function push-pull */
- #ifndef CRYSTAL_ON_PHY
- GPIO_InitStructure.GPIO_Pins = GPIO_Pins_8;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- #endif
- }
- /* EMAC initialization function */
- static rt_err_t rt_at32_eth_init(rt_device_t dev)
- {
- ETH_InitType ETH_InitStructure;
- RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_ETHMAC | RCC_AHBPERIPH_ETHMACTX |
- RCC_AHBPERIPH_ETHMACRX, ENABLE);
- /* MII/RMII Media interface selection ------------------------------------------*/
- #ifdef MII_MODE /* Mode MII with AT32F407-EVAL */
- GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_MII);
- /* Get 25MHz from system clock 200MHz on PA8 pin (MCO) */
- #ifndef CRYSTAL_ON_PHY
- RCC_CLKOUTConfig(RCC_CLKOUT_SYSCLK, RCC_MCOPRE_8);
- #endif
- #elif defined RMII_MODE /* Mode RMII with AT32F407-EVAL */
- GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII);
- #ifndef CRYSTAL_ON_PHY
- RCC_CLKOUTConfig(RCC_CLKOUT_SYSCLK, RCC_MCOPRE_8); /*25M to RMII Mode*/
- #endif
- #endif
- /*Reset phy*/
- Reset_Phy();
- /* Reset ETHERNET on AHB Bus */
- ETH_DeInit();
- /* Software reset */
- ETH_SoftwareReset();
- /* Wait for software reset */
- while (ETH_GetSoftwareResetStatus() == SET);
- /* ETHERNET Configuration ------------------------------------------------------*/
- /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
- ETH_StructInit(Ð_InitStructure);
- /* Fill ETH_InitStructure parametrs */
- /*------------------------ MAC -----------------------------------*/
- ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;//ETH_AutoNegotiation_Enable ;
- ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
- ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Enable;
- ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
- ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
- ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
- ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
- ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;//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_DropTCPIPChecksumErrorFrame_Enable;
- ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
- ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
- ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
- ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
- ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
- 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, check error */
- if(ETH_Init(Ð_InitStructure, PHY_ADDRESS) == ((uint32_t)0)) {
- return RT_ERROR;
- }
- /* Enable DMA Receive interrupt (need to enable in this case Normal interrupt) */
- ETH_DMAITConfig(ETH_DMA_INT_NIS | ETH_DMA_INT_R, ENABLE);
- /* Initialize Tx Descriptors list: Chain Mode */
- ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
- /* Initialize Rx Descriptors list: Chain Mode */
- ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
- /* MAC address configuration */
- ETH_MACAddressConfig(ETH_MAC_Address0, (u8*)&at32_eth_device.dev_addr[0]);
- /* Enable ETH transmition and recetion */
- ETH_Start();
- return RT_EOK;
- }
- static rt_err_t rt_at32_eth_open(rt_device_t dev, rt_uint16_t oflag)
- {
- LOG_D("emac open");
- return RT_EOK;
- }
- static rt_err_t rt_at32_eth_close(rt_device_t dev)
- {
- LOG_D("emac close");
- return RT_EOK;
- }
- static rt_size_t rt_at32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
- {
- LOG_D("emac read");
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- static rt_size_t rt_at32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
- {
- LOG_D("emac write");
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- static rt_err_t rt_at32_eth_control(rt_device_t dev, int cmd, void *args)
- {
- switch (cmd)
- {
- case NIOCTL_GADDR:
- /* get mac address */
- if (args) rt_memcpy(args, at32_eth_device.dev_addr, 6);
- else return -RT_ERROR;
- break;
- default :
- break;
- }
- return RT_EOK;
- }
- /* ethernet device interface */
- /* transmit data*/
- rt_err_t rt_at32_eth_tx(rt_device_t dev, struct pbuf *p)
- {
- struct pbuf* q;
- rt_uint32_t offset;
- /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
- while ((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET)
- {
- rt_err_t result;
- rt_uint32_t level;
- level = rt_hw_interrupt_disable();
- tx_is_waiting = RT_TRUE;
- rt_hw_interrupt_enable(level);
- /* it's own bit set, wait it */
- result = rt_sem_take(&tx_wait, RT_WAITING_FOREVER);
- if (result == RT_EOK) break;
- if (result == -RT_ERROR) return -RT_ERROR;
- }
- offset = 0;
- for (q = p; q != NULL; q = q->next)
- {
- uint8_t *to;
- /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */
- to = (uint8_t*)((DMATxDescToSet->Buffer1Addr) + offset);
- memcpy(to, q->payload, q->len);
- offset += q->len;
- }
- #ifdef ETH_TX_DUMP
- {
- rt_uint32_t i;
- rt_uint8_t *ptr = (rt_uint8_t*)(DMATxDescToSet->Buffer1Addr);
- AT32_ETH_PRINTF("tx_dump, len:%d\r\n", p->tot_len);
- for(i=0; i<p->tot_len; i++)
- {
- AT32_ETH_PRINTF("%02x ",*ptr);
- ptr++;
- if(((i+1)%8) == 0)
- {
- AT32_ETH_PRINTF(" ");
- }
- if(((i+1)%16) == 0)
- {
- AT32_ETH_PRINTF("\r\n");
- }
- }
- AT32_ETH_PRINTF("\r\ndump done!\r\n");
- }
- #endif
- /* Setting the Frame Length: bits[12:0] */
- DMATxDescToSet->ControlBufferSize = (p->tot_len & ETH_DMATxDesc_TBS1);
- /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
- DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS;
- /* Enable TX Completion Interrupt */
- DMATxDescToSet->Status |= ETH_DMATxDesc_IC;
- #ifdef CHECKSUM_BY_HARDWARE
- DMATxDescToSet->Status |= ETH_DMATxDesc_ChecksumTCPUDPICMPFull;
- /* clean ICMP checksum STM32F need */
- {
- struct eth_hdr *ethhdr = (struct eth_hdr *)(DMATxDescToSet->Buffer1Addr);
- /* is IP ? */
- if( ethhdr->type == htons(ETHTYPE_IP) )
- {
- struct ip_hdr *iphdr = (struct ip_hdr *)(DMATxDescToSet->Buffer1Addr + SIZEOF_ETH_HDR);
- /* is ICMP ? */
- if( IPH_PROTO(iphdr) == IP_PROTO_ICMP )
- {
- struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)(DMATxDescToSet->Buffer1Addr + SIZEOF_ETH_HDR + sizeof(struct ip_hdr) );
- iecho->chksum = 0;
- }
- }
- }
- #endif
- /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
- DMATxDescToSet->Status |= ETH_DMATxDesc_OWN;
- /* When Tx Buffer unavailable flag is set: clear it and resume transmission */
- if ((ETH->DMASTS & ETH_DMA_FLAG_TBU) != (uint32_t)RESET)
- {
- /* Clear TBUS ETHERNET DMA flag */
- ETH->DMASTS = ETH_DMA_FLAG_TBU;
- /* Transmit Poll Demand to resume DMA transmission*/
- ETH->DMATPD = 0;
- }
- /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */
- /* Chained Mode */
- /* Selects the next DMA Tx descriptor list for next buffer to send */
- DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr);
- /* Return SUCCESS */
- return RT_EOK;
- }
- /* receive data*/
- struct pbuf *rt_at32_eth_rx(rt_device_t dev)
- {
- struct pbuf* p;
- rt_uint32_t offset = 0, framelength = 0;
- /* init p pointer */
- p = RT_NULL;
- /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
- if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) != (uint32_t)RESET))
- return p;
- if (((DMARxDescToGet->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) &&
- ((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (uint32_t)RESET) &&
- ((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (uint32_t)RESET))
- {
- /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
- framelength = ((DMARxDescToGet->Status & ETH_DMARxDesc_FL) >> 16) - 4;
- /* allocate buffer */
- p = pbuf_alloc(PBUF_LINK, framelength, PBUF_RAM);
- if (p != RT_NULL)
- {
- struct pbuf* q;
- for (q = p; q != RT_NULL; q= q->next)
- {
- /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */
- memcpy(q->payload, (uint8_t *)((DMARxDescToGet->Buffer1Addr) + offset), q->len);
- offset += q->len;
- }
- #ifdef ETH_RX_DUMP
- {
- rt_uint32_t i;
- rt_uint8_t *ptr = (rt_uint8_t*)(DMARxDescToGet->Buffer1Addr);
- AT32_ETH_PRINTF("rx_dump, len:%d\r\n", p->tot_len);
- for(i=0; i<p->tot_len; i++)
- {
- AT32_ETH_PRINTF("%02x ", *ptr);
- ptr++;
- if(((i+1)%8) == 0)
- {
- AT32_ETH_PRINTF(" ");
- }
- if(((i+1)%16) == 0)
- {
- AT32_ETH_PRINTF("\r\n");
- }
- }
- AT32_ETH_PRINTF("\r\ndump done!\r\n");
- }
- #endif
- }
- }
- /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */
- DMARxDescToGet->Status = ETH_DMARxDesc_OWN;
- /* When Rx Buffer unavailable flag is set: clear it and resume reception */
- if ((ETH->DMASTS & ETH_DMA_FLAG_RBU) != (uint32_t)RESET)
- {
- /* Clear RBUS ETHERNET DMA flag */
- ETH->DMASTS = ETH_DMA_FLAG_RBU;
- /* Resume DMA reception */
- ETH->DMARPD = 0;
- }
- /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */
- /* Chained Mode */
- if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RCH) != (uint32_t)RESET)
- {
- /* Selects the next DMA Rx descriptor list for next buffer to read */
- DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr);
- }
- else /* Ring Mode */
- {
- if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RER) != (uint32_t)RESET)
- {
- /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */
- DMARxDescToGet = (ETH_DMADESCTypeDef*) (ETH->DMARDLADDR);
- }
- else
- {
- /* Selects the next DMA Rx descriptor list for next buffer to read */
- DMARxDescToGet = (ETH_DMADESCTypeDef*) ((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABM & 0x0000007C) >> 2));
- }
- }
- return p;
- }
- static void eth_link_thread_entry(void *paramter)
- {
- uint8_t linked_down = 1;
- struct netif *pnetif = at32_eth_device.parent.netif;
- while(1){
- if((ETH_ReadPHYRegister(PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status) && (linked_down == 1))
- {
- /* link up */
- linked_down = 0;
- #ifndef RT_LWIP_DHCP
- pnetif->ip_addr = inet_addr(RT_LWIP_IPADDR);
- pnetif->gw = inet_addr(RT_LWIP_GWADDR);
- pnetif->netmask = inet_addr(RT_LWIP_MSKADDR);
- #else
- IP4_ADDR(&(pnetif->ip_addr), 0, 0, 0, 0);
- IP4_ADDR(&(pnetif->netmask), 0, 0, 0, 0);
- IP4_ADDR(&(pnetif->gw), 0, 0, 0, 0);
- #endif
- eth_device_linkchange(&(at32_eth_device.parent), RT_TRUE);
- }else if(!(ETH_ReadPHYRegister(PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status) && (linked_down == 0))
- {
- /* link down */
- linked_down = 1;
- eth_device_linkchange(&(at32_eth_device.parent), RT_FALSE);
- }
- rt_thread_mdelay(500);
- }
- }
- /* interrupt service routine */
- void ETH_IRQHandler(void)
- {
- rt_uint32_t status;
- status = ETH->DMASTS;
- /* Clear received IT */
- if ((status & ETH_DMA_INT_NIS) != (u32)RESET)
- ETH->DMASTS = (u32)ETH_DMA_INT_NIS;
- if ((status & ETH_DMA_INT_AIS) != (u32)RESET)
- ETH->DMASTS = (u32)ETH_DMA_INT_AIS;
- if ((status & ETH_DMA_INT_RO) != (u32)RESET)
- ETH->DMASTS = (u32)ETH_DMA_INT_RO;
- if ((status & ETH_DMA_INT_RBU) != (u32)RESET)
- ETH->DMASTS = (u32)ETH_DMA_INT_RBU;
- if (ETH_GetDMAITStatus(ETH_DMA_INT_R) == SET) /* packet receiption */
- {
- /* a frame has been received */
- eth_device_ready(&(at32_eth_device.parent));
- ETH_DMAClearITPendingBit(ETH_DMA_INT_R);
- }
- if (ETH_GetDMAITStatus(ETH_DMA_INT_T) == SET) /* packet transmission */
- {
- if (tx_is_waiting == RT_TRUE)
- {
- tx_is_waiting = RT_FALSE;
- rt_sem_release(&tx_wait);
- }
- ETH_DMAClearITPendingBit(ETH_DMA_INT_T);
- }
- }
- enum {
- PHY_LINK = (1 << 0),
- PHY_100M = (1 << 1),
- PHY_FULL_DUPLEX = (1 << 2),
- };
- /* Register the EMAC device */
- static int rt_hw_at32_eth_init(void)
- {
- rt_err_t state = RT_EOK;
- Reset_Phy();
- GPIO_Configuration();
- NVIC_Configuration();
- at32_eth_device.dev_addr[0] = 0x00;
- at32_eth_device.dev_addr[1] = 0x80;
- at32_eth_device.dev_addr[2] = 0xE1;
- at32_eth_device.dev_addr[3] = 0x94;
- at32_eth_device.dev_addr[4] = 0x87;
- at32_eth_device.dev_addr[5] = 0x55;
- at32_eth_device.parent.parent.init = rt_at32_eth_init;
- at32_eth_device.parent.parent.open = rt_at32_eth_open;
- at32_eth_device.parent.parent.close = rt_at32_eth_close;
- at32_eth_device.parent.parent.read = rt_at32_eth_read;
- at32_eth_device.parent.parent.write = rt_at32_eth_write;
- at32_eth_device.parent.parent.control = rt_at32_eth_control;
- at32_eth_device.parent.parent.user_data = RT_NULL;
- at32_eth_device.parent.eth_rx = rt_at32_eth_rx;
- at32_eth_device.parent.eth_tx = rt_at32_eth_tx;
- /* register eth device */
- state = eth_device_init(&(at32_eth_device.parent), "e0");
- if (RT_EOK == state)
- {
- LOG_D("emac device init success");
- state = rt_thread_init(ð_link_thread, "eth_link_detect", eth_link_thread_entry, RT_NULL,
- ð_link_stack[0], LINK_THREAD_STACK_SIZE, LINK_THREAD_PREORITY, 20);
- if (state == RT_EOK)
- {
- rt_thread_startup(ð_link_thread);
- }
- }
- else
- {
- LOG_E("emac device init faild: %d", state);
- state = -RT_ERROR;
- }
- /* start phy monitor */
- return state;
- }
- INIT_DEVICE_EXPORT(rt_hw_at32_eth_init);
|