You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2017/04/19 18:18:05 UTC

[09/30] incubator-mynewt-core git commit: STM32 ethernet driver for LwIP. Make it functional.

STM32 ethernet driver for LwIP. Make it functional.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/c5f8cf66
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/c5f8cf66
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/c5f8cf66

Branch: refs/heads/master
Commit: c5f8cf661026c137cf5832133183b8a76452df9b
Parents: 0092753
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Fri Apr 14 10:37:34 2017 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Fri Apr 14 13:21:30 2017 -0700

----------------------------------------------------------------------
 .../stm32_eth/include/stm32_eth/stm32_eth.h     |  49 ++
 .../stm32_eth/include/stm32_eth/stm32_eth_cfg.h |  47 ++
 hw/drivers/lwip/stm32_eth/pkg.yml               |  41 +
 hw/drivers/lwip/stm32_eth/src/stm32_eth.c       | 538 +++++++++++++
 .../include/stm32f4_eth/stm32f4_eth.h           |  27 -
 .../include/stm32f4_eth/stm32f4_eth_cfg.h       |  32 -
 hw/drivers/lwip/stm32f4_eth/pkg.yml             |  33 -
 hw/drivers/lwip/stm32f4_eth/src/stm32f4_eth.c   | 746 -------------------
 8 files changed, 675 insertions(+), 838 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth.h
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth.h b/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth.h
new file mode 100644
index 0000000..fa2f048
--- /dev/null
+++ b/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth.h
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __STM32_ETH_H__
+#define __STM32_ETH_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Initialize the ethernet device with cfg.
+ *
+ * @param cfg HW specific configuration.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int stm32_eth_init(const void *cfg);
+
+/*
+ * Set the MAC address for ethernet to use.
+ *
+ * @param addr Byte array of 6 bytes to use as MAC address.
+ *
+ * @return int 0 on success, non-zero error code on failure.
+ */
+int stm32_eth_set_hwaddr(uint8_t *addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32_ETH_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth_cfg.h
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth_cfg.h b/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth_cfg.h
new file mode 100644
index 0000000..db11201
--- /dev/null
+++ b/hw/drivers/lwip/stm32_eth/include/stm32_eth/stm32_eth_cfg.h
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __STM32_ETH_CFG_H__
+#define __STM32_ETH_CFG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * BSP specific ethernet settings.
+ */
+#define STM32_MAX_PORTS	9
+
+struct stm32_eth_cfg {
+    /* Mask of pins from ports A-I to use */
+    uint32_t sec_port_mask[STM32_MAX_PORTS];
+    enum {
+        SMSC_8710_RMII,
+        LAN_8742_RMII
+    } sec_phy_type;
+    int sec_phy_irq;
+    uint8_t sec_phy_addr;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32_ETH_CFG_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32_eth/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32_eth/pkg.yml b/hw/drivers/lwip/stm32_eth/pkg.yml
new file mode 100644
index 0000000..5250d4d
--- /dev/null
+++ b/hw/drivers/lwip/stm32_eth/pkg.yml
@@ -0,0 +1,41 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/drivers/lwip/stm32_eth
+pkg.description: Driver for STM32FXXXX on-chip ethernet
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ip
+    - lwip
+    - ethernet
+pkg.deps:
+    - hw/hal
+    - net/ip/lwip_base
+
+pkg.deps.MCU_STM32F4:
+    - hw/mcu/stm/stm32f4xx
+
+pkg.deps.MCU_STM32F7:
+    - hw/mcu/stm/stm32f7xx
+
+pkg.req_apis: 
+
+pkg.init:
+    stm32_eth_open: 240

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32_eth/src/stm32_eth.c
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32_eth/src/stm32_eth.c b/hw/drivers/lwip/stm32_eth/src/stm32_eth.c
new file mode 100755
index 0000000..c9f028d
--- /dev/null
+++ b/hw/drivers/lwip/stm32_eth/src/stm32_eth.c
@@ -0,0 +1,538 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <syscfg/syscfg.h>
+
+#include <hal/hal_gpio.h>
+#include <hal/hal_timer.h>
+#include <bsp/cmsis_nvic.h>
+
+#include <os/os_cputime.h>
+
+#if MYNEWT_VAL(MCU_STM32F4)
+#include <bsp/stm32f4xx_hal_conf.h>
+#include <mcu/stm32f4_bsp.h>
+#endif
+#if MYNEWT_VAL(MCU_STM32F7)
+#include <bsp/stm32f7xx_hal_conf.h>
+#include <mcu/stm32f7_bsp.h>
+#endif
+
+#include <netif/etharp.h>
+#include <netif/ethernet.h>
+#include <lwip/tcpip.h>
+#include <lwip/ethip6.h>
+#include <string.h>
+
+#include "stm32_eth/stm32_eth.h"
+#include "stm32_eth/stm32_eth_cfg.h"
+
+/*
+ * PHY polling frequency, when HW has no interrupt line to report link status
+ * changes.
+ *
+ * Note STM32F767ZI errata regarding RMII sometimes corrupting RX.
+ * This shows up as MMCRFCECR going up, and no valid RX happening.
+ */
+#define STM32_PHY_POLL_FREQ os_cputime_usecs_to_ticks(1500000) /* 1.5 secs */
+
+/*
+ * Phy specific registers
+ */
+#define SMSC_8710_ISR 29
+#define SMSC_8710_IMR 30
+
+#define SMSC_8710_ISR_AUTO_DONE 0x40
+#define SMSC_8710_ISR_LINK_DOWN 0x10
+
+#define STM32_ETH_RX_DESC_SZ 3
+#define STM32_ETH_TX_DESC_SZ 4
+
+struct stm32_eth_desc {
+    volatile ETH_DMADescTypeDef desc;
+    struct pbuf *p;
+};
+
+struct stm32_eth_state {
+    struct netif st_nif;
+    ETH_HandleTypeDef st_eth;
+    struct stm32_eth_desc st_rx_descs[STM32_ETH_RX_DESC_SZ];
+    struct stm32_eth_desc st_tx_descs[STM32_ETH_TX_DESC_SZ];
+    uint8_t st_rx_head;
+    uint8_t st_rx_tail;
+    uint8_t st_tx_head;
+    uint8_t st_tx_tail;
+    struct hal_timer st_phy_tmr;
+    const struct stm32_eth_cfg *cfg;
+};
+
+struct stm32_eth_stats {
+    uint32_t oframe;
+    uint32_t odone;
+    uint32_t oerr;
+    uint32_t iframe;
+    uint32_t imem;
+} stm32_eth_stats;
+
+static struct stm32_eth_state stm32_eth_state;
+
+static void
+stm32_eth_setup_descs(struct stm32_eth_desc *descs, int cnt)
+{
+    int i;
+
+    for (i = 0; i < cnt - 1; i++) {
+        descs[i].desc.Status = 0;
+        descs[i].desc.Buffer2NextDescAddr = (uint32_t)&descs[i + 1].desc;
+    }
+    descs[cnt - 1].desc.Status = 0;
+    descs[cnt - 1].desc.Buffer2NextDescAddr = (uint32_t)&descs[0].desc;
+}
+
+static void
+stm32_eth_fill_rx(struct stm32_eth_state *ses)
+{
+    struct stm32_eth_desc *sed;
+    struct pbuf *p;
+
+    while (1) {
+        sed = &ses->st_rx_descs[ses->st_rx_tail];
+        if (sed->p) {
+            break;
+        }
+        p = pbuf_alloc(PBUF_RAW, ETH_MAX_PACKET_SIZE, PBUF_POOL);
+        if (!p) {
+            ++stm32_eth_stats.imem;
+            break;
+        }
+        sed->p = p;
+        sed->desc.Status = 0;
+        sed->desc.ControlBufferSize = ETH_DMARXDESC_RCH | ETH_MAX_PACKET_SIZE;
+        sed->desc.Buffer1Addr = (uint32_t)p->payload;
+        sed->desc.Status = ETH_DMARXDESC_OWN;
+
+        ses->st_rx_tail++;
+        if (ses->st_rx_tail >= STM32_ETH_RX_DESC_SZ) {
+            ses->st_rx_tail = 0;
+        }
+    }
+}
+
+static struct pbuf *
+stm32_eth_input(struct stm32_eth_state *ses)
+{
+    struct stm32_eth_desc *sed;
+    struct pbuf *p;
+    struct netif *nif;
+
+    nif = &ses->st_nif;
+
+    while (1) {
+        sed = &ses->st_rx_descs[ses->st_rx_head];
+        if (!sed->p) {
+            break;
+        }
+        if (sed->desc.Status & ETH_DMARXDESC_OWN) {
+            break;
+        }
+        p = sed->p;
+        sed->p = NULL;
+        if (!(sed->desc.Status & ETH_DMARXDESC_LS)) {
+            /*
+             * Incoming data spans multiple pbufs. XXX support later
+             */
+            pbuf_free(p);
+            continue;
+        }
+        p->len = p->tot_len = (sed->desc.Status & ETH_DMARXDESC_FL) >> 16;
+        ++stm32_eth_stats.iframe;
+        nif->input(p, nif);
+        ses->st_rx_head++;
+        if (ses->st_rx_head >= STM32_ETH_RX_DESC_SZ) {
+            ses->st_rx_head = 0;
+        }
+    }
+
+    stm32_eth_fill_rx(ses);
+
+    if (ses->st_eth.Instance->DMASR & ETH_DMASR_RBUS)  {
+        /*
+         * Resume DMA reception
+         */
+        ses->st_eth.Instance->DMASR = ETH_DMASR_RBUS;
+        ses->st_eth.Instance->DMARPDR = 0;
+    }
+
+    return p;
+}
+
+void
+HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
+{
+    stm32_eth_input(&stm32_eth_state);
+}
+
+/*
+ * Hardware configuration. Should be called from BSP init.
+ */
+int
+stm32_eth_init(const void *cfg)
+{
+    stm32_eth_state.cfg = (const struct stm32_eth_cfg *)cfg;
+    return 0;
+}
+
+/*
+ * XXX do proper multicast filtering at some stage
+ */
+#if LWIP_IGMP
+static err_t
+stm32_igmp_mac_filter(struct netif *nif, const ip4_addr_t *group,
+  enum netif_mac_filter_action action)
+{
+    return -1;
+}
+#endif
+
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+static err_t
+stm32_mld_mac_filter(struct netif *nif, const ip6_addr_t *group,
+  enum netif_mac_filter_action action)
+{
+    return -1;
+}
+#endif
+
+static void
+stm32_eth_output_done(struct stm32_eth_state *ses)
+{
+    struct stm32_eth_desc *sed;
+
+    while (1) {
+        sed = &ses->st_tx_descs[ses->st_tx_tail];
+        if (!sed->p) {
+            break;
+        }
+        if (sed->desc.Status & ETH_DMATXDESC_OWN) {
+            /*
+             * Belongs to board
+             */
+            break;
+        }
+        if (sed->desc.Status & ETH_DMATXDESC_ES) {
+            ++stm32_eth_stats.oerr;
+        } else {
+            ++stm32_eth_stats.odone;
+        }
+        pbuf_free(sed->p);
+        sed->p = NULL;
+        ses->st_tx_tail++;
+        if (ses->st_tx_tail >= STM32_ETH_TX_DESC_SZ) {
+            ses->st_tx_tail = 0;
+        }
+    }
+}
+
+static err_t
+stm32_eth_output(struct netif *nif, struct pbuf *p)
+{
+    struct stm32_eth_state *ses = (struct stm32_eth_state *)nif;
+    struct stm32_eth_desc *sed;
+    uint32_t reg;
+    struct pbuf *q;
+    err_t errval;
+
+    stm32_eth_output_done(ses);
+
+    ++stm32_eth_stats.oframe;
+    sed = &ses->st_tx_descs[ses->st_tx_head];
+    for (q = p; q; q = q->next) {
+        if (!q->len) {
+            continue;
+        }
+        if (sed->desc.Status & ETH_DMATXDESC_OWN) {
+            /*
+             * Not enough space.
+             */
+            errval = ERR_MEM;
+            goto error;
+        }
+        sed = (struct stm32_eth_desc *)sed->desc.Buffer2NextDescAddr;
+    }
+
+    for (q = p; q; q = q->next) {
+        if (!q->len) {
+            continue;
+        }
+        sed = &ses->st_tx_descs[ses->st_tx_head];
+        if (q == p) {
+            reg = ETH_DMATXDESC_FS | ETH_DMATXDESC_TCH;
+        } else {
+            reg = ETH_DMATXDESC_TCH;
+        }
+        if (q->next == NULL) {
+            reg |= ETH_DMATXDESC_LS;
+        }
+        sed->desc.Status = reg;
+        sed->desc.ControlBufferSize = p->len;
+        sed->desc.Buffer1Addr = (uint32_t)p->payload;
+        sed->p = p;
+        pbuf_ref(p);
+        sed->desc.Status = reg | ETH_DMATXDESC_OWN;
+        ses->st_tx_head++;
+        if (ses->st_tx_head >= STM32_ETH_TX_DESC_SZ) {
+            ses->st_tx_head = 0;
+        }
+    }
+
+    if (ses->st_eth.Instance->DMASR & ETH_DMASR_TBUS) {
+        /*
+         * Resume DMA transmission.
+         */
+        ses->st_eth.Instance->DMASR = ETH_DMASR_TBUS;
+        ses->st_eth.Instance->DMATPDR = 0U;
+    }
+
+    return ERR_OK;
+error:
+    ++stm32_eth_stats.oerr;
+    return errval;
+}
+
+static void
+stm32_eth_isr(void)
+{
+    HAL_ETH_IRQHandler(&stm32_eth_state.st_eth);
+}
+
+static void
+stm32_phy_isr(void *arg)
+{
+    struct stm32_eth_state *ses = (void *)arg;
+    uint32_t reg;
+
+    HAL_ETH_ReadPHYRegister(&ses->st_eth, PHY_BSR, &reg);
+    if (reg & PHY_LINKED_STATUS &&
+        (ses->st_nif.flags & NETIF_FLAG_LINK_UP) == 0) {
+        netif_set_link_up(&ses->st_nif);
+    } else if ((reg & PHY_LINKED_STATUS) == 0 &&
+               ses->st_nif.flags & NETIF_FLAG_LINK_UP) {
+        netif_set_link_down(&ses->st_nif);
+    }
+    switch (ses->cfg->sec_phy_type) {
+    case SMSC_8710_RMII:
+    case LAN_8742_RMII:
+        HAL_ETH_ReadPHYRegister(&ses->st_eth, SMSC_8710_ISR, &reg);
+    }
+}
+
+static void
+stm32_phy_poll(void *arg)
+{
+    struct stm32_eth_state *ses = (void *)arg;
+
+    stm32_phy_isr(arg);
+    os_cputime_timer_relative(&ses->st_phy_tmr, STM32_PHY_POLL_FREQ);
+}
+
+static err_t
+stm32_lwip_init(struct netif *nif)
+{
+    struct stm32_eth_state *ses = &stm32_eth_state;
+    int i, j;
+    const struct stm32_eth_cfg *cfg;
+    uint32_t reg;
+
+    /*
+     * LwIP clears most of these field in netif_add() before calling
+     * this init routine. So we need to fill them in here.
+     */
+    memcpy(nif->name, "st", 2);
+    nif->output = etharp_output;
+#if LWIP_IPV6
+    nif->output_ip6 = ethip6_output;
+#endif
+    nif->linkoutput = stm32_eth_output;
+    nif->mtu = 1500;
+    nif->hwaddr_len = ETHARP_HWADDR_LEN;
+    nif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
+
+#if LWIP_IGMP
+    nif->flags |= NETIF_FLAG_IGMP;
+    nif->igmp_mac_filter = stm32_igmp_mac_filter;
+#endif
+#if LWIP_IPV6 && LWIP_IPV6_MLD
+    nif->flags |= NETIF_FLAG_MLD6;
+    nif->mld_mac_filter = stm32_mld_mac_filter;
+#endif
+
+    cfg = ses->cfg;
+
+    /*
+     * Now take the BSP specific HW config and set up the hardware.
+     */
+    for (i = 0; i < STM32_MAX_PORTS; i++) {
+        for (j = 0; j < 32; j++) {
+            if ((cfg->sec_port_mask[i] & (1 << j)) == 0) {
+                continue;
+            }
+            hal_gpio_init_af(i * 16 + j, GPIO_AF11_ETH, GPIO_NOPULL, 0);
+        }
+    }
+
+    NVIC_SetVector(ETH_IRQn, (uint32_t)stm32_eth_isr);
+    __HAL_RCC_ETH_CLK_ENABLE();
+
+    ses->st_eth.Instance = ETH;
+
+    ses->st_eth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
+    ses->st_eth.Init.Speed = ETH_SPEED_100M;
+    ses->st_eth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+    ses->st_eth.Init.PhyAddress = cfg->sec_phy_addr;
+    ses->st_eth.Init.RxMode = ETH_RXINTERRUPT_MODE;
+    ses->st_eth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+
+    switch (cfg->sec_phy_type) {
+    case SMSC_8710_RMII:
+    case LAN_8742_RMII:
+        ses->st_eth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
+    }
+
+    ses->st_rx_head = 0;
+    ses->st_rx_tail = 0;
+    ses->st_tx_head = 0;
+    ses->st_tx_tail = 0;
+
+    stm32_eth_setup_descs(ses->st_rx_descs, STM32_ETH_RX_DESC_SZ);
+    stm32_eth_setup_descs(ses->st_tx_descs, STM32_ETH_TX_DESC_SZ);
+    stm32_eth_fill_rx(ses);
+
+    if (HAL_ETH_Init(&ses->st_eth) == HAL_ERROR) {
+        return ERR_IF;
+    }
+
+    /*
+     * XXX pass all multicast traffic for now
+     */
+    ses->st_eth.Instance->MACFFR |= ETH_MULTICASTFRAMESFILTER_NONE;
+    ses->st_eth.Instance->DMATDLAR = (uint32_t)ses->st_tx_descs;
+    ses->st_eth.Instance->DMARDLAR = (uint32_t)ses->st_rx_descs;
+
+    /*
+     * Generate an interrupt when link state changes
+     */
+    if (cfg->sec_phy_irq >= 0) {
+        switch (cfg->sec_phy_type) {
+        case SMSC_8710_RMII:
+            HAL_ETH_ReadPHYRegister(&ses->st_eth, SMSC_8710_IMR, &reg);
+            reg |= (SMSC_8710_ISR_AUTO_DONE | SMSC_8710_ISR_LINK_DOWN);
+            HAL_ETH_WritePHYRegister(&ses->st_eth, SMSC_8710_IMR, reg);
+        case LAN_8742_RMII:
+            /* XXX */
+            break;
+        }
+    } else {
+        os_cputime_timer_init(&ses->st_phy_tmr, stm32_phy_poll, ses);
+        os_cputime_timer_relative(&ses->st_phy_tmr, STM32_PHY_POLL_FREQ);
+    }
+    NVIC_EnableIRQ(ETH_IRQn);
+    HAL_ETH_Start(&ses->st_eth);
+
+    /*
+     * Check for link.
+     */
+    stm32_phy_isr(ses);
+    return ERR_OK;
+}
+
+int
+stm32_mii_dump(void (*func)(const char *fmt, ...))
+{
+    int i;
+    struct stm32_eth_state *ses = &stm32_eth_state;
+    uint32_t reg;
+    int rc;
+
+    for (i = 0; i <= 6; i++) {
+        rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, &reg);
+        func("%d: %x (%d)\n", i, reg, rc);
+    }
+    for (i = 17; i <= 18; i++) {
+        rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, &reg);
+        func("%d: %x (%d)\n", i, reg, rc);
+    }
+    for (i = 26; i <= 31; i++) {
+        rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, &reg);
+        func("%d: %x (%d)\n", i, reg, rc);
+    }
+    return 0;
+}
+
+int
+stm32_eth_set_hwaddr(uint8_t *addr)
+{
+    struct stm32_eth_state *ses = &stm32_eth_state;
+
+    if (ses->st_nif.name[0] != '\0') {
+        /*
+         * Needs to be called before stm32_eth_open() is called.
+         */
+        return -1;
+    }
+    memcpy(ses->st_nif.hwaddr, addr, ETHARP_HWADDR_LEN);
+    ses->st_eth.Init.MACAddr = ses->st_nif.hwaddr;
+    return 0;
+}
+
+int
+stm32_eth_open(void)
+{
+    struct stm32_eth_state *ses = &stm32_eth_state;
+    struct netif *nif;
+    struct ip4_addr addr;
+    int rc;
+
+    if (ses->cfg == NULL) {
+        /*
+         * HW configuration not passed in.
+         */
+        return -1;
+    }
+    if (ses->st_eth.Init.MACAddr == NULL) {
+        /*
+         * MAC address not set
+         */
+        return -1;
+    }
+
+    if (ses->cfg->sec_phy_irq >= 0) {
+        rc = hal_gpio_irq_init(ses->cfg->sec_phy_irq, stm32_phy_isr, ses,
+                               HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP);
+        assert(rc == 0);
+    }
+
+    /*
+     * Register network interface with LwIP.
+     */
+    memset(&addr, 0, sizeof(addr));
+    nif = netif_add(&ses->st_nif, &addr, &addr, &addr, NULL, stm32_lwip_init,
+                    tcpip_input);
+    assert(nif);
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth.h
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth.h b/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth.h
deleted file mode 100644
index c9dde0d..0000000
--- a/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef __STM32F4_ETH_H__
-#define __STM32F4_ETH_H__
-
-int stm32f4_eth_init(void *cfg);
-int stm32f4_eth_open(void);
-int stm32f4_eth_close(void);
-
-#endif /* __STM32F4_ETH_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth_cfg.h
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth_cfg.h b/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth_cfg.h
deleted file mode 100644
index 49f5fed..0000000
--- a/hw/drivers/lwip/stm32f4_eth/include/stm32f4_eth/stm32f4_eth_cfg.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef __STM32F4_ETH_CFG_H__
-#define __STM32F4_ETH_CFG_H__
-
-/*
- * BSP specific ethernet settings.
- */
-#define STM32F4_MAX_PORTS	9
-
-struct stm32f4_eth_cfg {
-    /* Mask of pins from ports A-I to use */
-    uint32_t sec_port_mask[STM32F4_MAX_PORTS];
-};
-#endif /* __STM32F4_ETH_CFG_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32f4_eth/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32f4_eth/pkg.yml b/hw/drivers/lwip/stm32f4_eth/pkg.yml
deleted file mode 100644
index 606bf1f..0000000
--- a/hw/drivers/lwip/stm32f4_eth/pkg.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#  http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-pkg.name: hw/drivers/lwip/stm32f4_eth
-pkg.description: Driver for STM43F4 on-chip ethernet
-pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
-pkg.homepage: "http://mynewt.apache.org/"
-pkg.keywords:
-    - ip
-    - lwip
-    - ethernet
-pkg.deps:
-    - hw/hal
-    - hw/mcu/stm/stm32f4xx
-    - net/ip/lwip_base
-pkg.req_apis: 
-

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5f8cf66/hw/drivers/lwip/stm32f4_eth/src/stm32f4_eth.c
----------------------------------------------------------------------
diff --git a/hw/drivers/lwip/stm32f4_eth/src/stm32f4_eth.c b/hw/drivers/lwip/stm32f4_eth/src/stm32f4_eth.c
deleted file mode 100755
index 0660a19..0000000
--- a/hw/drivers/lwip/stm32f4_eth/src/stm32f4_eth.c
+++ /dev/null
@@ -1,746 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <hal/hal_gpio.h>
-#include <bsp/cmsis_nvic.h>
-
-#include <stm32f4xx.h>
-#include <stm32f4xx_hal_gpio.h>
-#include <stm32f4xx_hal_eth.h>
-#include <stm32f4xx_hal_rcc.h>
-#include <mcu/stm32f4_bsp.h>
-
-#include <netif/etharp.h>
-#include <netif/ethernet.h>
-#include <lwip/ethip6.h>
-#include <string.h>
-
-#include "stm32f4_eth/stm32f4_eth.h"
-#include "stm32f4_eth/stm32f4_eth_cfg.h"
-
-#if 0
-/* Private typedef -----------------------------------------------------------*/
-/* Private define ------------------------------------------------------------*/
-/* Network interface name */
-#define IFNAME0 's'
-#define IFNAME1 't'
-
-/* Private macro -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
-  #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN ETH_DMADescTypeDef  DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;/* Ethernet Rx MA Descriptor */
-
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
-  #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN ETH_DMADescTypeDef  DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;/* Ethernet Tx DMA Descriptor */
-
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
-  #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */
-
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
-  #pragma data_alignment=4
-#endif
-__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */
-
-ETH_HandleTypeDef EthHandle;
-
-/* Private function prototypes -----------------------------------------------*/
-/* Private functions ---------------------------------------------------------*/
-/*******************************************************************************
-                       Ethernet MSP Routines
-*******************************************************************************/
-/**
-  * @brief  Initializes the ETH MSP.
-  * @param  heth: ETH handle
-  * @retval None
-  */
-void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
-{ 
-  GPIO_InitTypeDef GPIO_InitStructure;
-  
-  /* Enable GPIOs clocks */
-  __HAL_RCC_GPIOA_CLK_ENABLE();
-  __HAL_RCC_GPIOB_CLK_ENABLE();
-  __HAL_RCC_GPIOC_CLK_ENABLE();
-  __HAL_RCC_GPIOF_CLK_ENABLE();
-  __HAL_RCC_GPIOG_CLK_ENABLE();
-  __HAL_RCC_GPIOH_CLK_ENABLE();
-  __HAL_RCC_GPIOI_CLK_ENABLE(); 
-
-/* Ethernet pins configuration ************************************************/
-   /*
-        ETH_MDIO -------------------------> PA2
-        ETH_MDC --------------------------> PC1
-        ETH_PPS_OUT ----------------------> PB5
-        ETH_MII_CRS ----------------------> PH2
-        ETH_MII_COL ----------------------> PH3
-        ETH_MII_RX_ER --------------------> PI10
-        ETH_MII_RXD2 ---------------------> PH6
-        ETH_MII_RXD3 ---------------------> PH7
-        ETH_MII_TX_CLK -------------------> PC3
-        ETH_MII_TXD2 ---------------------> PC2
-        ETH_MII_TXD3 ---------------------> PB8
-        ETH_MII_RX_CLK/ETH_RMII_REF_CLK---> PA1
-        ETH_MII_RX_DV/ETH_RMII_CRS_DV ----> PA7
-        ETH_MII_RXD0/ETH_RMII_RXD0 -------> PC4
-        ETH_MII_RXD1/ETH_RMII_RXD1 -------> PC5
-        ETH_MII_TX_EN/ETH_RMII_TX_EN -----> PG11
-        ETH_MII_TXD0/ETH_RMII_TXD0 -------> PG13
-        ETH_MII_TXD1/ETH_RMII_TXD1 -------> PG14
-                                                  */
-
-  /* Configure PA1, PA2 , PA7 */
-  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
-  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
-  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
-  GPIO_InitStructure.Pull = GPIO_NOPULL; 
-  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
-  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-  /* Configure PB5 and PB8 */
-  GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_8;
-  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-  /* Configure PC1, PC2, PC3, PC4 and PC5 */
-  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
-  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
-                             
-  /* Configure PG11, PG14 and PG13 */
-  GPIO_InitStructure.Pin =  GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
-  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
-
-  /* Configure PH2, PH3, PH6, PH7 */
-  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7;
-  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
-
-  /* Configure PI10 */
-  GPIO_InitStructure.Pin = GPIO_PIN_10;
-  HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
-  
-  /* Enable ETHERNET clock  */
-  __HAL_RCC_ETH_CLK_ENABLE();
-  
-  if (heth->Init.MediaInterface == ETH_MEDIA_INTERFACE_MII)
-  {
-    /* Output HSE clock (25MHz) on MCO pin (PA8) to clock the PHY */
-    HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
-  }
-}
-
-/*******************************************************************************
-                       LL Driver Interface ( LwIP stack --> ETH) 
-*******************************************************************************/
-/**
-  * In this function, the hardware should be initialized.
-  * Called from ethernetif_init().
-  *
-  * @param netif the already initialized lwip network interface structure
-  *        for this ethernetif
-  */
-static void low_level_init(struct netif *netif)
-{ 
-  uint32_t regvalue = 0;
-  uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };
-
-  EthHandle.Instance = ETH;  
-  EthHandle.Init.MACAddr = macaddress;
-  EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
-  EthHandle.Init.Speed = ETH_SPEED_100M;
-  EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
-  EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
-  EthHandle.Init.RxMode = ETH_RXPOLLING_MODE;
-  EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
-  EthHandle.Init.PhyAddress = DP83848_PHY_ADDRESS;
-  
-  /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
-  if (HAL_ETH_Init(&EthHandle) == HAL_OK)
-  {
-    /* Set netif link flag */
-    netif->flags |= NETIF_FLAG_LINK_UP;
-  }
-  
-  /* Initialize Tx Descriptors list: Chain Mode */
-  HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
-     
-  /* Initialize Rx Descriptors list: Chain Mode  */
-  HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
-
-  /* set MAC hardware address length */
-  netif->hwaddr_len = ETHARP_HWADDR_LEN;
-  
-  /* set MAC hardware address */
-  netif->hwaddr[0] =  MAC_ADDR0;
-  netif->hwaddr[1] =  MAC_ADDR1;
-  netif->hwaddr[2] =  MAC_ADDR2;
-  netif->hwaddr[3] =  MAC_ADDR3;
-  netif->hwaddr[4] =  MAC_ADDR4;
-  netif->hwaddr[5] =  MAC_ADDR5;
-  
-  /* maximum transfer unit */
-  netif->mtu = 1500;
-  
-  /* device capabilities */
-  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
-  netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
-  
-  /* Enable MAC and DMA transmission and reception */
-  HAL_ETH_Start(&EthHandle);
-  
-  /**** Configure PHY to generate an interrupt when Eth Link state changes ****/
-  /* Read Register Configuration */
-  HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MICR, &regvalue);
-  
-  regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
-
-  /* Enable Interrupts */
-  HAL_ETH_WritePHYRegister(&EthHandle, PHY_MICR, regvalue );
-  
-  /* Read Register Configuration */
-  HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, &regvalue);
-  
-  regvalue |= PHY_MISR_LINK_INT_EN;
-    
-  /* Enable Interrupt on change of link status */
-  HAL_ETH_WritePHYRegister(&EthHandle, PHY_MISR, regvalue);
-}
-
-/**
-  * This function should do the actual transmission of the packet. The packet is
-  * contained in the pbuf that is passed to the function. This pbuf
-  * might be chained.
-  *
-  * @param netif the lwip network interface structure for this ethernetif
-  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
-  * @return ERR_OK if the packet could be sent
-  *         an err_t value if the packet couldn't be sent
-  *
-  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
-  *       strange results. You might consider waiting for space in the DMA queue
-  *       to become availale since the stack doesn't retry to send a packet
-  *       dropped because of memory failure (except for the TCP timers).
-  */
-static err_t low_level_output(struct netif *netif, struct pbuf *p)
-{
-  err_t errval;
-  struct pbuf *q;
-  uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr);
-  __IO ETH_DMADescTypeDef *DmaTxDesc;
-  uint32_t framelength = 0;
-  uint32_t bufferoffset = 0;
-  uint32_t byteslefttocopy = 0;
-  uint32_t payloadoffset = 0;
-
-  DmaTxDesc = EthHandle.TxDesc;
-  bufferoffset = 0;
-  
-  /* copy frame from pbufs to driver buffers */
-  for(q = p; q != NULL; q = q->next)
-  {
-    /* Is this buffer available? If not, goto error */
-    if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
-    {
-      errval = ERR_USE;
-      goto error;
-    }
-    
-    /* Get bytes in current lwIP buffer */
-    byteslefttocopy = q->len;
-    payloadoffset = 0;
-    
-    /* Check if the length of data to copy is bigger than Tx buffer size*/
-    while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE )
-    {
-      /* Copy data to Tx buffer*/
-      memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );
-      
-      /* Point to next descriptor */
-      DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
-      
-      /* Check if the buffer is available */
-      if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
-      {
-        errval = ERR_USE;
-        goto error;
-      }
-      
-      buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
-      
-      byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
-      payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
-      framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
-      bufferoffset = 0;
-    }
-    
-    /* Copy the remaining bytes */
-    memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy );
-    bufferoffset = bufferoffset + byteslefttocopy;
-    framelength = framelength + byteslefttocopy;
-  }
-  
-  /* Prepare transmit descriptors to give to DMA */ 
-  HAL_ETH_TransmitFrame(&EthHandle, framelength);
-  
-  errval = ERR_OK;
-  
-error:
-  
-  /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
-  if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
-  {
-    /* Clear TUS ETHERNET DMA flag */
-    EthHandle.Instance->DMASR = ETH_DMASR_TUS;
-    
-    /* Resume DMA transmission*/
-    EthHandle.Instance->DMATPDR = 0;
-  }
-  return errval;
-}
-
-/**
-  * Should allocate a pbuf and transfer the bytes of the incoming
-  * packet from the interface into the pbuf.
-  *
-  * @param netif the lwip network interface structure for this ethernetif
-  * @return a pbuf filled with the received packet (including MAC header)
-  *         NULL on memory error
-  */
-static struct pbuf * low_level_input(struct netif *netif)
-{
-  struct pbuf *p = NULL;
-  struct pbuf *q;
-  uint16_t len;
-  uint8_t *buffer;
-  __IO ETH_DMADescTypeDef *dmarxdesc;
-  uint32_t bufferoffset = 0;
-  uint32_t payloadoffset = 0;
-  uint32_t byteslefttocopy = 0;
-  uint32_t i=0;
-  
-  if (HAL_ETH_GetReceivedFrame(&EthHandle) != HAL_OK)
-    return NULL;
-  
-  /* Obtain the size of the packet and put it into the "len" variable. */
-  len = EthHandle.RxFrameInfos.length;
-  buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;
-  
-  /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
-  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
-  
-  if (p != NULL)
-  {
-    dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
-    bufferoffset = 0;
-    for(q = p; q != NULL; q = q->next)
-    {
-      byteslefttocopy = q->len;
-      payloadoffset = 0;
-      
-      /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
-      while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
-      {
-        /* Copy data to pbuf*/
-        memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
-        
-        /* Point to next descriptor */
-        dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
-        buffer = (unsigned char *)(dmarxdesc->Buffer1Addr);
-        
-        byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
-        payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
-        bufferoffset = 0;
-      }
-      /* Copy remaining data in pbuf */
-      memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy);
-      bufferoffset = bufferoffset + byteslefttocopy;
-    }
-  }
-  
-  dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
-  
-  /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
-  for (i=0; i< (EthHandle.RxFrameInfos).SegCount; i++)
-  {  
-    dmarxdesc->Status = ETH_DMARXDESC_OWN;
-    dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
-  }
-  
-  /* Clear Segment_Count */
-  (EthHandle.RxFrameInfos).SegCount =0;
-  
-  /* When Rx Buffer unavailable flag is set: clear it and resume reception */
-  if (((EthHandle.Instance)->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)  
-  {
-    /* Clear RBUS ETHERNET DMA flag */
-    (EthHandle.Instance)->DMASR = ETH_DMASR_RBUS;
-    /* Resume DMA reception */
-    (EthHandle.Instance)->DMARPDR = 0;
-  }
-  return p;
-}
-
-/**
-  * This function should be called when a packet is ready to be read
-  * from the interface. It uses the function low_level_input() that
-  * should handle the actual reception of bytes from the network
-  * interface. Then the type of the received packet is determined and
-  * the appropriate input function is called.
-  *
-  * @param netif the lwip network interface structure for this ethernetif
-  */
-void ethernetif_input(struct netif *netif)
-{
-  err_t err;
-  struct pbuf *p;
-  
-  /* move received packet into a new pbuf */
-  p = low_level_input(netif);
-    
-  /* no packet could be read, silently ignore this */
-  if (p == NULL) return;
-    
-  /* entry point to the LwIP stack */
-  err = netif->input(p, netif);
-    
-  if (err != ERR_OK)
-  {
-    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
-    pbuf_free(p);
-    p = NULL;
-  }
-}
-
-/**
-  * Should be called at the beginning of the program to set up the
-  * network interface. It calls the function low_level_init() to do the
-  * actual setup of the hardware.
-  *
-  * This function should be passed as a parameter to netif_add().
-  *
-  * @param netif the lwip network interface structure for this ethernetif
-  * @return ERR_OK if the loopif is initialized
-  *         ERR_MEM if private data couldn't be allocated
-  *         any other err_t on error
-  */
-err_t ethernetif_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] = IFNAME0;
-  netif->name[1] = IFNAME1;
-  /* 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 = low_level_output;
-
-  /* initialize the hardware */
-  low_level_init(netif);
-
-  return ERR_OK;
-}
-
-/**
-  * @brief  Returns the current time in milliseconds
-  *         when LWIP_TIMERS == 1 and NO_SYS == 1
-  * @param  None
-  * @retval Time
-  */
-u32_t sys_now(void)
-{
-  return HAL_GetTick();
-}
-
-/**
-  * @brief  This function sets the netif link status.
-  * @param  netif: the network interface
-  * @retval None
-  */
-void ethernetif_set_link(struct netif *netif)
-{
-  uint32_t regvalue = 0;
-  
-  /* Read PHY_MISR*/
-  HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, &regvalue);
-  
-  /* Check whether the link interrupt has occurred or not */
-  if((regvalue & PHY_LINK_INTERRUPT) != (uint16_t)RESET)
-  {
-    /* Read PHY_SR*/
-    HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, &regvalue);
-    
-    /* Check whether the link is up or down*/
-    if((regvalue & PHY_LINK_STATUS)!= (uint16_t)RESET)
-    {
-      netif_set_link_up(netif);
-    }
-    else
-    {
-      netif_set_link_down(netif);
-    }
-  }
-}
-
-/**
-  * @brief  Link callback function, this function is called on change of link status
-  *         to update low level driver configuration.
-  * @param  netif: The network interface
-  * @retval None
-  */
-void ethernetif_update_config(struct netif *netif)
-{
-  __IO uint32_t tickstart = 0;
-  uint32_t regvalue = 0;
-  
-  if(netif_is_link_up(netif))
-  { 
-    /* Restart the auto-negotiation */
-    if(EthHandle.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
-    {
-      /* Enable Auto-Negotiation */
-      HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION);
-      
-      /* Get tick */
-      tickstart = HAL_GetTick();
-      
-      /* Wait until the auto-negotiation will be completed */
-      do
-      {
-        HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &regvalue);
-        
-        /* Check for the Timeout ( 1s ) */
-        if((HAL_GetTick() - tickstart ) > 1000)
-        {
-          /* In case of timeout */
-          goto error;
-        }
-        
-      } while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));
-      
-      /* Read the result of the auto-negotiation */
-      HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, &regvalue);
-      
-      /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
-      if((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
-      {
-        /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
-        EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;  
-      }
-      else
-      {
-        /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
-        EthHandle.Init.DuplexMode = ETH_MODE_HALFDUPLEX;           
-      }
-      /* Configure the MAC with the speed fixed by the auto-negotiation process */
-      if(regvalue & PHY_SPEED_STATUS)
-      {  
-        /* Set Ethernet speed to 10M following the auto-negotiation */
-        EthHandle.Init.Speed = ETH_SPEED_10M; 
-      }
-      else
-      {   
-        /* Set Ethernet speed to 100M following the auto-negotiation */ 
-        EthHandle.Init.Speed = ETH_SPEED_100M;
-      }
-    }
-    else /* AutoNegotiation Disable */
-    {
-    error :
-      /* Check parameters */
-      assert_param(IS_ETH_SPEED(EthHandle.Init.Speed));
-      assert_param(IS_ETH_DUPLEX_MODE(EthHandle.Init.DuplexMode));
-      
-      /* Set MAC Speed and Duplex Mode to PHY */
-      HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, ((uint16_t)(EthHandle.Init.DuplexMode >> 3) |
-                                                     (uint16_t)(EthHandle.Init.Speed >> 1))); 
-    }
-
-    /* ETHERNET MAC Re-Configuration */
-    HAL_ETH_ConfigMAC(&EthHandle, (ETH_MACInitTypeDef *) NULL);
-
-    /* Restart MAC interface */
-    HAL_ETH_Start(&EthHandle);   
-  }
-  else
-  {
-    /* Stop MAC interface */
-    HAL_ETH_Stop(&EthHandle);
-  }
-
-  ethernetif_notify_conn_changed(netif);
-}
-
-/**
-  * @brief  This function notify user about link status changement.
-  * @param  netif: the network interface
-  * @retval None
-  */
-__weak void ethernetif_notify_conn_changed(struct netif *netif)
-{
-  /* NOTE : This is function clould be implemented in user file 
-            when the callback is needed,
-  */  
-}
-#endif
-
-struct stm32f4_eth_state {
-    struct netif nif;
-    ETH_HandleTypeDef st_eth;
-    struct stm32f4_eth_cfg *cfg;
-};
-
-static struct stm32f4_eth_state stm32f4_eth_state;
-
-/*
- * Hardware configuration. Should be called from BSP init.
- */
-int
-stm32f4_eth_init(void *cfg)
-{
-    stm32f4_eth_state.cfg = cfg;
-    return 0;
-}
-
-#if LWIP_IGMP
-static err_t
-stm32f4_igmp_mac_filter(struct netif *nif, const ip4_addr_t *group,
-  enum netif_mac_filter_action action)
-{
-    return -1;
-}
-#endif
-
-#if LWIP_IPV6 && LWIP_IPV6_MLD
-static err_t
-stm32f4_mld_mac_filter(struct netif *nif, const ip6_addr_t *group,
-  enum netif_mac_filter_action action)
-{
-    return -1;
-}
-#endif
-
-static err_t
-stm32f4_output(struct netif *nif, struct pbuf *p)
-{
-    return ERR_OK;
-}
-
-static void
-stm32f4_eth_isr(void)
-{
-#if 0
-    HAL_ETH_IRQHandler(&stmref4_eth_State.st_eth);
-#endif
-}
-
-static err_t
-stm32f4_lwip_init(struct netif *nif)
-{
-    struct stm32f4_eth_state *ses = &stm32f4_eth_state;
-    int i, j;
-    struct stm32f4_eth_cfg *cfg;
-
-    /*
-     * LwIP clears most of these field in netif_add() before calling
-     * this init routine. So we need to fill them in here.
-     */
-    memcpy(nif->name, "st", 2);
-    nif->output = etharp_output;
-#if LWIP_IPV6
-    nif->output_ip6 = ethip6_output;
-#endif
-    nif->linkoutput = stm32f4_output;
-    nif->mtu = 1500;
-    nif->hwaddr_len = ETHARP_HWADDR_LEN;
-    nif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
-
-#if LWIP_IGMP
-    nif->flags |= NETIF_FLAG_IGMP;
-    nif->igmp_mac_filter = stm32f4_igmp_mac_filter;
-#endif
-#if LWIP_IPV6 && LWIP_IPV6_MLD
-    nif->flags |= NETIF_FLAG_MLD6;
-    nif->mld_mac_filter = stm32f4_mld_mac_filter;
-#endif
-
-    cfg = ses->cfg;
-
-    /*
-     * Now take the BSP specific HW config and set up the hardware.
-     */
-    for (i = 0; i < STM32F4_MAX_PORTS; i++) {
-        for (j = 0; j < 32; j++) {
-            if ((cfg->sec_port_mask[i] & (1 << j)) == 0) {
-                continue;
-            }
-#if 0
-            hal_gpio_init_af(i * 16 + j, GPIO_AF11_ETH, GPIO_NOPULL);
-#endif
-        }
-    }
-
-    NVIC_SetVector(ETH_IRQn, (uint32_t)stm32f4_eth_isr);
-    NVIC_EnableIRQ(ETH_IRQn);
-    __HAL_RCC_ETH_CLK_ENABLE();
-
-    ses->st_eth.Instance = ETH;
-    ses->st_eth.Init.MACAddr[1] = 2;
-#if 0
-    ses->st_eth.Init.Autonegotiation = ETH_AUTONEGOTIATION_ENABLE;
-#endif
-    ses->st_eth.Init.Speed = ETH_SPEED_100M;
-    ses->st_eth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
-    ses->st_eth.Init.PhyAddress = 0;
-    ses->st_eth.Init.RxMode = ETH_RXINTERRUPT_MODE;
-    ses->st_eth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
-    ses->st_eth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
-
-    return ERR_OK;
-}
-
-int
-stm32f4_eth_open(void)
-{
-    struct stm32f4_eth_state *ses = &stm32f4_eth_state;
-    struct netif *nif;
-    struct ip4_addr addr;
-
-    if (ses->cfg == NULL) {
-        return -1;
-    }
-
-    /*
-     * Register network interface with LwIP.
-     */
-    memset(&addr, 0, sizeof(addr));
-    nif = netif_add(&ses->nif, &addr, &addr, &addr, NULL, stm32f4_lwip_init,
-      ethernet_input);
-    assert(nif);
-    return 0;
-}