summaryrefslogtreecommitdiffstats
path: root/app/steth.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/steth.c')
-rw-r--r--app/steth.c547
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;
}