#include #define PHY PHY0 #define TXEN GPIO11 #define TXEN_PORT GPIOB #define TXD0 GPIO12 #define TXD0_PORT GPIOB #define TXD1 GPIO13 #define TXD1_PORT GPIOB #define RXD0 GPIO4 #define RXD0_PORT GPIOC #define RXD1 GPIO5 #define RXD1_PORT GPIOC #define CRS_DV GPIO7 #define CRS_DV_PORT GPIOA #define MDIO GPIO2 #define MDIO_PORT GPIOA #define MDC GPIO1 #define MDC_PORT GPIOC #define REF_CLK GPIO1 #define REF_CLK_PORT GPIOA #define NRST GPIO2 #define NRST_PORT GPIOE #define DESC_SZ 32 #define FRAME_SZ 1516 #define TX_BUFS 4 #define RX_BUFS 4 #define ETH_BUF_LEN ((TX_BUFS+ RX_BUFS) * (DESC_SZ+FRAME_SZ)) static int running; static uint8_t __attribute__ ((aligned (4))) eth_buf[ETH_BUF_LEN]; static uint8_t sa[ETHARP_HWADDR_LEN] = { 0xc0, 0xf1, 0xee, 0xc0, 0xff, 0xee }; extern uint32_t TxBD; extern uint32_t RxBD; bool phy_link_an_done (uint8_t phy) { return eth_smi_read (PHY, PHY_REG_BSR) & PHY_REG_BSR_ANDONE; } static err_t steth_tx (struct netif *netif, struct pbuf *p) { #if 0 static uint8_t tx_buf[FRAME_SZ]; uint32_t len, left; len = 0; left = FRAME_SZ; for (; p != NULL; p = p->next) { uint32_t sz = (left > p->len) ? p->len : left; memcpy (&tx_buf[len], (u8_t *) p->payload, sz); len += sz; left -= sz; } // usart6_write ("X", 1, 0); // hexdump(tx_buf,len); while (!eth_tx (tx_buf, len)); #else if (p->next) return ERR_IF; while (!eth_tx (p->payload, p->len)); #endif { static int tx_cnt = 0; printf ("TX %d\r\n", tx_cnt++); } return ERR_OK; } static err_t steth_rx (void) { //err_t err; struct pbuf *p; uint32_t len; #if 0 struct pbuf *q; static uint8_t rx_buf[FRAME_SZ]; len = 0; if (!eth_rx (rx_buf, &len, sizeof (rx_buf))) { usart6_write ("?", 1, 0); return ERR_OK; } /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ p = pbuf_alloc (PBUF_RAW, len, PBUF_POOL); if (!p) { usart6_write ("!", 1, 0); return ERR_MEM; } len = 0; for (q = p; q != NULL; q = q->next) { memcpy ((u8_t *) q->payload, (u8_t *) & rx_buf[len], q->len); len += q->len; } #else p = pbuf_alloc (PBUF_RAW, MTU, PBUF_POOL); if (!p) return ERR_MEM; len = 0; if (!eth_rx (p->payload, &len, MTU)) { pbuf_free (p); return ERR_IF; } pbuf_realloc (p, len); #endif // usart6_write (".", 1, 0); { static int rx_cnt = 0; printf ("RX %d\r\n", rx_cnt++); } return if0.input (p, &if0); } static void steth_nis (void) { if (eth_irq_ack_pending (ETH_DMASR_RS)) steth_rx(); } void eth_isr (void) { if (eth_irq_ack_pending (ETH_DMASR_NIS)) steth_nis(); } void steth_isr (void) { #if 0 // printf ("eth\r\n"); if (eth_irq_ack_pending (ETH_DMASR_NIS)) steth_nis(); #endif } err_t steth_lwip_init (struct netif *netif) { LWIP_ASSERT ("netif != NULL", (netif != NULL)); #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ netif->hostname = "lwip"; #endif /* LWIP_NETIF_HOSTNAME */ netif->name[0] = 's'; netif->name[1] = 't'; /* We directly use etharp_output() here to save a function call. * You can instead declare your own function an call etharp_output() * from it if you have to do some checks before sending (e.g. if link * is available...) */ netif->output = etharp_output; netif->linkoutput = steth_tx; /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* set MAC hardware address */ memcpy (netif->hwaddr, sa, ETHARP_HWADDR_LEN); /* maximum transfer unit */ netif->mtu = 1500; /* device capabilities */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; return ERR_OK; } void steth_init (void) { MAP_AF (TXEN, GPIO_AF11); MAP_AF (TXD0, GPIO_AF11); MAP_AF (TXD1, GPIO_AF11); MAP_AF (RXD0, GPIO_AF11); MAP_AF (RXD1, GPIO_AF11); MAP_AF (CRS_DV, GPIO_AF11); MAP_AF (MDIO, GPIO_AF11); MAP_AF (MDC, GPIO_AF11); MAP_AF (REF_CLK, GPIO_AF11); MAP_OUTPUT_PP (NRST); SET (NRST); /* The switch to RMII has be done with steth under reset, with no clock */ rcc_periph_clock_disable (RCC_ETHMACPTP); rcc_periph_clock_disable (RCC_ETHMACRX); rcc_periph_clock_disable (RCC_ETHMACTX); rcc_periph_clock_disable (RCC_ETHMAC); RCC_AHB1RSTR |= RCC_AHB1RSTR_ETHMACRST; /*Assert RESET */ delay_us (1); #ifndef SYSCFG_PMC_MII_RMII_SEL #define SYSCFG_PMC_MII_RMII_SEL (1UL << 23) #endif SYSCFG_PMC |= SYSCFG_PMC_MII_RMII_SEL; RCC_AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST; /*De-sssert RESET */ rcc_periph_clock_enable (RCC_ETHMAC); rcc_periph_clock_enable (RCC_ETHMACTX); rcc_periph_clock_enable (RCC_ETHMACRX); rcc_periph_clock_enable (RCC_ETHMACPTP); eth_desc_init (eth_buf, TX_BUFS, RX_BUFS, FRAME_SZ, FRAME_SZ, 1); /*MDC = HCLK / 102 (0b100) => 1.6MHz */ eth_init (PHY, 0x4); eth_enable_checksum_offload(); printf ("Waiting for link\r\n"); while (!phy_link_isup (PHY)); phy_autoneg_enable (PHY); printf ("Waiting for autonegociation\r\n"); while (!phy_link_an_done (PHY)); switch (phy_link_status (PHY)) { case LINK_HD_10M: case LINK_FD_10M: ETH_MACCR &= ~ETH_MACCR_FES; break; default: ; } switch (phy_link_status (PHY)) { case LINK_HD_10M: case LINK_HD_100M: ETH_MACCR &= ~ETH_MACCR_DM; ETH_MACCR |= ETH_MACCR_ROD; break; default: ; } ETH_MACCR &= ~ETH_MACCR_RD; eth_set_mac (sa); nvic_disable_irq (NVIC_ETH_IRQ); eth_irq_enable (ETH_DMAIER_NISE); eth_irq_enable (ETH_DMAIER_RIE); eth_irq_enable (ETH_DMASR_TS); // eth_start(); running++; printf ("Running\r\n"); } void steth_dispatch (void) { #if 0 uint32_t d, s; #endif if (!running) return; #if 0 printf ("Net:\r\n"); printf (" ETH_MACCR: %08" PRIx32 "\r\n", ETH_MACCR); printf (" ETH_MACDBGR: %08" PRIx32 "\r\n", ETH_MACDBGR); printf (" ETH_DMASR: %08" PRIx32 "\r\n", ETH_DMASR); printf (" ETH_DMAIER: %08" PRIx32 "\r\n", ETH_DMAIER); printf (" ETH_DMACHTDR: %08" PRIx32 "\r\n", ETH_DMACHTDR); printf (" ETH_DMACHRDR: %08" PRIx32 "\r\n", ETH_DMACHRDR); s = d = RxBD; do { printf (" %08" PRIx32 ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32 "\r\n", d, ETH_DES0 (d), ETH_DES1 (d), ETH_DES2 (d), ETH_DES3 (d)); d = ETH_DES3 (d); } while (d != s); #endif steth_isr(); }