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, ®);
+ 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, ®);
+ }
+}
+
+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 |= (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, ®);
+ func("%d: %x (%d)\n", i, reg, rc);
+ }
+ for (i = 17; i <= 18; i++) {
+ rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, ®);
+ func("%d: %x (%d)\n", i, reg, rc);
+ }
+ for (i = 26; i <= 31; i++) {
+ rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, ®);
+ 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, ®value);
-
- 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, ®value);
-
- 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, ®value);
-
- /* 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, ®value);
-
- /* 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, ®value);
-
- /* 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, ®value);
-
- /* 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;
-}