From 70fc71c6f706c3abd3690f06996b3f7c937d12ff Mon Sep 17 00:00:00 2001 From: cpq Date: Thu, 3 Aug 2023 09:49:57 +0100 Subject: [PATCH] Changes --- examples/device-dashboard/net.c | 8 +- examples/microchip/same54/Makefile | 2 +- examples/microchip/same54/hal.h | 21 +++-- examples/microchip/same54/main.c | 7 +- mongoose.c | 122 ++++++++++++++++++++--------- src/tcpip/driver_same54.c | 121 +++++++++++++++++++--------- src/tcpip/tcpip.c | 1 + 7 files changed, 194 insertions(+), 88 deletions(-) diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index 10816c5b..455c74af 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -56,14 +56,14 @@ uint64_t mg_now(void) { int ui_event_next(int no, struct ui_event *e) { if (no < 0 || no >= MAX_EVENTS_NO) return 0; - srand(no); + srand((unsigned) no); e->type = (uint8_t) rand() % 4; e->prio = (uint8_t) rand() % 3; e->timestamp = - (unsigned long) (mg_now() - 86400 * 1000 /* one day back */ + + (unsigned long) ((int64_t) mg_now() - 86400 * 1000 /* one day back */ + no * 300 * 1000 /* 5 mins between alerts */ + 1000 * (rand() % 300) /* randomize event time */) / - 1000; + 1000UL; mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, "event#%d", no); return no + 1; @@ -163,7 +163,7 @@ static void handle_stats_get(struct mg_connection *c) { static size_t print_events(void (*out)(char, void *), void *ptr, va_list *ap) { size_t len = 0; struct ui_event ev; - int pageno = va_arg(*ap, unsigned); + int pageno = va_arg(*ap, int); int no = (pageno - 1) * EVENTS_PER_PAGE; int end = no + EVENTS_PER_PAGE; diff --git a/examples/microchip/same54/Makefile b/examples/microchip/same54/Makefile index e9ec2448..9dfe63c6 100644 --- a/examples/microchip/same54/Makefile +++ b/examples/microchip/same54/Makefile @@ -11,7 +11,7 @@ SOURCES = main.c syscalls.c startup.c #SOURCES += cmsis_sam/xc32/ATSAME54P20A/startup_atsame54p20a.c SOURCES += mongoose.c net.c packed_fs.c -CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 -DMG_ENABLE_LINES=1 +CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1 #-DMG_ENABLE_LINES=1 CFLAGS += -DMG_ENABLE_DRIVER_SAME54=1 -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1 $(CFLAGS_EXTRA) VCON_API_KEY=IBrJL5K4arSGMiAXbUKWdG6I2gM diff --git a/examples/microchip/same54/hal.h b/examples/microchip/same54/hal.h index 80a24f7a..226548b8 100644 --- a/examples/microchip/same54/hal.h +++ b/examples/microchip/same54/hal.h @@ -149,13 +149,18 @@ static inline uint32_t rng_read(void) { return TRNG_REGS->TRNG_DATA; } -#define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 39.1 +#define UID_BASE_W0 0x008061FC // Word 0 location of the 128-bit chip ID +#define UID_BASE_W1_3 0x00806010 // Words 1-3 location of the 128-bit chip ID -// Helper macro for MAC generation -#define GENERATE_LOCALLY_ADMINISTERED_MAC() \ - { \ - 2, UUID[0] ^ UUID[1], UUID[2] ^ UUID[3], UUID[4] ^ UUID[5], \ - UUID[6] ^ UUID[7] ^ UUID[8], UUID[9] ^ UUID[10] ^ UUID[11] \ +#define UUID(n) ((n >= 0 && n <= 3) ? \ + (((uint8_t *) UID_BASE_W0)[n]) : \ + (((uint8_t *) UID_BASE_W1_3)[n - 4])) + +#define GENERATE_LOCALLY_ADMINISTERED_MAC() \ + { \ + 2, UUID(0) ^ UUID(1) ^ UUID(2), UUID(3) ^ UUID(4) ^ UUID(5), \ + UUID(6) ^ UUID(7) ^ UUID(8), UUID(9) ^ UUID(10) ^ UUID(11), \ + UUID(12) ^ UUID(13) ^ UUID(14) ^ UUID(15) \ } static inline bool timer_expired(volatile uint64_t *t, uint64_t prd, @@ -194,9 +199,9 @@ static inline void ethernet_init(void) { PORT_REGS->GROUP[bank].PORT_PINCFG[no] |= PORT_PINCFG_PMUXEN_Msk; volatile uint8_t *m = &PORT_REGS->GROUP[bank].PORT_PMUX[no / 2], v = m[0]; if (no & 1) { - m[0] = (uint8_t) (v & ~0xf0) | PORT_PMUX_PMUXO(af[i]); + m[0] = (uint8_t) ((v & ~0xf0) | PORT_PMUX_PMUXO(af[i])); } else { - m[0] = (uint8_t) (v & ~0x0f) | PORT_PMUX_PMUXE(af[i]); + m[0] = (uint8_t) ((v & ~0x0f) | PORT_PMUX_PMUXE(af[i])); } } diff --git a/examples/microchip/same54/main.c b/examples/microchip/same54/main.c index d6d1d9b2..08390285 100644 --- a/examples/microchip/same54/main.c +++ b/examples/microchip/same54/main.c @@ -39,7 +39,8 @@ static void timer_fn(void *arg) { static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "ok\n"); - } + (void) ev_data, (void) fn_data; +} int main(void) { gpio_input(BUTTON_PIN); @@ -55,7 +56,7 @@ int main(void) { // Initialise Mongoose network stack struct mg_tcpip_driver_same54_data driver_data = {.mdc_cr = 5}; - struct mg_tcpip_if mif = {.mac = {2, 3, 4, 5, 6, 7}, + struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC()/*{2, 3, 4, 5, 6, 7}*/, // Uncomment below for static configuration: // .ip = mg_htonl(MG_U32(192, 168, 0, 223)), // .mask = mg_htonl(MG_U32(255, 255, 255, 0)), @@ -72,7 +73,7 @@ int main(void) { MG_INFO(("Initialising application...")); mg_http_listen(&mgr, "http://0.0.0.0", fn, NULL); - //web_init(&mgr); + // web_init(&mgr); MG_INFO(("Starting event loop")); for (;;) { diff --git a/mongoose.c b/mongoose.c index 6f8472e6..9a799837 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7043,8 +7043,8 @@ struct mg_tcpip_driver mg_tcpip_driver_imxrt1020 = { #define ETH_DESC_CNT 4 // Descriptors count #define ETH_DS 2 // Descriptor size (words) -static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); -static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +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 @@ -7053,6 +7053,10 @@ static uint8_t s_rxno; // Current RX descriptor static struct mg_tcpip_if *s_ifp; // MIP interface enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; +#define PHY_BCR_DUPLEX_MODE_Msk BIT(8) +#define PHY_BCR_SPEED_Msk BIT(13) +#define PHY_BSR_LINK_STATUS_Msk BIT(2) + static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation @@ -7071,6 +7075,56 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { } #endif +int get_clock_rate(struct mg_tcpip_driver_same54_data *d) { + if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) { + return d->mdc_cr; + } else { + // get MCLK from GCLK_GENERATOR 0 + uint32_t div = 512; + uint32_t mclk; + if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) { + div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); + if (div == 0) div = 1; + } + switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { + case GCLK_GENCTRL_SRC_XOSC0_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_XOSC1_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_OSCULP32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_XOSC32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_DFLL_Val: + mclk = 48000000UL; /* 48MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL0_Val: + mclk = 200000000UL; /* 200MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL1_Val: + mclk = 200000000UL; /* 200MHz */ + break; + default: + mclk = 200000000UL; /* 200MHz */ + } + + mclk /= div; + uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values + uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers + for (int i = 0; i < 6; i++) { + if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { + return crs[i]; + } + } + + return 5; + } +} + static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver_same54_data *d = (struct mg_tcpip_driver_same54_data *) ifp->driver_data; @@ -7078,56 +7132,45 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk; MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk; - GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(d->mdc_cr); // Set MDC divider + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO - // Init TX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer s_txdesc[i][1] = BIT(31); // OWN bit } s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap - // Init RX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { - s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer - s_rxdesc[i][1] = 0; // Clear status + GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); // DMA recv buf 1536 + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors + s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer + s_rxdesc[i][1] = 0; // Clear status } - s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor + s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - wrap GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know - // Select RMII operation mode - GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; + GMAC_REGS->SA[0].GMAC_SAB = + MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); + GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); - // Configure the receive filter + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk | - GMAC_NCFGR_SPD_Msk | GMAC_NCFGR_FD_Msk; - - // Clear transmit status register + GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk; GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk; - - // Clear receive status register GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk | GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk; - - // First disable all GMAC interrupts - GMAC_REGS->GMAC_IDR = ~0U; - - // Only the desired ones are enabled + GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk | GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk | GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk | GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk; - - // Enable the GMAC to transmit and receive data GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk; - NVIC_EnableIRQ(GMAC_IRQn); return true; @@ -7156,9 +7199,16 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); - // MG_INFO(("BSR: 0x%x", bsr)); - bool up = bsr & BIT(2) ? 1 : 0; - (void) ifp; + bool up = bsr & PHY_BSR_LINK_STATUS_Msk ? 1 : 0; + + // If PHY is ready, update NCFGR accordingly + if (ifp->state == MG_TCPIP_STATE_DOWN && up) { + uint16_t bcr = eth_read_phy(PHY_ADDR, PHY_BCR); + bool fd = bcr & PHY_BCR_DUPLEX_MODE_Msk ? 1 : 0; + bool spd = bcr & PHY_BCR_SPEED_Msk ? 1 : 0; + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd); + } + return up; } @@ -7167,12 +7217,12 @@ void GMAC_Handler(void) { uint32_t isr = GMAC_REGS->GMAC_ISR; uint32_t rsr = GMAC_REGS->GMAC_RSR; uint32_t tsr = GMAC_REGS->GMAC_TSR; - // MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); - if (isr & BIT(1)) { - if (rsr & BIT(1)) { - for (int i = 0; i < 10; i++) { + //MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + if (isr & GMAC_ISR_RCOMP_Msk) { + if (rsr & GMAC_ISR_RCOMP_Msk) { + for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break; - uint32_t len = s_rxdesc[s_rxno][1] & (BIT(14) - 1); + size_t len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; @@ -7183,8 +7233,7 @@ void GMAC_Handler(void) { if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) { - GMAC_REGS->GMAC_TSR = tsr; - MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); + // MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31); } @@ -8824,6 +8873,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { pkt.raw.ptr = (char *) buf; pkt.raw.len = len; pkt.eth = (struct eth *) buf; + //mg_hexdump(buf, len > 16 ? 16: len); if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt? if (ifp->enable_mac_check && memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 && diff --git a/src/tcpip/driver_same54.c b/src/tcpip/driver_same54.c index 33b6f13d..2b49197a 100644 --- a/src/tcpip/driver_same54.c +++ b/src/tcpip/driver_same54.c @@ -11,8 +11,8 @@ #define ETH_DESC_CNT 4 // Descriptors count #define ETH_DS 2 // Descriptor size (words) -static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); -static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] __attribute__((aligned(8))); +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 @@ -21,6 +21,10 @@ static uint8_t s_rxno; // Current RX descriptor static struct mg_tcpip_if *s_ifp; // MIP interface enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; +#define PHY_BCR_DUPLEX_MODE_Msk BIT(8) +#define PHY_BCR_SPEED_Msk BIT(13) +#define PHY_BSR_LINK_STATUS_Msk BIT(2) + static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(2) | // Setting the read operation @@ -39,6 +43,56 @@ static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { } #endif +int get_clock_rate(struct mg_tcpip_driver_same54_data *d) { + if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) { + return d->mdc_cr; + } else { + // get MCLK from GCLK_GENERATOR 0 + uint32_t div = 512; + uint32_t mclk; + if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) { + div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16); + if (div == 0) div = 1; + } + switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) { + case GCLK_GENCTRL_SRC_XOSC0_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_XOSC1_Val: + mclk = 32000000UL; /* 32MHz */ + break; + case GCLK_GENCTRL_SRC_OSCULP32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_XOSC32K_Val: + mclk = 32000UL; + break; + case GCLK_GENCTRL_SRC_DFLL_Val: + mclk = 48000000UL; /* 48MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL0_Val: + mclk = 200000000UL; /* 200MHz */ + break; + case GCLK_GENCTRL_SRC_DPLL1_Val: + mclk = 200000000UL; /* 200MHz */ + break; + default: + mclk = 200000000UL; /* 200MHz */ + } + + mclk /= div; + uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values + uint8_t dividers[] = {8, 16, 32, 48, 64, 128}; // Respective CLK dividers + for (int i = 0; i < 6; i++) { + if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) { + return crs[i]; + } + } + + return 5; + } +} + static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { struct mg_tcpip_driver_same54_data *d = (struct mg_tcpip_driver_same54_data *) ifp->driver_data; @@ -46,56 +100,45 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) { MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk; MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk; - GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(d->mdc_cr); // Set MDC divider + GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO - // Init TX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer s_txdesc[i][1] = BIT(31); // OWN bit } s_txdesc[ETH_DESC_CNT - 1][1] |= BIT(30); // Last tx descriptor - wrap - // Init RX descriptors - for (int i = 0; i < ETH_DESC_CNT; i++) { - s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer - s_rxdesc[i][1] = 0; // Clear status + GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18); // DMA recv buf 1536 + for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors + s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer + s_rxdesc[i][1] = 0; // Clear status } - s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor + s_rxdesc[ETH_DESC_CNT - 1][0] |= BIT(1); // Last rx descriptor - wrap GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know - // Select RMII operation mode - GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; + GMAC_REGS->SA[0].GMAC_SAB = + MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); + GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); - // Configure the receive filter + GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk | - GMAC_NCFGR_SPD_Msk | GMAC_NCFGR_FD_Msk; - - // Clear transmit status register + GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk; GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk; - - // Clear receive status register GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk | GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk; - - // First disable all GMAC interrupts - GMAC_REGS->GMAC_IDR = ~0U; - - // Only the desired ones are enabled + GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk | GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk | GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk | GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk; - - // Enable the GMAC to transmit and receive data GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk; - NVIC_EnableIRQ(GMAC_IRQn); return true; @@ -124,9 +167,16 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len, static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { uint16_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR); - // MG_INFO(("BSR: 0x%x", bsr)); - bool up = bsr & BIT(2) ? 1 : 0; - (void) ifp; + bool up = bsr & PHY_BSR_LINK_STATUS_Msk ? 1 : 0; + + // If PHY is ready, update NCFGR accordingly + if (ifp->state == MG_TCPIP_STATE_DOWN && up) { + uint16_t bcr = eth_read_phy(PHY_ADDR, PHY_BCR); + bool fd = bcr & PHY_BCR_DUPLEX_MODE_Msk ? 1 : 0; + bool spd = bcr & PHY_BCR_SPEED_Msk ? 1 : 0; + GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd); + } + return up; } @@ -135,12 +185,12 @@ void GMAC_Handler(void) { uint32_t isr = GMAC_REGS->GMAC_ISR; uint32_t rsr = GMAC_REGS->GMAC_RSR; uint32_t tsr = GMAC_REGS->GMAC_TSR; - MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); - if (isr & BIT(1)) { - if (rsr & BIT(1)) { - for (int i = 0; i < 10; i++) { + //MG_INFO(("ISR: 0x%x, TSR: 0x%x, RSR: 0x%x", isr, tsr, rsr)); + if (isr & GMAC_ISR_RCOMP_Msk) { + if (rsr & GMAC_ISR_RCOMP_Msk) { + for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { if ((s_rxdesc[s_rxno][0] & BIT(0)) == 0) break; - uint32_t len = s_rxdesc[s_rxno][1] & (BIT(14) - 1); + size_t len = s_rxdesc[s_rxno][1] & (BIT(13) - 1); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); s_rxdesc[s_rxno][0] &= ~BIT(0); // Disown if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; @@ -151,8 +201,7 @@ void GMAC_Handler(void) { if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk | GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) { - GMAC_REGS->GMAC_TSR = tsr; - MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); + // MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr)); if (!(s_txdesc[s_txno][1] & BIT(31))) s_txdesc[s_txno][1] |= BIT(31); } diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index bfdc1d65..a0078f87 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -762,6 +762,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { pkt.raw.ptr = (char *) buf; pkt.raw.len = len; pkt.eth = (struct eth *) buf; + //mg_hexdump(buf, len > 16 ? 16: len); if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt? if (ifp->enable_mac_check && memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&