diff options
author | root <root@lab.panaceas.james.local> | 2019-02-19 18:08:31 +0000 |
---|---|---|
committer | root <root@lab.panaceas.james.local> | 2019-02-19 18:08:31 +0000 |
commit | 9bbf1d200534cd946c4776e29457f989147b45b2 (patch) | |
tree | 6d167a3bede4ae9da3912562ad9fb5baf76d6770 /app/steth.c | |
parent | b3c6320899d6b27899ab3c67c745e8d3b29af3a2 (diff) | |
download | clock-9bbf1d200534cd946c4776e29457f989147b45b2.tar.gz clock-9bbf1d200534cd946c4776e29457f989147b45b2.tar.bz2 clock-9bbf1d200534cd946c4776e29457f989147b45b2.zip |
everything working, even with fucked phy
Diffstat (limited to 'app/steth.c')
-rw-r--r-- | app/steth.c | 547 |
1 files changed, 258 insertions, 289 deletions
diff --git a/app/steth.c b/app/steth.c index 8672163..afd68ed 100644 --- a/app/steth.c +++ b/app/steth.c @@ -1,52 +1,20 @@ #include <project.h> +#include "steth.h" -#define PHY PHY0 +#define FUCKED -#define RXER GPIO10 -#define RXER_PORT GPIOB +static int fucked; -#define TXEN GPIO11 -#define TXEN_PORT GPIOB -#define TXD0 GPIO12 -#define TXD0_PORT GPIOB +#define AN_RETRY 6 -#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 int an_clock; +static int an_happy; +static int ready; -static int running; static uint8_t __attribute__ ((aligned (4))) eth_buf[ETH_BUF_LEN]; @@ -56,80 +24,82 @@ extern uint32_t TxBD; extern uint32_t RxBD; -static void mac_stat(void) +#define FOO(a) \ + do { static uint32_t w; \ + uint32_t v=a; \ + if (v!=w) {\ + printf (" " #a": %08x (%08x +%08x -%08x)\r\n", \ + (unsigned) v,(unsigned) (v^w),(unsigned) ((v^w) &v),(unsigned) ((v^w)&w)); \ + }\ + w=v; \ + } while (0) + + + +static void mac_stat (void) { - uint32_t d, s; + //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; + FOO (ETH_MACCR); + FOO (ETH_MACFFR); + FOO (ETH_MACFCR); + FOO (ETH_MACDBGR); + FOO (ETH_MACSR); + FOO (ETH_DMAOMR); + FOO (ETH_DMASR); + FOO (ETH_DMAIER); + FOO (ETH_DMACHTDR); + FOO (ETH_DMACHRDR); + FOO (ETH_DMAOMR); + FOO (ETH_DMATDLAR); + FOO (ETH_DMARDLAR); + FOO (ETH_DMABMR); -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); +#if 0 + s = d = RxBD; - } while (d != s); -} + 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)); -static void phy_stat_reg(unsigned i) -{ -static uint16_t last_phy[0x20]; -uint16_t cur=eth_smi_read(PHY,i); + d = ETH_DES3 (d); -if (cur==last_phy[i]) return; + } while (d != s); -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])); +#endif -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); - +#define PHY_REGS 0x20 +static void phy_stat_reg (unsigned i) +{ + static uint16_t last_phy[PHY_REGS]; + 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) +{ + unsigned i; - + for (i = 0; i < PHY_REGS; ++i) + phy_stat_reg (i); +} bool phy_link_an_done (uint8_t phy) @@ -138,84 +108,22 @@ phy_link_an_done (uint8_t phy) } - 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; @@ -228,25 +136,11 @@ steth_rx (void) } 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) { @@ -264,14 +158,8 @@ eth_isr (void) void steth_isr (void) { -#if 1 - //printf ("eth\r\n"); - if (eth_irq_ack_pending (ETH_DMASR_NIS)) steth_nis(); - -#endif - } @@ -310,182 +198,263 @@ steth_lwip_init (struct netif *netif) } -void -steth_init (void) +#ifdef FUCKED + +static void fucked_phy_reset(uint8_t phy) +{ +unsigned i; + eth_smi_write(phy, PHY_REG_BCR, PHY_REG_BCR_RESET); + for (i=0;(eth_smi_read(phy, PHY_REG_BCR) & PHY_REG_BCR_RESET) && (i<1000);++i) delay_us(1000); + +} + +static void fucked_eth_init(uint8_t phy, enum eth_clk clock) +{ + ETH_MACMIIAR = clock; + fucked_phy_reset(phy); + + ETH_MACCR = ETH_MACCR_CSTF | ETH_MACCR_FES | ETH_MACCR_DM | + ETH_MACCR_APCS | ETH_MACCR_RD; + ETH_MACFFR = ETH_MACFFR_RA | ETH_MACFFR_PM; + ETH_MACHTHR = 0; /* pass all frames */ + ETH_MACHTLR = 0; + ETH_MACFCR = (0x100 << ETH_MACFCR_PT_SHIFT); + ETH_MACVLANTR = 0; + ETH_DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_DFRF | + ETH_DMAOMR_TSF | ETH_DMAOMR_FEF | ETH_DMAOMR_OSF; + ETH_DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_FB | + (32 << ETH_DMABMR_RDP_SHIFT) | (32 << ETH_DMABMR_PBL_SHIFT) | + ETH_DMABMR_PM_2_1 | ETH_DMABMR_USP; +} +#endif + + +void eth_reset (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); + printf("Eth_reset()\r\n"); + + 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); + + + delay_ms (1); + CLEAR (NRST); + delay_us (1); + SET (NRST); + delay_ms (1); + + TRACE; + ETH_DMABMR |= ETH_DMABMR_SR; + + i=0; + while (ETH_DMABMR & ETH_DMABMR_SR) { + delay_ms(1); + i++; + + if (i>1000) { + printf("No 50MHz clock to ethernet MAC\n"); + return; + } + } + + /*MDC = HCLK / 102 (0b100) => 1.6MHz */ + TRACE; +#ifdef FUCKED + fucked_eth_init (PHY, ETH_CLK_150_168MHZ); +#else + eth_init (PHY, ETH_CLK_150_168MHZ); +#endif + + if (eth_smi_read (PHY, 0)==0xffff) { + fucked=1; + printf("WARNING: PHY is AWOL\r\n"); + } + + TRACE; + phy_stat(); + + eth_set_mac (sa); + eth_enable_checksum_offload(); + eth_desc_init (eth_buf, TX_BUFS, RX_BUFS, FRAME_SZ, FRAME_SZ, 1); + + eth_irq_enable (ETH_DMAIER_NISE); + eth_irq_enable (ETH_DMAIER_RIE); + eth_irq_enable (ETH_DMASR_TS); + + +} + +void eth_start_an (void) +{ + printf ("starting autonegociation\r\n"); + eth_smi_write (PHY, PHY_REG_ANTX, 0x1e1); + phy_autoneg_enable (PHY); +} + +void +steth_init (void) +{ - rcc_periph_reset_hold(RST_ETHMAC); - delay_ms(1); + 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); + 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 ); + MAP_OUTPUT_PP (RXD0); + MAP_OUTPUT_PP (RXD1); + MAP_OUTPUT_PP (CRS_DV); + + MAP_AF_100 (REF_CLK, GPIO_AF11); - SET(RXD0); - SET(RXD1); - SET(CRS_DV); + SET (RXD0); + SET (RXD1); + SET (CRS_DV); - CLEAR(NRST); - delay_ms(1); + delay_ms (1); + CLEAR (NRST); + delay_ms (1); SET (NRST); + delay_ms (1); - 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 (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 + /* The switch to RMII has be done with steth under reset, with no clock */ - SYSCFG_PMC |= SYSCFG_PMC_MII_RMII_SEL; - delay_ms(1); - rcc_periph_reset_release(RST_ETHMAC); - ETH_DMABMR|=1; + eth_reset(); - TRACE; - while (ETH_DMABMR & 1) { - mac_stat(); - delay_ms(1000); - } -TRACE; + phy_stat(); + mac_stat(); - /*MDC = HCLK / 102 (0b100) => 1.6MHz */ - eth_init (PHY, 0x4); -TRACE; - phy_stat(); #if 0 -// eth_smi_write (PHY, PHY_REG_BCR, 0x2100); + 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"); + phy_stat(); + delay_ms (1000); + } -i=0; - while (!phy_link_an_done (PHY)) { - phy_stat(); - delay_ms(1000); +#endif + + eth_start_an(); + if (fucked) delay_ms(1000); + + + + // + //eth_start(); + nvic_enable_irq (NVIC_ETH_IRQ); + + + ready++; -#if 0 -if (i>4) { - phy_autoneg_enable (PHY); - i=0; } -#endif -i++; - } + + +static void eth_stop (void) +{ + ETH_MACCR &= (ETH_MACCR_TE & ETH_MACCR_RE); + ETH_DMAOMR &= ~ (ETH_DMAOMR_FTF | ETH_DMAOMR_ST | ETH_DMAOMR_SR); +} + +void steth_slow_tick (void) +{ + phy_stat(); + +#if 0 + mac_stat(); #endif - switch (phy_link_status (PHY)) { - case LINK_HD_10M: - TRACE; - case LINK_FD_10M: - TRACE; - ETH_MACCR &= ~ETH_MACCR_FES; - break; - - default: - TRACE; - ; - } + if (!ready) return; - printf("phy link status %x\r\n",phy_link_status(PHY)); + an_happy = phy_link_an_done (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; + if ((!phy_link_isup (PHY) || !an_happy) && running) { - default: - ; - } + printf ("stopping nic\r\n"); + eth_reset(); -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; + running = 0; + } - ETH_MACCR &= ~ETH_MACCR_RD; + if (!phy_link_isup (PHY) && an_happy) { + eth_start_an(); + an_clock = 0; + } + if (!an_happy) { + an_clock++; + if (an_clock > AN_RETRY) { + eth_start_an(); + an_clock = 0; + } - nvic_disable_irq (NVIC_ETH_IRQ); + } else + an_clock = 0; - eth_irq_enable (ETH_DMAIER_NISE); - eth_irq_enable (ETH_DMAIER_RIE); - eth_irq_enable (ETH_DMASR_TS); - // - eth_start(); + if (phy_link_isup (PHY) && an_happy && !running) { + printf ("autonegociation done\r\n"); + printf ("phy link status %x\r\n", phy_link_status (PHY)); - running++; - nvic_enable_irq (NVIC_ETH_IRQ); + switch (phy_link_status (PHY)) { + case LINK_HD_10M: + TRACE; - printf ("Running\r\n"); + case LINK_HD_100M: + TRACE; + ETH_MACCR &= ~ETH_MACCR_DM; + ETH_MACCR |= ETH_MACCR_ROD; + break; -} + default: + ; + } + ETH_MACCR &= ~ETH_MACCR_RD; + eth_start(); + printf ("starting nic\r\n"); + running++; + } -void -steth_dispatch (void) -{ - if (!running) - return; } |