#include #define PHY PHY0 #define RXER GPIO10 #define RXER_PORT GPIOB #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 ETH_DES_EXT_SIZE #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, 0xdd }; extern uint32_t TxBD; extern uint32_t RxBD; static void mac_stat(void) { uint32_t d, s; printf ("Net:\r\n"); printf (" ETH_MACCR: %08" PRIx32 "\r\n", ETH_MACCR); #if 0 printf (" ETH_MACFFR: %08" PRIx32 "\r\n", ETH_MACFFR); printf (" ETH_MACFCR: %08" PRIx32 "\r\n", ETH_MACFCR); printf (" ETH_MACDBGR: %08" PRIx32 "\r\n", ETH_MACDBGR); printf (" ETH_MACSR: %08" PRIx32 "\r\n", ETH_MACSR); #endif printf (" ETH_DMAOMR: %08" PRIx32 "\r\n", ETH_DMAOMR); printf (" ETH_DMASR: %08" PRIx32 " ebs=%x tps=%x rps=%x\r\n", ETH_DMASR, (ETH_DMASR >>23) & 7 , (ETH_DMASR >>20) & 7 , (ETH_DMASR >>17) & 7 ); 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); printf (" ETH_DMAOMR: %08" PRIx32 "\r\n", ETH_DMAOMR); printf (" ETH_DMATDLAR: %08" PRIx32 "\r\n", ETH_DMATDLAR); printf (" ETH_DMARDLAR: %08" PRIx32 "\r\n", ETH_DMARDLAR); printf (" ETH_DMABMR: %08" PRIx32 "\r\n", ETH_DMABMR); s = d = RxBD; if (running) 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); } static void phy_stat_reg(unsigned i) { static uint16_t last_phy[0x20]; uint16_t cur=eth_smi_read(PHY,i); if (cur==last_phy[i]) return; printf(" phy:%02x %4x (was %4x +%4x -%4x)\r\n", i,(unsigned) cur,(unsigned) last_phy[i], (unsigned) ((last_phy[i] ^ cur) & cur), (unsigned) ((last_phy[i] ^ cur) & last_phy[i])); last_phy[i]=cur; } static void phy_stat(void) { phy_stat_reg(0x0); phy_stat_reg(0x1); phy_stat_reg(0x4); phy_stat_reg(0x5); phy_stat_reg(0x6); phy_stat_reg(0x11); phy_stat_reg(0x12); phy_stat_reg(0x1f); } 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 #if 0 { static int tx_cnt = 0; printf ("TX %d\r\n", tx_cnt++); } #endif return ERR_OK; } static err_t steth_rx (void) { //err_t err; struct pbuf *p; uint32_t len; //printf("Packet\r\n"); #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); #if 0 { static int rx_cnt = 0; printf ("RX %d\r\n", rx_cnt++); } #endif 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 1 //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) { unsigned i; rcc_periph_clock_enable (RCC_GPIOA); rcc_periph_clock_enable (RCC_GPIOB); rcc_periph_clock_enable (RCC_GPIOC); rcc_periph_clock_enable (RCC_SYSCFG); rcc_periph_clock_enable (RCC_ETHMAC); rcc_periph_clock_enable (RCC_ETHMACTX); rcc_periph_clock_enable (RCC_ETHMACRX); rcc_periph_clock_enable (RCC_ETHMACPTP); rcc_periph_reset_hold(RST_ETHMAC); delay_ms(1); #ifndef SYSCFG_PMC_MII_RMII_SEL #define SYSCFG_PMC_MII_RMII_SEL (1UL << 23) #endif SYSCFG_PMC |= SYSCFG_PMC_MII_RMII_SEL; delay_ms(1); rcc_periph_reset_release(RST_ETHMAC); MAP_OUTPUT_PP (NRST); MAP_OUTPUT_PP (RXD0 ); MAP_OUTPUT_PP (RXD1 ); MAP_OUTPUT_PP (CRS_DV ); SET(RXD0); SET(RXD1); SET(CRS_DV); CLEAR(NRST); delay_ms(1); SET (NRST); MAP_AF_100 (REF_CLK, GPIO_AF11); MAP_AF_100 (MDIO, GPIO_AF11); MAP_AF_100 (CRS_DV, GPIO_AF11); MAP_AF_100(RXER,GPIO_AF11); MAP_AF_100(TXEN,GPIO_AF11); MAP_AF_100(TXD0,GPIO_AF11); MAP_AF_100(TXD1,GPIO_AF11); MAP_AF_100 (MDC, GPIO_AF11); MAP_AF_100 (RXD0, GPIO_AF11); MAP_AF_100 (RXD1, GPIO_AF11); /* The switch to RMII has be done with steth under reset, with no clock */ rcc_periph_reset_hold(RST_ETHMAC); delay_ms(1); #ifndef SYSCFG_PMC_MII_RMII_SEL #define SYSCFG_PMC_MII_RMII_SEL (1UL << 23) #endif SYSCFG_PMC |= SYSCFG_PMC_MII_RMII_SEL; delay_ms(1); rcc_periph_reset_release(RST_ETHMAC); ETH_DMABMR|=1; TRACE; while (ETH_DMABMR & 1) { mac_stat(); delay_ms(1000); } TRACE; /*MDC = HCLK / 102 (0b100) => 1.6MHz */ eth_init (PHY, 0x4); TRACE; phy_stat(); #if 0 // eth_smi_write (PHY, PHY_REG_BCR, 0x2100); printf ("Waiting for link\r\n"); while (!phy_link_isup (PHY)) { phy_stat(); delay_ms(1000); } #else eth_smi_write (PHY, PHY_REG_ANTX, 0x1e1); phy_autoneg_enable (PHY); printf ("Waiting for autonegociation\r\n"); i=0; while (!phy_link_an_done (PHY)) { phy_stat(); delay_ms(1000); #if 0 if (i>4) { phy_autoneg_enable (PHY); i=0; } #endif i++; } #endif switch (phy_link_status (PHY)) { case LINK_HD_10M: TRACE; case LINK_FD_10M: TRACE; ETH_MACCR &= ~ETH_MACCR_FES; break; default: TRACE; ; } printf("phy link status %x\r\n",phy_link_status(PHY)); switch (phy_link_status (PHY)) { case LINK_HD_10M: TRACE; case LINK_HD_100M: TRACE; ETH_MACCR &= ~ETH_MACCR_DM; ETH_MACCR |= ETH_MACCR_ROD; break; default: ; } TRACE; eth_set_mac (sa); TRACE; eth_enable_checksum_offload(); TRACE; eth_desc_init (eth_buf, TX_BUFS, RX_BUFS, FRAME_SZ, FRAME_SZ, 1); TRACE; ETH_MACCR &= ~ETH_MACCR_RD; 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++; nvic_enable_irq (NVIC_ETH_IRQ); printf ("Running\r\n"); } void steth_dispatch (void) { if (!running) return; }