From 8f2eb1f7c98718e50d2b54c8e63f6e70b71f5a96 Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 22 Mar 2024 04:52:07 -0400 Subject: [PATCH] Added Infineon XMC44/47 examples --- mongoose.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++ mongoose.h | 81 ++++++++++++------ src/drivers/xmc.c | 208 +++++++++++++++++++++++++++++++++++++++++++++ src/drivers/xmc.h | 34 ++++++++ src/net_builtin.h | 1 + 5 files changed, 509 insertions(+), 27 deletions(-) create mode 100644 src/drivers/xmc.c create mode 100644 src/drivers/xmc.h diff --git a/mongoose.c b/mongoose.c index 25a9e0f6026..13f2ce2da95 100644 --- a/mongoose.c +++ b/mongoose.c @@ -16054,3 +16054,215 @@ static bool w5500_up(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver mg_tcpip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx, w5500_up}; #endif + +#ifdef MG_ENABLE_LINES +#line 1 "src/drivers/xmc.c" +#endif + + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC + +#ifdef XMC4400_F100x512 +#include +#else +#ifdef XMC4700_F144x2048 +#include +#endif +#endif + +#ifndef ETH0 +#define ETH0 ((volatile ETH_GLOBAL_TypeDef*) 0x5000C000UL) +#endif + +#define ETH_PKT_SIZE 1536 // Max frame size +#define ETH_DESC_CNT 4 // Descriptors count +#define ETH_DS 4 // Descriptor size (words) + +static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; +static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; +static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors +static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors +static uint8_t s_txno; // Current TX descriptor +static uint8_t s_rxno; // Current RX descriptor + +static struct mg_tcpip_if *s_ifp; // MIP interface +enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 }; + +static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { + ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk) | + ETH_GMII_ADDRESS_MB_Msk | + ((uint32_t)addr << ETH_GMII_ADDRESS_PA_Pos) | + ((uint32_t)reg << ETH_GMII_ADDRESS_MR_Pos); + while ((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) (void) 0; + return (uint16_t)(ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk); +} + +static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { + ETH0->GMII_DATA = val; + ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk) | + ETH_GMII_ADDRESS_MB_Msk | + ETH_GMII_ADDRESS_MW_Msk | + ((uint32_t)addr << ETH_GMII_ADDRESS_PA_Pos) | + ((uint32_t)reg << ETH_GMII_ADDRESS_MR_Pos); + while ((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) (void) 0; +} + +static uint32_t get_clock_rate(struct mg_tcpip_driver_xmc_data *d) { + // assume ETH clock is 60MHz + // then according to 13.2.8.1, we need to set value 3 + (void) d; + return 3; +} + +static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) { + struct mg_tcpip_driver_xmc_data *d = + (struct mg_tcpip_driver_xmc_data *) ifp->driver_data; + s_ifp = ifp; + + // reset MAC + ETH0->BUS_MODE |= 1; + while (ETH0->BUS_MODE & 1) (void) 0; + + // set clock rate + ETH0->GMII_ADDRESS = get_clock_rate(d) << ETH_GMII_ADDRESS_CR_Pos; + + // init phy + eth_write_phy(MG_PHY_ADDR, MG_PHYREG_BCR, 0x8000); // reset + uint8_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR); + while ((bcr & 0x8000) != 0) { + bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR); + } + + // auto-negotiation, 100M, full-duplex + eth_write_phy(MG_PHY_ADDR, MG_PHYREG_BCR, 0x3100); + + ETH0->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_DO_Msk | ETH_MAC_CONFIGURATION_DM_Msk | + ETH_MAC_CONFIGURATION_FES_Msk | ETH_MAC_CONFIGURATION_TC_Msk; + + // set the MAC address + ETH0->MAC_ADDRESS0_HIGH = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); + ETH0->MAC_ADDRESS0_LOW = + MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); + + // Configure the receive filter + ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk | ETH_MAC_FRAME_FILTER_HMC_Msk; + // Disable flow control + ETH0->FLOW_CONTROL = 0; + // Enable store and forward mode + ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk; + + // Configure DMA bus mode + ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk | + (32 << ETH_BUS_MODE_RPBL_Pos) | (32 << ETH_BUS_MODE_PBL_Pos); + + // init RX descriptors + for (int i = 0; i < ETH_DESC_CNT; i++) { + s_rxdesc[i][0] = MG_BIT(31); // OWN descriptor + //s_rxdesc[i][1] = MG_BIT(24) | ETH_PKT_SIZE; // chained descriptors + s_rxdesc[i][1] = MG_BIT(14) | ETH_PKT_SIZE; + s_rxdesc[i][2] = (uint32_t) s_rxbuf[i]; + if (i == ETH_DESC_CNT - 1) { + s_rxdesc[i][3] = (uint32_t) &s_rxdesc[0][0]; + } else { + s_rxdesc[i][3] = (uint32_t) &s_rxdesc[i + 1][0]; + } + } + ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_rxdesc[0][0]; + + // init TX descriptors + for (int i = 0; i < ETH_DESC_CNT; i++) { + s_txdesc[i][0] = MG_BIT(30) | MG_BIT(20); + s_txdesc[i][2] = (uint32_t) s_txbuf[i]; + if (i == ETH_DESC_CNT - 1) { + s_txdesc[i][3] = (uint32_t) &s_txdesc[0][0]; + } else { + s_txdesc[i][3] = (uint32_t) &s_txdesc[i + 1][0]; + } + } + ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_txdesc[0][0]; + + // Clear interrupts + ETH0->STATUS = 0xFFFFFFFF; + + // Disable MAC interrupts + ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF; + ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; + ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; + ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk; + + //Enable interrupts + ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk | + ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk; + + // Enable MAC transmission and reception + ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk; + // Enable DMA transmission and reception + ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk; + + NVIC_EnableIRQ(ETH0_0_IRQn); + return true; +} + +static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len, + struct mg_tcpip_if *ifp) { + if (len > sizeof(s_txbuf[s_txno])) { + MG_ERROR(("Frame too big, %ld", (long) len)); + len = 0; // Frame is too big + } else if ((s_txdesc[s_txno][0] & MG_BIT(31))) { + ifp->nerr++; + MG_ERROR(("No free descriptors")); + len = 0; // All descriptors are busy, fail + } else { + memcpy(s_txbuf[s_txno], buf, len); + s_txdesc[s_txno][1] = len; + s_txdesc[s_txno][0] = MG_BIT(29) /* Last frame */ | + MG_BIT(28) /* First frame */ | MG_BIT(30) /* Interrupt on send */ | + MG_BIT(20) /* Chained descriptors */; + s_txdesc[s_txno][0] |= MG_BIT(31); // OWN bit: handle control to DMA + if (++s_txno >= ETH_DESC_CNT) s_txno = 0; + } + + // Resume processing + ETH0->STATUS = ETH_STATUS_TU_Msk; + ETH0->TRANSMIT_POLL_DEMAND = 0; + return len; +} + +static bool mg_tcpip_driver_xmc_up(struct mg_tcpip_if *ifp) { + uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR); + bool up = bsr & MG_BIT(2) ? 1 : 0; + (void) ifp; + return up; +} + +void ETH0_IRQHandler(void); +void ETH0_IRQHandler(void) { + uint32_t irq_status = ETH0->STATUS; + if (irq_status & ETH_STATUS_RI_Msk) { + for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { + if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) == 0) { + size_t len = (s_rxdesc[s_rxno][0] & 0x3fff0000) >> 16; + mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); + s_rxdesc[s_rxno][0] = MG_BIT(31); // OWN bit: handle control to DMA + // Resume processing + ETH0->STATUS = ETH_STATUS_RU_Msk | ETH_STATUS_RI_Msk; + ETH0->RECEIVE_POLL_DEMAND = 0; + if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; + } + } + ETH0->STATUS = ETH_STATUS_RI_Msk; + } + + if (irq_status & ETH_STATUS_TI_Msk) { + ETH0->STATUS = ETH_STATUS_TI_Msk; + } + + if (irq_status & ETH_STATUS_NIS_Msk) { + ETH0->STATUS = ETH_STATUS_NIS_Msk; + } +} + +struct mg_tcpip_driver mg_tcpip_driver_xmc = { + mg_tcpip_driver_xmc_init, mg_tcpip_driver_xmc_tx, NULL, + mg_tcpip_driver_xmc_up}; +#endif diff --git a/mongoose.h b/mongoose.h index 6e2ae9abcbd..1d98243f0ad 100644 --- a/mongoose.h +++ b/mongoose.h @@ -254,30 +254,30 @@ static inline int mg_mkdir(const char *path, mode_t mode) { #include int mkdir(const char *, mode_t); #endif - - -#if MG_ARCH == MG_ARCH_RTTHREAD - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MG_IO_SIZE -#define MG_IO_SIZE 1460 -#endif - -#endif // MG_ARCH == MG_ARCH_RTTHREAD + + +#if MG_ARCH == MG_ARCH_RTTHREAD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MG_IO_SIZE +#define MG_IO_SIZE 1460 +#endif + +#endif // MG_ARCH == MG_ARCH_RTTHREAD #if MG_ARCH == MG_ARCH_ARMCC || MG_ARCH == MG_ARCH_CMSIS_RTOS1 || \ @@ -2794,6 +2794,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; extern struct mg_tcpip_driver mg_tcpip_driver_same54; extern struct mg_tcpip_driver mg_tcpip_driver_cmsis; extern struct mg_tcpip_driver mg_tcpip_driver_ra; +extern struct mg_tcpip_driver mg_tcpip_driver_xmc; // Drivers that require SPI, can use this SPI abstraction struct mg_tcpip_spi { @@ -3081,10 +3082,36 @@ struct mg_tcpip_driver_tm4c_data { #endif -#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5500) && MG_ENABLE_DRIVER_W5500 +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC -#undef MG_ENABLE_TCPIP_DRIVER_INIT -#define MG_ENABLE_TCPIP_DRIVER_INIT 0 +struct mg_tcpip_driver_xmc_data { + int mdc_cr; + uint8_t phy_addr; +}; + +#ifndef MG_TCPIP_PHY_ADDR +#define MG_TCPIP_PHY_ADDR 0 +#endif + +#ifndef MG_DRIVER_MDC_CR +#define MG_DRIVER_MDC_CR 4 +#endif + +#define MG_TCPIP_DRIVER_INIT(mgr) \ + do { \ + static struct mg_tcpip_driver_xmc_data driver_data_; \ + static struct mg_tcpip_if mif_; \ + driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \ + driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \ + mif_.ip = MG_TCPIP_IP; \ + mif_.mask = MG_TCPIP_MASK; \ + mif_.gw = MG_TCPIP_GW; \ + mif_.driver = &mg_tcpip_driver_xmc; \ + mif_.driver_data = &driver_data_; \ + MG_SET_MAC_ADDRESS(mif_.mac); \ + mg_tcpip_init(mgr, &mif_); \ + MG_INFO(("Driver: xmc, MAC: %M", mg_print_mac, mif_.mac)); \ + } while (0) #endif diff --git a/src/drivers/xmc.c b/src/drivers/xmc.c new file mode 100644 index 00000000000..5b7390d7d3a --- /dev/null +++ b/src/drivers/xmc.c @@ -0,0 +1,208 @@ +#include "net_builtin.h" + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC + +#ifdef XMC4400_F100x512 +#include +#else +#ifdef XMC4700_F144x2048 +#include +#endif +#endif + +#ifndef ETH0 +#define ETH0 ((volatile ETH_GLOBAL_TypeDef*) 0x5000C000UL) +#endif + +#define ETH_PKT_SIZE 1536 // Max frame size +#define ETH_DESC_CNT 4 // Descriptors count +#define ETH_DS 4 // Descriptor size (words) + +static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; +static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; +static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors +static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors +static uint8_t s_txno; // Current TX descriptor +static uint8_t s_rxno; // Current RX descriptor + +static struct mg_tcpip_if *s_ifp; // MIP interface +enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 }; + +static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { + ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk) | + ETH_GMII_ADDRESS_MB_Msk | + ((uint32_t)addr << ETH_GMII_ADDRESS_PA_Pos) | + ((uint32_t)reg << ETH_GMII_ADDRESS_MR_Pos); + while ((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) (void) 0; + return (uint16_t)(ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk); +} + +static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { + ETH0->GMII_DATA = val; + ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk) | + ETH_GMII_ADDRESS_MB_Msk | + ETH_GMII_ADDRESS_MW_Msk | + ((uint32_t)addr << ETH_GMII_ADDRESS_PA_Pos) | + ((uint32_t)reg << ETH_GMII_ADDRESS_MR_Pos); + while ((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0) (void) 0; +} + +static uint32_t get_clock_rate(struct mg_tcpip_driver_xmc_data *d) { + // assume ETH clock is 60MHz + // then according to 13.2.8.1, we need to set value 3 + (void) d; + return 3; +} + +static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) { + struct mg_tcpip_driver_xmc_data *d = + (struct mg_tcpip_driver_xmc_data *) ifp->driver_data; + s_ifp = ifp; + + // reset MAC + ETH0->BUS_MODE |= 1; + while (ETH0->BUS_MODE & 1) (void) 0; + + // set clock rate + ETH0->GMII_ADDRESS = get_clock_rate(d) << ETH_GMII_ADDRESS_CR_Pos; + + // init phy + eth_write_phy(MG_PHY_ADDR, MG_PHYREG_BCR, 0x8000); // reset + uint8_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR); + while ((bcr & 0x8000) != 0) { + bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR); + } + + // auto-negotiation, 100M, full-duplex + eth_write_phy(MG_PHY_ADDR, MG_PHYREG_BCR, 0x3100); + + ETH0->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_DO_Msk | ETH_MAC_CONFIGURATION_DM_Msk | + ETH_MAC_CONFIGURATION_FES_Msk | ETH_MAC_CONFIGURATION_TC_Msk; + + // set the MAC address + ETH0->MAC_ADDRESS0_HIGH = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); + ETH0->MAC_ADDRESS0_LOW = + MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); + + // Configure the receive filter + ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk | ETH_MAC_FRAME_FILTER_HMC_Msk; + // Disable flow control + ETH0->FLOW_CONTROL = 0; + // Enable store and forward mode + ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk; + + // Configure DMA bus mode + ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk | + (32 << ETH_BUS_MODE_RPBL_Pos) | (32 << ETH_BUS_MODE_PBL_Pos); + + // init RX descriptors + for (int i = 0; i < ETH_DESC_CNT; i++) { + s_rxdesc[i][0] = MG_BIT(31); // OWN descriptor + //s_rxdesc[i][1] = MG_BIT(24) | ETH_PKT_SIZE; // chained descriptors + s_rxdesc[i][1] = MG_BIT(14) | ETH_PKT_SIZE; + s_rxdesc[i][2] = (uint32_t) s_rxbuf[i]; + if (i == ETH_DESC_CNT - 1) { + s_rxdesc[i][3] = (uint32_t) &s_rxdesc[0][0]; + } else { + s_rxdesc[i][3] = (uint32_t) &s_rxdesc[i + 1][0]; + } + } + ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_rxdesc[0][0]; + + // init TX descriptors + for (int i = 0; i < ETH_DESC_CNT; i++) { + s_txdesc[i][0] = MG_BIT(30) | MG_BIT(20); + s_txdesc[i][2] = (uint32_t) s_txbuf[i]; + if (i == ETH_DESC_CNT - 1) { + s_txdesc[i][3] = (uint32_t) &s_txdesc[0][0]; + } else { + s_txdesc[i][3] = (uint32_t) &s_txdesc[i + 1][0]; + } + } + ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_txdesc[0][0]; + + // Clear interrupts + ETH0->STATUS = 0xFFFFFFFF; + + // Disable MAC interrupts + ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF; + ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; + ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; + ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk; + + //Enable interrupts + ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk | + ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk; + + // Enable MAC transmission and reception + ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk; + // Enable DMA transmission and reception + ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk; + + NVIC_EnableIRQ(ETH0_0_IRQn); + return true; +} + +static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len, + struct mg_tcpip_if *ifp) { + if (len > sizeof(s_txbuf[s_txno])) { + MG_ERROR(("Frame too big, %ld", (long) len)); + len = 0; // Frame is too big + } else if ((s_txdesc[s_txno][0] & MG_BIT(31))) { + ifp->nerr++; + MG_ERROR(("No free descriptors")); + len = 0; // All descriptors are busy, fail + } else { + memcpy(s_txbuf[s_txno], buf, len); + s_txdesc[s_txno][1] = len; + s_txdesc[s_txno][0] = MG_BIT(29) /* Last frame */ | + MG_BIT(28) /* First frame */ | MG_BIT(30) /* Interrupt on send */ | + MG_BIT(20) /* Chained descriptors */; + s_txdesc[s_txno][0] |= MG_BIT(31); // OWN bit: handle control to DMA + if (++s_txno >= ETH_DESC_CNT) s_txno = 0; + } + + // Resume processing + ETH0->STATUS = ETH_STATUS_TU_Msk; + ETH0->TRANSMIT_POLL_DEMAND = 0; + return len; +} + +static bool mg_tcpip_driver_xmc_up(struct mg_tcpip_if *ifp) { + uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR); + bool up = bsr & MG_BIT(2) ? 1 : 0; + (void) ifp; + return up; +} + +void ETH0_IRQHandler(void); +void ETH0_IRQHandler(void) { + uint32_t irq_status = ETH0->STATUS; + if (irq_status & ETH_STATUS_RI_Msk) { + for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { + if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) == 0) { + size_t len = (s_rxdesc[s_rxno][0] & 0x3fff0000) >> 16; + mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); + s_rxdesc[s_rxno][0] = MG_BIT(31); // OWN bit: handle control to DMA + // Resume processing + ETH0->STATUS = ETH_STATUS_RU_Msk | ETH_STATUS_RI_Msk; + ETH0->RECEIVE_POLL_DEMAND = 0; + if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; + } + } + ETH0->STATUS = ETH_STATUS_RI_Msk; + } + + if (irq_status & ETH_STATUS_TI_Msk) { + ETH0->STATUS = ETH_STATUS_TI_Msk; + } + + if (irq_status & ETH_STATUS_NIS_Msk) { + ETH0->STATUS = ETH_STATUS_NIS_Msk; + } +} + +struct mg_tcpip_driver mg_tcpip_driver_xmc = { + mg_tcpip_driver_xmc_init, mg_tcpip_driver_xmc_tx, NULL, + mg_tcpip_driver_xmc_up}; +#endif diff --git a/src/drivers/xmc.h b/src/drivers/xmc.h new file mode 100644 index 00000000000..ba5a13fa6a8 --- /dev/null +++ b/src/drivers/xmc.h @@ -0,0 +1,34 @@ +#pragma once + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC + +struct mg_tcpip_driver_xmc_data { + int mdc_cr; + uint8_t phy_addr; +}; + +#ifndef MG_TCPIP_PHY_ADDR +#define MG_TCPIP_PHY_ADDR 0 +#endif + +#ifndef MG_DRIVER_MDC_CR +#define MG_DRIVER_MDC_CR 4 +#endif + +#define MG_TCPIP_DRIVER_INIT(mgr) \ + do { \ + static struct mg_tcpip_driver_xmc_data driver_data_; \ + static struct mg_tcpip_if mif_; \ + driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \ + driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \ + mif_.ip = MG_TCPIP_IP; \ + mif_.mask = MG_TCPIP_MASK; \ + mif_.gw = MG_TCPIP_GW; \ + mif_.driver = &mg_tcpip_driver_xmc; \ + mif_.driver_data = &driver_data_; \ + MG_SET_MAC_ADDRESS(mif_.mac); \ + mg_tcpip_init(mgr, &mif_); \ + MG_INFO(("Driver: xmc, MAC: %M", mg_print_mac, mif_.mac)); \ + } while (0) + +#endif diff --git a/src/net_builtin.h b/src/net_builtin.h index b5ef0c938f5..8b0f714b8e8 100644 --- a/src/net_builtin.h +++ b/src/net_builtin.h @@ -60,6 +60,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_imxrt; extern struct mg_tcpip_driver mg_tcpip_driver_same54; extern struct mg_tcpip_driver mg_tcpip_driver_cmsis; extern struct mg_tcpip_driver mg_tcpip_driver_ra; +extern struct mg_tcpip_driver mg_tcpip_driver_xmc; // Drivers that require SPI, can use this SPI abstraction struct mg_tcpip_spi {