[PATCH rtems-lwip v2] STM32 lwIP addition

Robin Mueller robin.mueller.m at gmail.com
Wed Apr 28 17:41:04 UTC 2021


This patch adds the STM32H7 / NUCLEO-H743ZI lwIP port.
It also improves the architecture to make integration
of new BSPs easier. The patch continues the wscript file to
allow installing the lwIP support similar to how a RTEMS
BSP is installed.

https://github.com/rmspacefish/rtems-stm32-lwip is a self-contained
repository to test the lwIP integration for the arm/stm32h7
and arm/nucleo-h743zi BSP. The repository README specifies
how to build the RTEMS lwIP support and install it at a specified
prefix location.

The STM32 port includes the LAN driver (lan8742.c), the
primary port functions in ethernetif.c and some application code
taken from CubeH7, which can serve as a starting point for
implementations and was also tailored to RTEMS.

The common source file were refactored to be more generic and independent
of the used BSP.

This patch includes corrections from the code review by Gedare Bloom.

Please note that any merges need to be held off until some licensing issues
with STM concerning the SLA0044 license on example files are resolved.
---
 .gitignore                                    |   6 +
 .gitmodules                                   |   1 +
 README.md                                     |  32 +
 lwip-to-rtems.py                              |   0
 lwip.py                                       | 182 ++++-
 .../drivers/{eth_lwip.c => rtems_lwip.c}      | 187 +++--
 .../drivers/{eth_lwip.h => rtems_lwip.h}      |  92 ++-
 .../{eth_lwip_default.h => rtems_lwip_conf.h} |  30 +-
 lwip/ports/drivers/stm32h7/app_dhcp.c         | 208 +++++
 lwip/ports/drivers/stm32h7/app_ethernet.c     | 191 +++++
 lwip/ports/drivers/stm32h7/ethernetif.c       | 748 ++++++++++++++++++
 .../stm32h7/include/rtems_lwip/app_dhcp.h     |  51 ++
 .../stm32h7/include/rtems_lwip/app_ethernet.h |  64 ++
 .../stm32h7/include/rtems_lwip/ethernetif.h   |  59 ++
 lwip/ports/drivers/stm32h7/lan8742.c          | 664 ++++++++++++++++
 lwip/ports/drivers/stm32h7/lan8742.h          | 448 +++++++++++
 lwip/ports/drivers/stm32h7/port_conf.h        |  44 ++
 .../stm32h7/template/lwipopts_template.h      | 292 +++++++
 .../include/rtems_lwip}/tms570_netif.h        |  31 +
 .../ports/drivers/{ => tms570}/phy_dp83848h.c |   0
 .../ports/drivers/{ => tms570}/phy_dp83848h.h |   0
 .../tms570/template/lwipopts_template.h       |  75 ++
 lwip/ports/drivers/{ => tms570}/ti_drv_emac.h |   0
 lwip/ports/drivers/{ => tms570}/ti_drv_mdio.h |   0
 lwip/ports/drivers/{ => tms570}/tms570_emac.h |   0
 .../ports/drivers/{ => tms570}/tms570_netif.c |  11 +-
 lwip/ports/os/rtems/arch/cc.h                 |   3 +
 lwip/ports/os/rtems/arch/sys_arch.c           |  31 +-
 lwip/ports/os/rtems/arch/sys_arch.h           |  18 +-
 lwip/ports/os/rtems/defaults/lwipopts.h       |  37 +
 lwip/src/include/lwip/sys.h                   |   1 -
 lwip/{ports/os => test}/lwipopts.h            |   0
 wscript                                       |   2 +
 33 files changed, 3348 insertions(+), 160 deletions(-)
 create mode 100644 README.md
 mode change 100755 => 100644 lwip-to-rtems.py
 rename lwip/ports/drivers/{eth_lwip.c => rtems_lwip.c} (56%)
 rename lwip/ports/drivers/{eth_lwip.h => rtems_lwip.h} (55%)
 rename lwip/ports/drivers/{eth_lwip_default.h => rtems_lwip_conf.h} (68%)
 create mode 100644 lwip/ports/drivers/stm32h7/app_dhcp.c
 create mode 100644 lwip/ports/drivers/stm32h7/app_ethernet.c
 create mode 100644 lwip/ports/drivers/stm32h7/ethernetif.c
 create mode 100644 lwip/ports/drivers/stm32h7/include/rtems_lwip/app_dhcp.h
 create mode 100644 lwip/ports/drivers/stm32h7/include/rtems_lwip/app_ethernet.h
 create mode 100644 lwip/ports/drivers/stm32h7/include/rtems_lwip/ethernetif.h
 create mode 100644 lwip/ports/drivers/stm32h7/lan8742.c
 create mode 100644 lwip/ports/drivers/stm32h7/lan8742.h
 create mode 100644 lwip/ports/drivers/stm32h7/port_conf.h
 create mode 100644 lwip/ports/drivers/stm32h7/template/lwipopts_template.h
 rename lwip/ports/drivers/{ => tms570/include/rtems_lwip}/tms570_netif.h (74%)
 rename lwip/ports/drivers/{ => tms570}/phy_dp83848h.c (100%)
 rename lwip/ports/drivers/{ => tms570}/phy_dp83848h.h (100%)
 create mode 100644 lwip/ports/drivers/tms570/template/lwipopts_template.h
 rename lwip/ports/drivers/{ => tms570}/ti_drv_emac.h (100%)
 rename lwip/ports/drivers/{ => tms570}/ti_drv_mdio.h (100%)
 rename lwip/ports/drivers/{ => tms570}/tms570_emac.h (100%)
 rename lwip/ports/drivers/{ => tms570}/tms570_netif.c (99%)
 create mode 100644 lwip/ports/os/rtems/defaults/lwipopts.h
 rename lwip/{ports/os => test}/lwipopts.h (100%)

diff --git a/.gitignore b/.gitignore
index 618d791..91a3a03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,10 @@
+# Python
 __pycache__
+
+# Waf
 .lock-waf*
 .waf*
+/*.pyc
+
+# Builds
 build/
diff --git a/.gitmodules b/.gitmodules
index 4ea46da..a98aac6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,4 @@
 [submodule "rtems_waf"]
 	path = rtems_waf
 	url = git://git.rtems.org/rtems_waf.git
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ebbef12
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+RTEMS lwIP Repository
+======
+
+This repository contains the RTEMS lwIP support and all available ports.
+Currently, the following RTEMS BSPs are supported:
+
+ - All `arm/tms*` BSPs.
+ - The `arm/stm32h7` and the `arm/nucleo-h743zi` BSP. An example application can be
+   found [here](https://github.com/rmspacefish/rtems-stm32-lwip).
+
+# Using this repository
+
+The repository contains the lwIP sources, the OS port for RTEMS and port files
+belonging to a RTEMS BSP.
+
+It is recommended that the user supplies the `lwipopts.h` configuration file. The port folders
+contain template option files to get started. The user can copy and rename this files into the
+application and then pass the include path to the build system using the `--lwip-opts` option.
+
+# Building with waf
+
+It is assumed that the path(s) containing the `lwipopts.h` file was stored in the environmental
+variable `LWIP_OPTS_PATH`, the install prefix is stored in the environmental
+variable `RTEMS_PREFIX` and the RTEMS BSP is stored inside `RTEMS_BSP`.
+The lwIP support can now be built like this:
+
+```sh
+./waf configure --prefix="$RTEMS_PREFIX" --lwip-opts="$LWIP_OPTS_PATH" --rtems-bsp="$RTEMS_BSP"
+./waf
+./waf install
+```
+
diff --git a/lwip-to-rtems.py b/lwip-to-rtems.py
old mode 100755
new mode 100644
diff --git a/lwip.py b/lwip.py
index a3eb7cb..56919d9 100644
--- a/lwip.py
+++ b/lwip.py
@@ -33,45 +33,163 @@ source_files = []
 driver_source = []
 include_files = {}
 
+DEFAULT_OPTIONS_PATH = "./lwip/ports/os/rtems/defaults"
+DEBUG_LWIP_WSCRIPT = False
+BUILD_SAMPLE_FILE = False
+RTEMS_LWIP_PORT_INC_FOLDER_NAME = "rtems_lwip"
+
+
+
+def options(opt):
+    opt.add_option(
+        "--lwip-opts",
+        default=DEFAULT_OPTIONS_PATH,
+        dest="lwipopts_path",
+        help="Path including the lwipopts.h file. If none is supplied, a default "
+             " configuration file will be used"
+    )
+
+
+def configure(conf):
+    conf.env.LWIPOPTS_PATH = conf.options.lwipopts_path
+    if(conf.env.LWIPOPTS_PATH == DEFAULT_OPTIONS_PATH):
+        print('No path for lwipopts.h file supplied, using default path %s' % DEFAULT_OPTIONS_PATH)
+    else:
+        print('Path(s) for lwIP options supplied: %s' % conf.env.LWIPOPTS_PATH)
+
+
 def build(bld):
-    arch_lib_path = rtems.arch_bsp_lib_path(bld.env.RTEMS_VERSION,
-                                            bld.env.RTEMS_ARCH_BSP)
+    arch_lib_path = rtems.arch_bsp_lib_path(
+        bld.env.RTEMS_VERSION, bld.env.RTEMS_ARCH_BSP
+    )
+    arch_inc_path = rtems.arch_bsp_include_path(
+        bld.env.RTEMS_VERSION, bld.env.RTEMS_ARCH_BSP
+    )
+
     with open('file-import.yaml', 'r') as cf:
         files = yaml.full_load(cf.read())
         for f in files['files-to-import']:
             if f[-2:] == '.c':
                 source_files.append(os.path.join('./lwip', f))
-        
-        for f in os.listdir('./lwip/ports/drivers'):
+
+    # Determine port sources and include path, if there are any
+    port_name = ""
+    generic_port_path = './lwip/ports/drivers'
+    if bld.env.RTEMS_BSP in ["nucleo-h743zi", "stm32h7"]:
+        port_name = "stm32h7"
+    elif "tms570" in bld.env.RTEMS_BSP:
+        port_name = "tms570"
+    driver_include_path = ""
+    if port_name != "":
+        port_path = './lwip/ports/drivers/%s' % port_name
+        driver_include_path = os.path.join(
+            port_path, 'include/%s' % RTEMS_LWIP_PORT_INC_FOLDER_NAME
+        )
+        for f in os.listdir(port_path):
             if f[-2:] == '.c':
-                driver_source.append(os.path.join('./lwip/ports/drivers', f))
+                driver_source.append(os.path.join(port_path, f))
+    else:
+        print("Port does not exist. Only compiling lwIP source files")
+
+    if DEBUG_LWIP_WSCRIPT:
+        print('Port sources: ')
+        print(driver_source)
+
+    os_inc_path = './lwip/ports/os/rtems/arch'
+
     source_files.append('./lwip/ports/os/rtems/arch/sys_arch.c')
-    
-    #source_files.append('./lwip/ports/port/sys_arch.c')
-    #source_files.append('./lwip/ports/port/perf.c')
-    #source_files.append('./lwip/ports/port/netif/fifo.c')
-    #source_files.append('./lwip/ports/port/netif/list.c')
-    #source_files.append('./lwip/ports/port/netif/pcapif.c')
-    #source_files.append('./lwip/ports/port/netif/sio.c')
-    #source_files.append('./lwip/ports/port/netif/tapif.c')
-
-    bld(features ='c',
+    source_files.append('./lwip/ports/drivers/rtems_lwip.c')
+    source_files.append(driver_source)
+
+    # Add the path containing the lwipopts.h file
+    options_include_path = bld.env.LWIPOPTS_PATH
+
+    if(options_include_path == ""):
+      print("Invalid options path, setting default path")
+      options_include_path = DEFAULT_OPTIONS_PATH
+
+    lwip_core_include_path = './lwip/src/include'
+    lwip_obj_includes = \
+        './include %s ./lwip/src/include lwip/ports/port/include ./lwip/ports/os ' \
+        './lwip/ports/drivers ./lwip/ports/os/rtems %s %s' \
+        % (lwip_core_include_path, options_include_path, driver_include_path)
+
+    if DEBUG_LWIP_WSCRIPT:
+        print('Include paths for lwIP: ')
+        print(lwip_obj_includes)
+
+    bld(
+        features='c',
         target='lwip_obj',
-        includes='./include ./lwip/src/include lwip/ports/port/include ./lwip/ports/os ./lwip/ports/drivers ./lwip/ports/os/rtems',
-        source=source_files,
+        includes=lwip_obj_includes,
+        source=source_files
+    )
+
+    bld(
+        features='c cstlib',
+        target='lwip',
+        use=['lwip_obj']
+     )
+
+    # Install static library
+    bld.install_files(os.path.join('${PREFIX}', arch_lib_path), ["liblwip.a"])
+
+    install_header_source = []
+    install_header_target = []
+
+    # Installation for the lwIP core header files
+    for root, dirnames, filenames in os.walk(lwip_core_include_path):
+        install_headers_source = [
+            os.path.join(root, file)
+            for file in filenames
+            if (file[-2:] == '.h')
+        ]
+        install_headers_target = os.path.relpath(root, lwip_core_include_path)
+        install_destination = os.path.join(bld.env.PREFIX, arch_inc_path, install_headers_target)
+        if DEBUG_LWIP_WSCRIPT:
+            print('Install Source: %s' % install_headers_source)
+        if DEBUG_LWIP_WSCRIPT:
+            print('Install Target: %s' % install_destination)
+        bld.install_files(install_destination, install_headers_source)
+
+    # Installation for the lwIP port header files
+    generic_port_include_files = os.listdir(generic_port_path)
+    install_headers_source = [
+        os.path.join(generic_port_path, file)
+        for file in generic_port_include_files
+        if (file[-2:] == '.h')
+    ]
+    if driver_include_path != "":
+        drv_include_files = os.listdir(driver_include_path)
+        install_headers_source += [
+            os.path.join(driver_include_path, file)
+            for file in drv_include_files
+            if (file[-2:] == '.h')
+        ]
+        install_destination = os.path.join(bld.env.PREFIX, arch_inc_path, 'rtems_lwip')
+        bld.install_files(install_destination, install_headers_source)
+
+    # Installation for OS abstraction layer
+    os_include_files = os.listdir(os_inc_path)
+    install_headers_source = [
+        os.path.join(os_inc_path, file)
+        for file in os_include_files
+        if (file[-2:] == '.h')
+    ]
+    install_destination = os.path.join(bld.env.PREFIX, arch_inc_path, 'arch')
+    bld.install_files(install_destination,  install_headers_source)
+
+    if BUILD_SAMPLE_FILE:
+        sample_inc = \
+            './include ./lwip/ports/os/rtems ./lwip/ports/os ./lwip/src/include ' \
+            './lwip/ports/os/rtems ./lwip/test/' \
+            + os.path.relpath(os.path.join(arch_lib_path,'include'))
+        bld.program(
+            features='c',
+            target='test01.exe',
+            source='./lwip/test/sample_app.c',
+            use='lwip',
+            lib=['rtemscpu', 'rtemsbsp', 'rtemstest', 'lwip'],
+            includes=sample_inc
         )
-#    bld(features ='c',
-#        target='lwip_drv_obj',
-#        includes='./ ../ ../../src/include ./include ./lwip/src/include ./lwip/ports/os/rtems ./lwip/ports/os ./lwip/ports/drivers ' + os.path.relpath(os.path.join(arch_lib_path,'include')),
-#        source=driver_source,
-#        )
-    bld(features='c cstlib',
-        target = 'lwip',
-        use=['lwip_obj'])
-
-    bld.program(features='c',
-                target='test01.exe',
-                source='./lwip/test/sample_app.c',
-                use='lwip',
-                lib=['rtemscpu', 'rtemsbsp', 'rtemstest', 'lwip'],
-                includes='./include ./lwip/ports/os/rtems ./lwip/ports/os ./lwip/src/include ./lwip/ports/os/rtems ./lwip/test/' + os.path.relpath(os.path.join(arch_lib_path,'include')))
+
diff --git a/lwip/ports/drivers/eth_lwip.c b/lwip/ports/drivers/rtems_lwip.c
similarity index 56%
rename from lwip/ports/drivers/eth_lwip.c
rename to lwip/ports/drivers/rtems_lwip.c
index b1ae4bb..0633605 100644
--- a/lwip/ports/drivers/eth_lwip.c
+++ b/lwip/ports/drivers/rtems_lwip.c
@@ -31,53 +31,47 @@
  * Based on work of Carlos Jenkins, Rostislav Lisovy, Jan Dolezal
  */
 
-//#define DEBUG 1
-#include "lwip/tcpip.h" /* includes - lwip/opt.h, lwip/api_msg.h, lwip/netifapi.h, lwip/pbuf.h, lwip/api.h, lwip/sys.h, lwip/timers.h, lwip/netif.h */
+#include "rtems_lwip.h"
+#include "rtems_lwip_conf.h"
+
+#include "lwip/init.h"
 #include "lwip/stats.h"
 #include "lwip/dhcp.h"
+#include "netif/ethernet.h"
+
+#if LWIP_NETIF_API == 1
 #include "lwip/netifapi.h"
-#include "netif/etharp.h" /* includes - lwip/ip.h, lwip/netif.h, lwip/ip_addr.h, lwip/pbuf.h */
-#include "eth_lwip_default.h"
-#include "eth_lwip.h"
-#include "tms570_netif.h"
-#include <stdio.h>
+#endif
 
-/* The lwIP network interface structure for the Ethernet EMAC. */
-#ifndef MAX_EMAC_INSTANCE
-#define MAX_EMAC_INSTANCE           1
-#endif /*MAX_EMAC_INSTANCE*/
+#if NO_SYS == 0
+#include "lwip/tcpip.h"
+#endif
+
+#include <stdio.h>
 
 #define SUCCESS ERR_OK
 #define FAILURE ERR_IF
 
-static struct netif eth_lwip_netifs[MAX_EMAC_INSTANCE];
-static void eth_lwip_conv_IP_decimal_Str(ip_addr_t ip, uint8_t *ipStr);
+/* Assigned in specific port */
+extern netif_init_fn eth_lwip_init_fnc;
 
+/* The lwIP network interface structure for the Ethernet EMAC. */
+#ifndef MAX_EMAC_INSTANCE
+#define MAX_EMAC_INSTANCE           1
+#endif /*MAX_EMAC_INSTANCE*/
 
-void
-eth_lwip_get_dhcp_info(void)
-{
-  struct netif *netif = eth_lwip_get_netif(0);
-
-  if (dhcp_supplied_address(netif)) {
-    uint8_t ipString[16]; // FIXME change the functions to use char
-    eth_lwip_conv_IP_decimal_Str(netif->ip_addr, ipString);
-    printf("Address: %s\n", ipString);
-    eth_lwip_conv_IP_decimal_Str(netif->netmask, ipString);
-    printf("Netmask: %s\n", ipString);
-    eth_lwip_conv_IP_decimal_Str(netif->gw, ipString);
-    printf("Gateway: %s\n", ipString);
-  } else {
-    printf("dhcp not bound\n");
-  }
-}
+struct netif eth_lwip_netifs[MAX_EMAC_INSTANCE];
 
 int8_t
-eth_lwip_init(uint8_t *mac_addr)
+rtems_lwip_init(uint8_t *mac_addr, netif_status_callback_fn netif_status_cb)
 {
   unsigned int instance_number = 0;
-  int8_t retVal = SUCCESS;
+  int8_t retval = SUCCESS;
 
+#if NO_SYS == 1
+  /* Initialize the lwIP stack */
+  lwip_init();
+#endif
 
   ip4_addr_t ip_addr;
   ip4_addr_t net_mask;
@@ -89,63 +83,78 @@ eth_lwip_init(uint8_t *mac_addr)
   if (mac_addr == NULL)
     mac_addr = default_mac;             /* use default MAC */
 
-  eth_lwip_set_hwaddr(netif, mac_addr);
+  rtems_lwip_set_hwaddr(netif, mac_addr);
+
+#if NO_SYS == 0
   tcpip_init(NULL, NULL);
+#endif
 
-#if STATIC_IP_ADDRESS
-  ip_addr.addr = htonl(ETH_IP_ADDR);
-  net_mask.addr = htonl(ETH_NETMASK);
-  gw_addr.addr = htonl(ETH_GW);
+  rtems_lwip_determine_static_ipv4_address(&ip_addr, &net_mask, &gw_addr);
+
+  netif_input_fn netif_input_fnc = NULL;
+#if NO_SYS == 1
+  netif_input_fnc = &ethernet_input;
 #else
-  ip_addr.addr = 0;
-  net_mask.addr = 0;
-  gw_addr.addr = 0;
+  netif_input_fnc = &tcpip_input;
 #endif
 
   netif_tmp = netif_add(netif, &ip_addr, &net_mask, &gw_addr,
-                        NULL, ETH_LWIP_INIT_NETIF_FNC, tcpip_input);
+                        NULL, eth_lwip_init_fnc, netif_input_fnc);
 
   if (netif_tmp == NULL)
     return NETIF_ADD_ERR;
 
   netif_set_default(netif);
+
+#if LWIP_NETIF_API == 1
   netifapi_netif_set_up(netif);
-#if !STATIC_IP_ADDRESS
+#endif
+
+#if LWIP_NETIF_LINK_CALLBACK
+  if(netif_status_cb != NULL) {
+    netif_status_cb(netif);
+    netif_set_link_callback(netif, netif_status_cb);
+  }
+#endif
+
+#if !STATIC_IP_ADDRESS && NO_SYS == 0 && LWIP_NETIF_API == 1
   netifapi_dhcp_start(netif);
 #endif
 
-  return retVal;
+  return retval;
+}
+
+void
+rtems_lwip_print_dhcp_info(void)
+{
+  struct netif *netif = rtems_lwip_get_netif(0);
+
+  if (dhcp_supplied_address(netif)) {
+    printf("DHCP information: \n\r");
+    printf("Address: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
+    printf("Netmask: %s\n\r", ip4addr_ntoa(netif_ip4_netmask(netif)));
+    printf("Gateway: %s\n\r", ip4addr_ntoa(netif_ip4_gw(netif)));
+  } else {
+    printf("DHCP not bound\n\r");
+  }
 }
 
 int
-eth_lwip_get_netif_status_cmd(int argc, char *arg[])
+rtems_lwip_get_netif_status_cmd(int argc, char *arg[])
 {
   stats_display();
   return 0;
 }
 
 struct netif *
-eth_lwip_get_netif(uint32_t instance_number)
+rtems_lwip_get_netif(uint32_t instance_number)
 {
-  if (instance_number >= MAX_EMAC_INSTANCE)
+  if (instance_number >= MAX_EMAC_INSTANCE) {
     return NULL;
+  }
   return &eth_lwip_netifs[instance_number];
 }
 
-static void
-eth_lwip_conv_IP_decimal_Str(ip_addr_t ip, uint8_t *ipStr)
-{
-  uint32_t addr;
- #if LWIP_IPV6
-  addr = ip.u_addr.ip4.addr;
- #else
-  addr = ip.addr;
- #endif
-
-  snprintf((char *)ipStr, 16, "%lu.%lu.%lu.%lu",
-           (addr >> 24), ((addr >> 16) & 0xff), ((addr >> 8) & 0xff), (addr & 0xff));
-}
-
 /*
 * Function to set the MAC address to the interface
 * @param   inst_num the instance number
@@ -153,7 +162,7 @@ eth_lwip_conv_IP_decimal_Str(ip_addr_t ip, uint8_t *ipStr)
 * @note    mac_addr[0] is considered MSB
 */
 void
-eth_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr)
+rtems_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr)
 {
   int i;
 
@@ -171,18 +180,62 @@ eth_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr)
 }
 
 void
-eth_lwip_get_hwaddr_str(struct netif *netif, uint8_t *macStr)
+rtems_lwip_get_hwaddr_str(struct netif *netif, uint8_t *mac_str)
 {
   uint8_t index, outindex = 0;
   char ch;
 
   for (index = 0; index < netif->hwaddr_len; index++) {
-    if (index)
-      macStr[outindex++] = ':';
+    if (index) {
+      mac_str[outindex++] = ':';
+    }
     ch = (netif->hwaddr[index] >> 4);
-    macStr[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
+    mac_str[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
     ch = (netif->hwaddr[index] & 0xf);
-    macStr[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
+    mac_str[outindex++] = (ch < 10) ? (ch + '0') : (ch - 10 + 'A');
   }
-  macStr[outindex] = 0;
+  mac_str[outindex] = 0;
+}
+
+void
+rtems_lwip_convert_ip_to_decimal_str(ip_addr_t ip, char *ip_str)
+{
+  uint32_t addr;
+ #if LWIP_IPV6
+  addr = ip.u_addr.ip4.addr;
+ #else
+  addr = ip.addr;
+ #endif
+
+  snprintf((char *)ip_str, 16, "%lu.%lu.%lu.%lu",
+           (addr >> 24), ((addr >> 16) & 0xff), ((addr >> 8) & 0xff), (addr & 0xff));
+}
+
+void rtems_lwip_determine_static_ipv4_address(ip4_addr_t* ip_addr, ip4_addr_t* netmask,
+        ip4_addr_t* gw_addr) {
+#if STATIC_IP_ADDRESS == 1
+
+#if CALCULATE_ETH_IP_ADDR == 1
+  IP_ADDR4(ip_addr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+#else
+  ip_addr->addr = htonl(ETH_IP_ADDR);
+#endif
+
+#if CALCULATE_ETH_NETMASK == 1
+  IP_ADDR4(net_mask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+#else
+  net_mask->addr = htonl(ETH_NETMASK);
+#endif
+
+#if CALCULATE_GW_ADDRESS == 1
+  IP_ADDR4(gw_addr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+#else
+  gw_addr->addr = htonl(ETH_GW);
+#endif
+
+#else
+  ip_addr_set_zero_ip4(ip_addr);
+  ip_addr_set_zero_ip4(netmask);
+  ip_addr_set_zero_ip4(gw_addr);
+#endif /* STATIC_IP_ADDRESS == 0 */
 }
diff --git a/lwip/ports/drivers/eth_lwip.h b/lwip/ports/drivers/rtems_lwip.h
similarity index 55%
rename from lwip/ports/drivers/eth_lwip.h
rename to lwip/ports/drivers/rtems_lwip.h
index a9c0325..8802e09 100644
--- a/lwip/ports/drivers/eth_lwip.h
+++ b/lwip/ports/drivers/rtems_lwip.h
@@ -34,67 +34,85 @@
 #ifndef __ETH_LWIP_H
 #define __ETH_LWIP_H
 
+#include "lwip/netif.h"
+#include "rtems_lwip_conf.h"
+
 #include <stdio.h>
 #include <stdbool.h>
-#include "lwip/netif.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /**
- * While scanning phy addresses no alive phy was found.
- * Return value of rpp_eth_hw_init() function.
+ * LwIP netif couldn't be added, it is likely that there was an error during initialization of the hardware.
  */
-#define NO_PHY_ALIVE             -1
+#define NETIF_ADD_ERR            -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
+
 /**
- * Scanning default phy address, it was found it's not alive.
- * Return value of rpp_eth_hw_init() function.
+ * @brief   RTEMS lwIP initialization function.
+ *
+ * Call this method before using this module. This function also takes care of initializing
+ * the lwIP stack by calling lwip_init.
+ * @param   mac_addr            Can be set to NULL to use default mac address
+ * @param   netif_status_cb     Callback function which will be called if the network
+ *                              link status changes
+ * @return
+ *  - SUCCESS if initialization successful.\n
+ *  - NETIF_ADD_ERR Error adding net interface.
  */
-#define DFLT_PHY_NOT_ALIVE       -1
+int8_t rtems_lwip_init(uint8_t *mac_addr, netif_status_callback_fn netif_status_cb);
+
 /**
- * When setting autonegotiation parameters to EMAC module, there was found impossible mode (usually on timeout of autonegotiation).
- * Return value of rpp_eth_hw_init_postInit() function.
+ * @brief   Access to the net interface instances
  */
-#define UNKN_DUPLEX_MODE         -2 /* this could mean that autonegotiation was not completed yet */
+struct netif *rtems_lwip_get_netif(uint32_t instance_number);
+
 /**
- * Phy is down error.
- * Return value of rpp_eth_init_postInit() function.
+ * @brief   Print information about the assigned DHCP address.
  */
-#define PHY_LINK_DOWN            -3
+void rtems_lwip_print_dhcp_info(void);
 
 /**
- * LwIP netif couldn't be added, it is likely that there was an error during initialization of the hardware.
+ * Convert the given IP to its string representation
+ * @param ip
+ * @param ip_str
  */
-#define NETIF_ADD_ERR            -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
+void rtems_lwip_convert_ip_to_decimal_str(ip_addr_t ip, char *ip_str);
+
 /**
- * Memory requirements couldn't be satisfied.
+ * Get the netif status by calling the lwIP  stats_display function
+ * @param argc
+ * @param arg
+ * @return
  */
-#define DHCP_MEM_ERR             -11
+int rtems_lwip_get_netif_status_cmd(int argc, char *arg[]);
 
 /**
- * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
+ * Set the hardware (MAC) address
+ * @param netif
+ * @param mac_addr
  */
-#define MAC_BIG_LETTERS           1
+void rtems_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr);
 
 /**
- * ETH module system startup initialization.
- *
- * Call this method before using this module.
- * This method starts autonegotiation and doesn't check for end of autoneg.
- * When eth module is about to be used, you have to run rpp_eth_init_postInit()
- * first and you should check whether link is up.
- *
- * @return SUCCESS if initialization successful.\n
- *         FAILURE if module already initialized.
+ * Get the hardware (MAC) address
+ * @param netif
+ * @param mac_addr
  */
-int8_t eth_lwip_init(uint8_t *mac_addr);
-void eth_lwip_get_dhcp_info(void);
-int eth_lwip_get_netif_status_cmd(int argc, char *arg[]);
-void eth_lwip_set_hwaddr(struct netif *netif, uint8_t *mac_addr);
-void eth_lwip_get_hwaddr_str(struct netif *netif, uint8_t *macStr);
-struct netif *eth_lwip_get_netif(uint32_t instance_number);
-
-
-
+void rtems_lwip_get_hwaddr_str(struct netif *netif, uint8_t *mac_str);
 
+/**
+ * @brief   Determines a static IP address from the configuration files.
+ * @param ip_addr
+ * @param netmask
+ * @param gw
+ */
+void rtems_lwip_determine_static_ipv4_address(ip4_addr_t* ip_addr, ip4_addr_t* netmask,
+        ip4_addr_t* gw);
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* __ETH_LWIP_H */
diff --git a/lwip/ports/drivers/eth_lwip_default.h b/lwip/ports/drivers/rtems_lwip_conf.h
similarity index 68%
rename from lwip/ports/drivers/eth_lwip_default.h
rename to lwip/ports/drivers/rtems_lwip_conf.h
index 6194d06..85e48f3 100644
--- a/lwip/ports/drivers/eth_lwip_default.h
+++ b/lwip/ports/drivers/rtems_lwip_conf.h
@@ -1,14 +1,8 @@
 #ifndef __ETH_LWIP_DEFAULT_H
 #define __ETH_LWIP_DEFAULT_H
 
-/* #define DEBUG 1 */
-/* #define STATIC_IP_ADDRESS 1 */
-
-void tms570_eth_memp_avaible(int type);
-
-#define ETH_LWIP_INIT_NETIF_FNC tms570_eth_init_netif
-/*called from memp_free() when a memp pool was empty and an item is now available*/
-#define LWIP_HOOK_MEMP_AVAILABLE tms570_eth_memp_avaible
+#include "lwipopts.h"
+#include "lwip/etharp.h"
 
 /* this MAC address is used when user put NULL on the right place when calling postInit function */
 /**
@@ -20,29 +14,43 @@ void tms570_eth_memp_avaible(int type);
 #define ETH_MAC_ADDR             { 0x12 /* Unicast, Locally administered */, 0x34, 0x56, 0x78, 0x9A, 0xBC }
 #endif
 
-#if STATIC_IP_ADDRESS
-
 /**
  * When static IP is configured in lwipopts.h, this IP address is used for interface.
  */
 #ifndef ETH_IP_ADDR
+
+#if defined(IP_ADDR0) && defined(IP_ADDR1) && defined(IP_ADDR2) && defined(IP_ADDR3)
+#define CALCULATE_ETH_IP_ADDR
+#else
 #define ETH_IP_ADDR               0xC0A8F701 /* 192.168.247.1  */
 #endif
 
+#endif
+
 /**
  * When static IP is configured in lwipopts.h, this NETMASK address is used for interface.
  */
 #ifndef ETH_NETMASK
+
+#if defined(NETMASK_ADDR0) && defined(NETMASK_ADDR1) && defined(NETMASK_ADDR2) && defined(NETMASK_ADDR3)
+#define CALCULATE_ETH_NETMASK
+#else
 #define ETH_NETMASK               0xFFFFFF00 /* 255.255.255.0  */
 #endif
 
+#endif
+
 /**
  * When static IP is configured in lwipopts.h, this Gateway address is used for interface.
  */
 #ifndef ETH_GW
+
+#if defined(GW_ADDR0) && defined(GW_ADDR1) && defined(GW_ADDR2) && defined(GW_ADDR3)
+#define CALCULATE_GW_ADDRESS
+#else
 #define ETH_GW                    0xC0A8F7FE /* 192.168.247.254*/
 #endif
 
-#endif /* STATIC_IP_ADDRESS */
+#endif /* ETH_GW */
 
 #endif /* __ETH_LWIP_DEFAULT_H */
diff --git a/lwip/ports/drivers/stm32h7/app_dhcp.c b/lwip/ports/drivers/stm32h7/app_dhcp.c
new file mode 100644
index 0000000..0685670
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/app_dhcp.c
@@ -0,0 +1,208 @@
+/* Includes ------------------------------------------------------------------*/
+#include "app_dhcp.h"
+#include "port_conf.h"
+#include "ethernetif.h"
+#include "stm32h7xx_hal.h"
+#include "lwip/opt.h"
+#include "lwip/dhcp.h"
+#include "lwip/ip_addr.h"
+#include "rtems_lwip.h"
+#include "rtems_lwip_conf.h"
+
+#if NO_SYS == 0
+#include "lwip/sys.h"
+#endif
+#include <sys/unistd.h>
+
+#if LWIP_DHCP
+#ifndef MAX_DHCP_TRIES
+#define MAX_DHCP_TRIES  4
+#endif /* MAX_DHCP_TRIES */
+
+
+#if NO_SYS == 1
+static uint32_t DHCPfineTimer = 0;
+
+#endif /* NO_SYS == 1*/
+
+static void dhcp_thread(void* argument);
+
+LwipThreadArgs dhcp_args;
+uint8_t DHCP_state = DHCP_START;
+
+#if NO_SYS == 0
+void rtems_lwip_start_dhcp_thread(uint32_t task_interval_ms,
+    size_t task_stack, uint8_t task_priority) {
+  dhcp_args.netif = rtems_lwip_get_netif(0);
+  dhcp_args.task_interval_ms = task_interval_ms;
+  sys_thread_new("DHCP", dhcp_thread, (void*) &dhcp_args, task_stack, task_priority);
+}
+#endif /* NO_SYS == 0 */
+
+/**
+ * @brief  This is the thread dedicated to DHCP handling
+ * @param  argument: network interface
+ * @retval None
+ */
+void dhcp_thread(void* argument)
+{
+  ip_addr_t ipaddr;
+  ip_addr_t netmask;
+  ip_addr_t gw;
+  struct dhcp *dhcp = NULL;
+  LwipThreadArgs* args = (LwipThreadArgs*) argument;
+  if(args == NULL) {
+    printf("dhcp_thread: Passed arguments are invalid!\n\r");
+    exit(1);
+  }
+
+  struct netif* netif = args->netif;
+  if(netif == NULL) {
+    printf("dhcp_thread: Passed netif is invalid!\n\r");
+    exit(1);
+  }
+
+  if(args->task_interval_ms == 0) {
+    printf("dhcp_thread: Invalid task interval!\n\r");
+    exit(1);
+  }
+
+  for (;;) {
+    switch (DHCP_state) {
+    case DHCP_START: {
+      ip_addr_set_zero_ip4(&netif->ip_addr);
+      ip_addr_set_zero_ip4(&netif->netmask);
+      ip_addr_set_zero_ip4(&netif->gw);
+      DHCP_state = DHCP_WAIT_ADDRESS;
+
+      dhcp_start(netif);
+    }
+    break;
+    case DHCP_WAIT_ADDRESS: {
+      if (dhcp_supplied_address(netif)) {
+        DHCP_state = DHCP_ADDRESS_ASSIGNED;
+#if RTEMS_LWIP_DHCP_PRINTOUT == 1
+        printf("IP address assigned by a DHCP server: %s\n\r",
+            ip4addr_ntoa(netif_ip4_addr(netif)));
+#endif
+      }
+      else {
+        dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
+
+        /* DHCP timeout */
+        if (dhcp->tries > MAX_DHCP_TRIES) {
+          DHCP_state = DHCP_TIMEOUT;
+#if RTEMS_LWIP_DHCP_PRINTOUT == 1
+          uint8_t iptxt[20];
+          sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+          printf("DHCP timeout\n\r");
+          printf("Setting static IP address %s..\n\r", iptxt);
+#endif
+          /* Static address used */
+          rtems_lwip_determine_static_ipv4_address(&ipaddr, &netmask, &gw);
+          netif_set_addr(netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw));
+        }
+      }
+    }
+    break;
+    case DHCP_LINK_DOWN: {
+      DHCP_state = DHCP_OFF;
+    }
+    break;
+    default: break;
+    }
+
+    usleep(args->task_interval_ms * 1000);
+  }
+}
+
+#if NO_SYS == 1
+
+void DHCP_Process(struct netif *netif);
+
+/**
+ * @brief  DHCP periodic check
+ * @param  netif
+ * @retval None
+ */
+void dhcp_periodic_handle(struct netif *netif)
+{
+  /* Fine DHCP periodic process every 500ms */
+  if (HAL_GetTick() - DHCPfineTimer >= RTEMS_LWIP_DHCP_TASK_INTERVAL_MS) {
+    DHCPfineTimer = HAL_GetTick();
+    /* process DHCP state machine */
+    DHCP_Process(netif);
+  }
+}
+
+/**
+ * @brief  DHCP_Process_Handle
+ * @param  None
+ * @retval None
+ */
+void DHCP_Process(struct netif *netif)
+{
+  ip_addr_t ipaddr;
+  ip_addr_t netmask;
+  ip_addr_t gw;
+  struct dhcp *dhcp = NULL;
+  switch (DHCP_state) {
+  case DHCP_START: {
+    ip_addr_set_zero_ip4(&netif->ip_addr);
+    ip_addr_set_zero_ip4(&netif->netmask);
+    ip_addr_set_zero_ip4(&netif->gw);
+    dhcp_start(netif);
+    DHCP_state = DHCP_WAIT_ADDRESS;
+  }
+  break;
+
+  case DHCP_WAIT_ADDRESS: {
+    if (dhcp_supplied_address(netif)) {
+      DHCP_state = DHCP_ADDRESS_ASSIGNED;
+      printf("IP address assigned by a DHCP server: %s\n\r", ip4addr_ntoa(netif_ip4_addr(netif)));
+    }
+    else
+    {
+      dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
+
+      /* DHCP timeout */
+      if (dhcp->tries > MAX_DHCP_TRIES)
+      {
+        DHCP_state = DHCP_TIMEOUT;
+
+        uint8_t iptxt[20];
+        sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+        printf("DHCP timeout\n\r");
+        printf("Setting static IP address %s..\n\r", iptxt);
+        /* Static address used */
+        rtems_lwip_determine_static_ipv4_address(&ipaddr, &netmask, &gw);
+        netif_set_addr(netif, &ipaddr, &netmask, &gw);
+
+      }
+    }
+  }
+  break;
+  case DHCP_LINK_DOWN: {
+    /* Stop DHCP */
+    //dhcp_release_and_stop(netif);
+    DHCP_state = DHCP_OFF;
+  }
+  break;
+  default: break;
+  }
+}
+
+#endif /* NO_SYS == 1 */
+
+void set_dhcp_state(uint8_t new_state)
+{
+  DHCP_state = new_state;
+}
+
+uint8_t get_dhcp_state()
+{
+  return DHCP_state;
+}
+
+#endif  /* LWIP_DHCP */
+
diff --git a/lwip/ports/drivers/stm32h7/app_ethernet.c b/lwip/ports/drivers/stm32h7/app_ethernet.c
new file mode 100644
index 0000000..0536886
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/app_ethernet.c
@@ -0,0 +1,191 @@
+/**
+  ******************************************************************************
+  * @file    LwIP/LwIP_HTTP_Server_Netconn_RTOS/Src/app_ethernet.c 
+  * @author  MCD Application Team
+  * @brief   Ethernet specefic module
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under Ultimate Liberty license
+  * SLA0044, the "License"; You may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at:
+  *                             www.st.com/SLA0044
+  *
+  ******************************************************************************
+  */
+/* Includes ------------------------------------------------------------------*/
+#include "rtems_lwip_conf.h"
+#include "rtems_lwip.h"
+#include "stm32h7/lan8742.h"
+#include "stm32h7xx_hal.h"
+#include "lwip/opt.h"
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#endif
+
+#if NO_SYS == 0
+#include "lwip/sys.h"
+#endif
+
+#include "app_ethernet.h"
+#include "app_dhcp.h"
+#include "ethernetif.h"
+
+/* Private typedef -----------------------------------------------------------*/
+LwipThreadArgs linkArgs;
+
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+#if NO_SYS == 1
+uint32_t ethernet_link_timer = 0;
+#endif
+
+/* Private function prototypes -----------------------------------------------*/
+#if LWIP_DHCP
+void set_dhcp_state(uint8_t new_state);
+#endif
+static void ethernet_link_thread( void* argument );
+lan8742_Object_t* get_lan_phy_handle();
+ETH_HandleTypeDef* get_eth_handle();
+
+/* Private functions ---------------------------------------------------------*/
+/**
+  * @brief  Notify the User about the nework interface config status 
+  * @param  netif: the network interface
+  * @retval None
+  */
+void ethernet_link_status_updated(struct netif *netif) 
+{
+  if (netif_is_up(netif)) {
+#if LWIP_DHCP
+    printf("Ethernet link up. Setting DHCP state..\n\r");
+    /* Update DHCP state machine */
+    set_dhcp_state(DHCP_START);
+#endif /* LWIP_DHCP */
+  }
+  else {
+#if LWIP_DHCP
+    printf("Ethernet link down. Setting DHCP state..\n\r");
+    /* Update DHCP state machine */
+    set_dhcp_state(DHCP_LINK_DOWN);
+#endif /* LWIP_DHCP */
+  } 
+}
+
+#if LWIP_NETIF_LINK_CALLBACK == 1 && NO_SYS == 1
+/**
+  * @brief  Ethernet Link periodic check
+  * @param  netif
+  * @retval None
+  */
+void ethernet_link_periodic_handle(struct netif *netif)
+{
+  uint32_t time_now = HAL_GetTick();
+  /* Ethernet Link every 100ms */
+  if (time_now - ethernet_link_timer >= 100) {
+    ethernet_link_timer = time_now;
+    ethernet_link_check_state(netif);
+  }
+}
+#endif
+
+#if NO_SYS == 0
+
+void rtems_lwip_start_link_thread(uint32_t task_interval_ms,
+    size_t task_stack, uint8_t task_priority) {
+  linkArgs.netif = rtems_lwip_get_netif(0);
+  linkArgs.task_interval_ms = task_interval_ms;
+  sys_thread_new("LINK", ethernet_link_thread, (void*) &linkArgs, task_stack, task_priority);
+}
+
+#endif
+
+/**
+  * @brief  Check the ETH link state and update netif accordingly.
+  * @param  argument: netif
+  * @retval None
+  */
+void ethernet_link_thread( void* argument )
+{
+  ETH_MACConfigTypeDef MACConf;
+  int32_t PHYLinkState;
+  uint32_t linkchanged = 0, speed = 0, duplex =0;
+  LwipThreadArgs* args = (LwipThreadArgs*) argument;
+  if(args == NULL) {
+    printf("ethernet_link_thread: Passed arguments are invalid!\n\r");
+    exit(1);
+  }
+
+  struct netif *netif = args->netif;
+  if(netif == NULL) {
+    printf("ethernet_link_thread: Passed netif is invalid!\n\r");
+    exit(1);
+  }
+
+  if(args->task_interval_ms == 0) {
+    printf("ethernet_link_thread: Invalid task interval!\n\r");
+    exit(1);
+  }
+
+  lan8742_Object_t* lan = get_lan_phy_handle();
+  ETH_HandleTypeDef* eth = get_eth_handle();
+  for(;;) {
+
+    PHYLinkState = LAN8742_GetLinkState(lan);
+
+    if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) {
+      HAL_ETH_Stop_IT(eth);
+      netif_set_down(netif);
+      netif_set_link_down(netif);
+    }
+    else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) {
+      switch (PHYLinkState) {
+      case LAN8742_STATUS_100MBITS_FULLDUPLEX: {
+        duplex = ETH_FULLDUPLEX_MODE;
+        speed = ETH_SPEED_100M;
+        linkchanged = 1;
+        break;
+      }
+      case LAN8742_STATUS_100MBITS_HALFDUPLEX: {
+        duplex = ETH_HALFDUPLEX_MODE;
+        speed = ETH_SPEED_100M;
+        linkchanged = 1;
+        break;
+      }
+      case LAN8742_STATUS_10MBITS_FULLDUPLEX: {
+        duplex = ETH_FULLDUPLEX_MODE;
+        speed = ETH_SPEED_10M;
+        linkchanged = 1;
+        break;
+      }
+      case LAN8742_STATUS_10MBITS_HALFDUPLEX: {
+        duplex = ETH_HALFDUPLEX_MODE;
+        speed = ETH_SPEED_10M;
+        linkchanged = 1;
+        break;
+      }
+      default:
+        break;
+      }
+
+      if(linkchanged) {
+        /* Get MAC Config MAC */
+        HAL_ETH_GetMACConfig(eth, &MACConf);
+        MACConf.DuplexMode = duplex;
+        MACConf.Speed = speed;
+        HAL_ETH_SetMACConfig(eth, &MACConf);
+        HAL_ETH_Start_IT(eth);
+        netif_set_up(netif);
+        netif_set_link_up(netif);
+      }
+    }
+
+    usleep(args->task_interval_ms * 1000);
+  }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/lwip/ports/drivers/stm32h7/ethernetif.c b/lwip/ports/drivers/stm32h7/ethernetif.c
new file mode 100644
index 0000000..61014df
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/ethernetif.c
@@ -0,0 +1,748 @@
+/**
+  ******************************************************************************
+  * @file    LwIP/LwIP_HTTP_Server_Netconn_RTOS/Src/ethernetif.c
+  * @author  MCD Application Team
+  * @brief   This file implements Ethernet network interface drivers for lwIP
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under Ultimate Liberty license
+  * SLA0044, the "License"; You may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at:
+  *                             www.st.com/SLA0044
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+#include "port_conf.h"
+#include "lwip/timeouts.h"
+#include "netif/ethernet.h"
+#include "netif/etharp.h"
+#include "lwip/stats.h"
+#include "lwip/snmp.h"
+#include "lwip/tcpip.h"
+#include "ethernetif.h"
+
+#include "lan8742.h"
+#include <string.h>
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define DMA_DESCRIPTOR_ALIGNMENT                ( 0x20 )
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 's'
+#define IFNAME1 't'
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* 
+ at Note: This interface is implemented to operate in zero-copy mode only:
+        - Rx buffers are allocated statically and passed directly to the LwIP stack,
+          they will return back to ETH DMA after been processed by the stack.
+        - Tx Buffers will be allocated from LwIP stack memory heap, 
+          then passed to ETH HAL driver.
+
+ at Notes: 
+  1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4, 
+       to customize it please redefine ETH_RX_DESC_CNT in stm32xxxx_hal_conf.h
+  1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4, 
+       to customize it please redefine ETH_TX_DESC_CNT in stm32xxxx_hal_conf.h
+
+  2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT
+  2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
+       passed to ETH DMA in the init field (EthHandle.Init.RxBuffLen)
+  2.c  The RX Ruffers addresses and sizes must be properly defined to be aligned
+       to L1-CACHE line size (32 bytes).
+*/
+
+#ifdef __rtems__
+netif_init_fn eth_lwip_init_fnc = &ethernetif_init;
+
+/* Put into special RTEMS section and align correctly */
+ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".bsp_nocache"), __aligned__(DMA_DESCRIPTOR_ALIGNMENT))); /* Ethernet Rx DMA Descriptors */
+/* Put into special RTEMS section and align correctly */
+ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]  __attribute__((section(".bsp_nocache"), __aligned__(DMA_DESCRIPTOR_ALIGNMENT)));  /* Ethernet Tx DMA Descriptors */
+/* Ethernet Receive Buffers. Just place somewhere is BSS instead of explicitely placing it */
+uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE] RTEMS_ALIGNED(DMA_DESCRIPTOR_ALIGNMENT);
+#endif /* __rtems__ */
+
+ETH_HandleTypeDef EthHandle;
+ETH_TxPacketConfig TxConfig; 
+
+lan8742_Object_t LAN8742;
+
+#if NO_SYS == 0
+sys_sem_t RxPktSemaphore; /* Semaphore to signal incoming packets */
+#endif
+
+/* Private function prototypes -----------------------------------------------*/
+#if !STATIC_IP_ADDRESS && NO_SYS == 0 && LWIP_NETIF_API == 1
+void set_dhcp_state(uint8_t new_state);
+#endif
+
+uint8_t determine_mpu_region_size_select(size_t lwip_heap_size);
+static void low_level_init(struct netif *netif);
+static err_t low_level_output(struct netif *netif, struct pbuf *p);
+void ethernet_link_check_state(struct netif *netif);
+
+void pbuf_free_custom(struct pbuf *p);
+
+int32_t ETH_PHY_IO_Init(void);
+int32_t ETH_PHY_IO_DeInit (void);
+int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
+int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
+int32_t ETH_PHY_IO_GetTick(void);
+
+
+lan8742_IOCtx_t  LAN8742_IOCtx = {ETH_PHY_IO_Init,
+                               ETH_PHY_IO_DeInit,
+                               ETH_PHY_IO_WriteReg,
+                               ETH_PHY_IO_ReadReg,
+                               ETH_PHY_IO_GetTick};
+
+LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(struct pbuf_custom), "Zero-copy RX PBUF pool");
+
+/* Private functions ---------------------------------------------------------*/
+/*******************************************************************************
+                       LL Driver Interface ( LwIP stack --> ETH) 
+*******************************************************************************/
+
+/**
+  * @brief 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));
+
+#ifdef __rtems__
+#if RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU == 1
+  mpu_config_tx_buffers(LWIP_RAM_HEAP_POINTER, MEM_SIZE);
+#endif /* RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU == 1 */
+#endif /* __rtems__ */
+
+#if LWIP_NETIF_HOSTNAME
+  /* Initialize interface hostname */
+  netif->hostname = "lwip";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+#if NO_SYS == 0
+  /*
+   * Initialize the snmp variables and counters inside the struct netif.
+   * The last argument should be replaced with your link speed, in units
+   * of bits per second.
+   */
+  MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
+#endif
+
+  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;
+
+  /* This is already done by the generic driver, so the internal state machine is set accordingly */
+#if !STATIC_IP_ADDRESS && NO_SYS == 0 && LWIP_NETIF_API == 1
+  set_dhcp_state(DHCP_WAIT_ADDRESS);
+#endif
+
+  /* initialize the hardware */
+  low_level_init(netif);
+
+  return ERR_OK;
+}
+
+/**
+  * @brief 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)
+{
+#if NO_SYS == 0
+  int32_t PHYLinkState;
+  ETH_MACConfigTypeDef MACConf;
+  uint32_t duplex, speed = 0;
+#endif
+  uint32_t idx = 0;
+  uint8_t macaddress[6]= {ETH_MAC_ADDR0, ETH_MAC_ADDR1, ETH_MAC_ADDR2, ETH_MAC_ADDR3, ETH_MAC_ADDR4, ETH_MAC_ADDR5};
+  
+  EthHandle.Instance = ETH;  
+  EthHandle.Init.MACAddr = macaddress;
+  EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
+  EthHandle.Init.RxDesc = DMARxDscrTab;
+  EthHandle.Init.TxDesc = DMATxDscrTab;
+  EthHandle.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;
+  
+  /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
+  HAL_ETH_Init(&EthHandle);
+  
+#if NO_SYS == 0
+  /* Enable the Ethernet global Interrupt */
+  HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
+  HAL_NVIC_EnableIRQ(ETH_IRQn);
+#endif
+
+  /* set MAC hardware address length */
+  netif->hwaddr_len = ETH_HWADDR_LEN;
+  
+  /* set MAC hardware address */
+  netif->hwaddr[0] =  ETH_MAC_ADDR0;
+  netif->hwaddr[1] =  ETH_MAC_ADDR1;
+  netif->hwaddr[2] =  ETH_MAC_ADDR2;
+  netif->hwaddr[3] =  ETH_MAC_ADDR3;
+  netif->hwaddr[4] =  ETH_MAC_ADDR4;
+  netif->hwaddr[5] =  ETH_MAC_ADDR5;
+  
+  /* maximum transfer unit */
+  netif->mtu = ETH_MAX_PAYLOAD;
+  
+  /* device capabilities */
+  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
+  netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
+  
+  for(idx = 0; idx < ETH_RX_DESC_CNT; idx ++)
+  {
+    HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
+  }
+  
+  /* Initialize the RX POOL */
+  LWIP_MEMPOOL_INIT(RX_POOL);
+  
+  memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));  
+  TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
+  TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
+  TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
+
+#ifdef __rtems__
+#if NO_SYS == 0
+  /* create a binary semaphore used for informing ethernetif of frame reception */
+  sys_sem_new(&RxPktSemaphore, 1);
+  
+  /* create the task that handles the ETH_MAC */
+  sys_thread_new(
+    "ETHM",
+    (lwip_thread_fn) ethernetif_input,
+    netif,
+    RTEMS_LWIP_INTERFACE_THREAD_STACK_SIZE,
+    RTEMS_LWIP_INTERFACE_THREAD_PRIORITY
+  );
+#endif /* NO_SYS == 0 */
+#endif /* __rtems__ */
+  
+  /* Set PHY IO functions */
+  LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);
+  
+  /* Initialize the LAN8742 ETH PHY */
+  LAN8742_Init(&LAN8742);
+  
+#if NO_SYS == 0
+  PHYLinkState = LAN8742_GetLinkState(&LAN8742);
+  
+  /* Get link state */  
+  if(PHYLinkState <= LAN8742_STATUS_LINK_DOWN)
+  {
+    netif_set_link_down(netif);
+    netif_set_down(netif);
+  }
+  else 
+  {
+    switch (PHYLinkState)
+    {
+    case LAN8742_STATUS_100MBITS_FULLDUPLEX:
+      duplex = ETH_FULLDUPLEX_MODE;
+      speed = ETH_SPEED_100M;
+      break;
+    case LAN8742_STATUS_100MBITS_HALFDUPLEX:
+      duplex = ETH_HALFDUPLEX_MODE;
+      speed = ETH_SPEED_100M;
+      break;
+    case LAN8742_STATUS_10MBITS_FULLDUPLEX:
+      duplex = ETH_FULLDUPLEX_MODE;
+      speed = ETH_SPEED_10M;
+      break;
+    case LAN8742_STATUS_10MBITS_HALFDUPLEX:
+      duplex = ETH_HALFDUPLEX_MODE;
+      speed = ETH_SPEED_10M;
+      break;
+    default:
+      duplex = ETH_FULLDUPLEX_MODE;
+      speed = ETH_SPEED_100M;
+      break;      
+    }
+    
+    /* Get MAC Config MAC */
+    HAL_ETH_GetMACConfig(&EthHandle, &MACConf); 
+    MACConf.DuplexMode = duplex;
+    MACConf.Speed = speed;
+    HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
+    HAL_ETH_Start_IT(&EthHandle);
+#ifdef __rtems__
+    /* Install the ETH IRQ for RTEMS */
+    rtems_interrupt_handler_install(ETH_IRQn, NULL, RTEMS_INTERRUPT_UNIQUE,
+        (rtems_interrupt_handler) &HAL_ETH_IRQHandler, &EthHandle);
+#endif
+    netif_set_up(netif);
+    netif_set_link_up(netif);
+  }
+#endif
+
+  ethernet_link_check_state(netif);
+}
+
+/**
+  * @brief 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 available 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)
+{
+  uint32_t i=0;
+  struct pbuf *q;
+  err_t errval = ERR_OK;
+  ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
+  
+  memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
+  
+  for(q = p; q != NULL; q = q->next)
+  {
+    if(i >= ETH_TX_DESC_CNT)	
+      return ERR_IF;
+    
+    Txbuffer[i].buffer = q->payload;
+    Txbuffer[i].len = q->len;
+
+#ifdef __rtems__
+    /* For the socket API, a custom send buffer might be used which is not protected by the
+    MPU. Therefore, clean DCache here as well */
+#if RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU == 0 || LWIP_SOCKET == 1
+    /* Cleaning cache isn't necessary if the tx buffers are in a not-cacheable MPU region. */
+    uint8_t *dataStart = q->payload;
+    uint8_t *lineStart = (uint8_t *)((uint32_t)dataStart & ~31);
+    SCB_CleanDCache_by_Addr((uint32_t *)lineStart, q->len + (dataStart - lineStart));
+#endif
+#endif
+
+    if(i>0)
+    {
+      Txbuffer[i-1].next = &Txbuffer[i];
+    }
+    
+    if(q->next == NULL)
+    {
+      Txbuffer[i].next = NULL;
+    }
+
+    i++;
+  }
+
+  TxConfig.Length = p->tot_len;
+  TxConfig.TxBuffer = Txbuffer;
+
+  HAL_ETH_Transmit(&EthHandle, &TxConfig, RTEMS_LWIP_ETH_DMA_TRANSMIT_TIMEOUT);
+  
+  return errval;
+}
+
+/**
+  * @brief 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;
+  ETH_BufferTypeDef RxBuff[ETH_RX_DESC_CNT];
+  uint32_t framelength = 0, i = 0;;
+  struct pbuf_custom* custom_pbuf;
+
+  memset(RxBuff, 0 , ETH_RX_DESC_CNT*sizeof(ETH_BufferTypeDef));
+  
+  for(i = 0; i < ETH_RX_DESC_CNT -1; i++)
+  {
+    RxBuff[i].next=&RxBuff[i+1];
+  }
+
+#if NO_SYS == 0
+  if(HAL_ETH_GetRxDataBuffer(&EthHandle, RxBuff) == HAL_OK) {
+#else
+  if (HAL_ETH_IsRxDataAvailable(&EthHandle)) {
+#endif /* NO_SYS != 0 */
+
+#if NO_SYS == 1
+    HAL_ETH_GetRxDataBuffer(&EthHandle, RxBuff);
+#endif /* NO_SYS == 1 */
+
+    HAL_ETH_GetRxDataLength(&EthHandle, &framelength);
+
+    /* Build Rx descriptor to be ready for next data reception */
+    HAL_ETH_BuildRxDescriptors(&EthHandle);
+
+    /* Invalidate data cache for ETH Rx Buffers */
+    SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff->buffer, framelength);
+    
+    custom_pbuf  = (struct pbuf_custom*)LWIP_MEMPOOL_ALLOC(RX_POOL);
+    if(custom_pbuf != NULL)
+    {
+      custom_pbuf->custom_free_function = pbuf_free_custom;
+
+      p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_REF, custom_pbuf, RxBuff->buffer, framelength);
+    }
+
+  }
+  
+  return p;
+}
+
+#if NO_SYS == 0
+/**
+  * @brief This function is the ethernetif_input task, it is processed 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)
+{
+  struct pbuf *p;
+  
+  for( ;; )
+  {
+    if (sys_arch_sem_wait(&RxPktSemaphore, 0) != SYS_ARCH_TIMEOUT)
+    {
+      do
+      {
+        p = low_level_input( netif );
+        if (p != NULL)
+        {
+          if (netif->input( p, netif) != ERR_OK )
+          {
+            pbuf_free(p);
+          }
+        }
+
+      }while(p!=NULL);
+    }
+  }
+}
+#else
+/**
+  * @brief This function is the ethernetif_input task, it is processed 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;
+  }
+}
+#endif /* NO_SYS == 1 */
+
+/**
+  * @brief  Custom Rx pbuf free callback
+  * @param  pbuf: pbuf to be freed
+  * @retval None
+  */
+void pbuf_free_custom(struct pbuf *p)
+{
+  struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p;
+  LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
+}
+
+
+/*******************************************************************************
+                       Ethernet MSP Routines
+*******************************************************************************/
+/**
+  * @brief  Note: HAL_ETH_MspInit of RTEMS BSP is used.
+  * @param  heth: ETH handle
+  * @retval None
+*/
+
+#if NO_SYS == 0
+/**
+  * @brief  Ethernet Rx Transfer completed callback
+  * @param  heth: ETH handle
+  * @retval None
+  */
+void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
+{
+  sys_sem_signal(&RxPktSemaphore);
+}
+#endif
+
+/*******************************************************************************
+                       PHI IO Functions
+*******************************************************************************/
+/**
+  * @brief  Initializes the MDIO interface GPIO and clocks.
+  * @param  None
+  * @retval 0 if OK, -1 if ERROR
+  */
+int32_t ETH_PHY_IO_Init(void)
+{  
+  /* We assume that MDIO GPIO configuration is already done
+     in the ETH_MspInit() else it should be done here 
+  */
+  
+  /* Configure the MDIO Clock */
+  HAL_ETH_SetMDIOClockRange(&EthHandle);
+  
+  return 0;
+}
+
+/**
+  * @brief  De-Initializes the MDIO interface .
+  * @param  None
+  * @retval 0 if OK, -1 if ERROR
+  */
+int32_t ETH_PHY_IO_DeInit (void)
+{
+  return 0;
+}
+
+/**
+  * @brief  Read a PHY register through the MDIO interface.
+  * @param  DevAddr: PHY port address
+  * @param  RegAddr: PHY register address
+  * @param  pRegVal: pointer to hold the register value 
+  * @retval 0 if OK -1 if Error
+  */
+int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
+{
+  if(HAL_ETH_ReadPHYRegister(&EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK)
+  {
+    return -1;
+  }
+  
+  return 0;
+}
+
+/**
+  * @brief  Write a value to a PHY register through the MDIO interface.
+  * @param  DevAddr: PHY port address
+  * @param  RegAddr: PHY register address
+  * @param  RegVal: Value to be written 
+  * @retval 0 if OK -1 if Error
+  */
+int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
+{
+  if(HAL_ETH_WritePHYRegister(&EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK)
+  {
+    return -1;
+  }
+  
+  return 0;
+}
+
+/**
+  * @brief  Get the time in millisecons used for internal PHY driver process.
+  * @retval Time value
+  */
+int32_t ETH_PHY_IO_GetTick(void)
+{
+  return HAL_GetTick();
+}
+
+void ethernet_link_check_state(struct netif *netif)
+{
+  ETH_MACConfigTypeDef MACConf;
+  uint32_t PHYLinkState;
+  uint32_t linkchanged = 0, speed = 0, duplex =0;
+
+  PHYLinkState = LAN8742_GetLinkState(&LAN8742);
+
+  if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
+  {
+    HAL_ETH_Stop(&EthHandle);
+    netif_set_down(netif);
+    netif_set_link_down(netif);
+  }
+  else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
+  {
+    switch (PHYLinkState)
+    {
+    case LAN8742_STATUS_100MBITS_FULLDUPLEX:
+      duplex = ETH_FULLDUPLEX_MODE;
+      speed = ETH_SPEED_100M;
+      linkchanged = 1;
+      break;
+    case LAN8742_STATUS_100MBITS_HALFDUPLEX:
+      duplex = ETH_HALFDUPLEX_MODE;
+      speed = ETH_SPEED_100M;
+      linkchanged = 1;
+      break;
+    case LAN8742_STATUS_10MBITS_FULLDUPLEX:
+      duplex = ETH_FULLDUPLEX_MODE;
+      speed = ETH_SPEED_10M;
+      linkchanged = 1;
+      break;
+    case LAN8742_STATUS_10MBITS_HALFDUPLEX:
+      duplex = ETH_HALFDUPLEX_MODE;
+      speed = ETH_SPEED_10M;
+      linkchanged = 1;
+      break;
+    default:
+      break;
+    }
+
+    if(linkchanged)
+    {
+      /* Get MAC Config MAC */
+      HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
+      MACConf.DuplexMode = duplex;
+      MACConf.Speed = speed;
+      HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
+      HAL_ETH_Start(&EthHandle);
+      netif_set_up(netif);
+      netif_set_link_up(netif);
+    }
+  }
+}
+
+#ifdef __rtems__
+#if NO_SYS == 1
+/* Even for NO_SYS == 1 this needs to be implemented */
+uint32_t
+sys_now()
+{
+  /* Forward call to HAL function which already implements returning millisecond ticks */
+  return HAL_GetTick();
+}
+#endif /* NO_SYS == 1 */
+
+/* Configure the MPU for the lwIP heap. */
+void mpu_config_tx_buffers(uint32_t base_addr, size_t region_size)
+{
+    MPU_Region_InitTypeDef MPU_InitStruct;
+    uint8_t region_select = determine_mpu_region_size_select(region_size);
+
+    /* Disable the MPU */
+    HAL_MPU_Disable();
+
+    /* Configure the MPU attributes as Normal Non Cacheable
+       for LwIP RAM heap which contains the Tx buffers */
+    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
+    MPU_InitStruct.BaseAddress = base_addr;
+    MPU_InitStruct.Size = region_select;
+    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
+    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
+    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
+    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
+    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
+    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
+    MPU_InitStruct.SubRegionDisable = 0x00;
+    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
+
+    HAL_MPU_ConfigRegion(&MPU_InitStruct);
+
+    SCB_CleanDCache_by_Addr((uint32_t*) base_addr, region_size);
+
+    /* Enable the MPU */
+    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
+
+}
+
+uint8_t determine_mpu_region_size_select(size_t lwip_heap_size)
+{
+    if(lwip_heap_size <= 1024) {
+        return MPU_REGION_SIZE_1KB;
+    }
+    else if(lwip_heap_size <= 2 * 1024) {
+        return MPU_REGION_SIZE_2KB;
+    }
+    else if(lwip_heap_size <= 4 * 1024) {
+        return MPU_REGION_SIZE_4KB;
+    }
+    else if(lwip_heap_size <= 8 * 1024) {
+        return MPU_REGION_SIZE_8KB;
+    }
+    else if(lwip_heap_size <= 16 * 1024) {
+        return MPU_REGION_SIZE_16KB;
+    }
+    else if(lwip_heap_size <= 32 * 1024) {
+        return MPU_REGION_SIZE_32KB;
+    }
+    else if(lwip_heap_size <= 64 * 1024) {
+        return MPU_REGION_SIZE_64KB;
+    }
+    else if(lwip_heap_size <= 128 * 1024) {
+        return MPU_REGION_SIZE_128KB;
+    }
+    else if(lwip_heap_size <= 256 * 1024) {
+        return MPU_REGION_SIZE_256KB;
+    }
+    else if(lwip_heap_size <= 512 * 1024) {
+        return MPU_REGION_SIZE_512KB;
+    }
+    else {
+        /* There is only 1MB RAM available so a MPU protection of 1MB does not really make sense */
+        return MPU_REGION_SIZE_512KB;
+    }
+}
+
+lan8742_Object_t* get_lan_phy_handle() {
+  return &LAN8742;
+}
+
+ETH_HandleTypeDef* get_eth_handle() {
+  return &EthHandle;
+}
+#endif /* __rtems__ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/lwip/ports/drivers/stm32h7/include/rtems_lwip/app_dhcp.h b/lwip/ports/drivers/stm32h7/include/rtems_lwip/app_dhcp.h
new file mode 100644
index 0000000..c2447f2
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/include/rtems_lwip/app_dhcp.h
@@ -0,0 +1,51 @@
+#ifndef LWIP_PORTS_DRIVERS_STM32H7_APP_DHCP_H_
+#define LWIP_PORTS_DRIVERS_STM32H7_APP_DHCP_H_
+
+#include <lwipopts.h>
+#include <stdint.h>
+
+#include <lwip/netif.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the state of the internal DHCP state machine
+ * @return
+ */
+uint8_t get_dhcp_state();
+
+/* DHCP process states */
+#define DHCP_OFF                   (uint8_t) 0
+#define DHCP_START                 (uint8_t) 1
+#define DHCP_WAIT_ADDRESS          (uint8_t) 2
+#define DHCP_ADDRESS_ASSIGNED      (uint8_t) 3
+#define DHCP_TIMEOUT               (uint8_t) 4
+#define DHCP_LINK_DOWN             (uint8_t) 5
+
+#if NO_SYS == 1
+/**
+ * This function should be called in mainloop or in a dedicated thread and takes care of
+ * the DHCP handling.
+ * @param netif
+ */
+void dhcp_periodic_handle(struct netif *netif);
+#else
+
+/**
+ * Start a DHCP thread with the given parameters.
+ * @param task_interval_ms
+ * @param task_stack
+ * @param task_priority
+ */
+void rtems_lwip_start_dhcp_thread(uint32_t task_interval_ms,
+    size_t task_stack, uint8_t task_priority);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_PORTS_DRIVERS_STM32H7_APP_DHCP_H_ */
diff --git a/lwip/ports/drivers/stm32h7/include/rtems_lwip/app_ethernet.h b/lwip/ports/drivers/stm32h7/include/rtems_lwip/app_ethernet.h
new file mode 100644
index 0000000..acf7e5a
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/include/rtems_lwip/app_ethernet.h
@@ -0,0 +1,64 @@
+/**
+  ******************************************************************************
+  * @file    LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/app_ethernet.h 
+  * @author  MCD Application Team
+  * @brief   Header for app_ethernet.c module
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under Ultimate Liberty license
+  * SLA0044, the "License"; You may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at:
+  *                             www.st.com/SLA0044
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __APP_ETHERNET_H
+#define __APP_ETHERNET_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "lwip/netif.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void ethernet_link_status_updated(struct netif *netif);
+
+#if LWIP_NETIF_LINK_CALLBACK == 1 && NO_SYS == 1
+/**
+ * This function should be called in mainloop or in a dedicated thread and takes care of
+ * the ethernet link handling.
+ * @param netif
+ */
+void ethernet_link_periodic_handle(struct netif *netif);
+#endif
+
+/**
+ * Start a ethernet link thread with the given parameters.
+ * @param task_interval_ms
+ * @param task_stack
+ * @param task_priority
+ */
+void rtems_lwip_start_link_thread(uint32_t task_interval_ms,
+    size_t task_stack, uint8_t task_priority);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __APP_ETHERNET_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/lwip/ports/drivers/stm32h7/include/rtems_lwip/ethernetif.h b/lwip/ports/drivers/stm32h7/include/rtems_lwip/ethernetif.h
new file mode 100644
index 0000000..ff9b491
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/include/rtems_lwip/ethernetif.h
@@ -0,0 +1,59 @@
+/**
+  ******************************************************************************
+  * @file    LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/ethernetif.h 
+  * @author  MCD Application Team
+  * @brief   Header for ethernetif.c module
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under Ultimate Liberty license
+  * SLA0044, the "License"; You may not use this file except in compliance with
+  * the License. You may obtain a copy of the License at:
+  *                             www.st.com/SLA0044
+  *
+  ******************************************************************************
+  */
+
+#ifndef __ETHERNETIF_H__
+#define __ETHERNETIF_H__
+
+
+#include "lwip/err.h"
+#include "lwip/netif.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ETH_RX_BUFFER_SIZE                     (1536UL)
+
+/* Exported types ------------------------------------------------------------*/
+#ifdef __rtems__
+typedef struct {
+ struct netif* netif;
+ uint32_t task_interval_ms;
+} LwipThreadArgs;
+#endif /* __rtems__ */
+
+/* Exported functions ------------------------------------------------------- */
+err_t ethernetif_init(struct netif *netif);      
+void ethernetif_input(struct netif *netif);
+void ethernet_link_check_state(struct netif *netif);
+
+#ifdef __rtems__
+/**
+ * This function can be used to protect the TX lwIP buffer region (lwIP Heap).
+ * @param base_addr
+ * @param region_size
+ */
+void mpu_config_tx_buffers(uint32_t base_addr, size_t region_size);
+#endif /* __rtems__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ETHERNETIF_H__ */
diff --git a/lwip/ports/drivers/stm32h7/lan8742.c b/lwip/ports/drivers/stm32h7/lan8742.c
new file mode 100644
index 0000000..a268393
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/lan8742.c
@@ -0,0 +1,664 @@
+/** 
+  ******************************************************************************
+  * @file    lan8742.c
+  * @author  MCD Application Team
+  * @brief   This file provides a set of functions needed to manage the LAN742
+  *          PHY devices.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */  
+
+/* Includes ------------------------------------------------------------------*/
+#include "lan8742.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup Component
+  * @{
+  */ 
+  
+/** @defgroup LAN8742 LAN8742
+  * @{
+  */   
+  
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines
+  * @{
+  */
+#define LAN8742_SW_RESET_TO    ((uint32_t)500U)
+#define LAN8742_INIT_TO        ((uint32_t)2000U)
+#define LAN8742_MAX_DEV_ADDR   ((uint32_t)31U)
+/**
+  * @}
+  */
+ 
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup LAN8742_Private_Functions LAN8742 Private Functions
+  * @{
+  */
+    
+/**
+  * @brief  Register IO functions to component object
+  * @param  pObj: device object  of LAN8742_Object_t. 
+  * @param  ioctx: holds device IO functions.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_ERROR if missing mandatory function
+  */
+int32_t  LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx)
+{
+  if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
+  {
+    return LAN8742_STATUS_ERROR;
+  }
+  
+  pObj->IO.Init = ioctx->Init;
+  pObj->IO.DeInit = ioctx->DeInit;
+  pObj->IO.ReadReg = ioctx->ReadReg;
+  pObj->IO.WriteReg = ioctx->WriteReg;
+  pObj->IO.GetTick = ioctx->GetTick;
+  
+  return LAN8742_STATUS_OK;
+}
+
+/**
+  * @brief  Initialize the lan8742 and configure the needed hardware resources
+  * @param  pObj: device object LAN8742_Object_t. 
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_ADDRESS_ERROR if cannot find device address
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  *         LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset
+  */
+ int32_t LAN8742_Init(lan8742_Object_t *pObj)
+ {
+   uint32_t tickstart = 0, regvalue = 0, addr = 0;
+   int32_t status = LAN8742_STATUS_OK;
+   
+   if(pObj->Is_Initialized == 0)
+   {
+     if(pObj->IO.Init != 0)
+     {
+       /* GPIO and Clocks initialization */
+       pObj->IO.Init();
+     }
+   
+     /* for later check */
+     pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1;
+   
+     /* Get the device address from special mode register */  
+     for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++)
+     {
+       if(pObj->IO.ReadReg(addr, LAN8742_SMR, &regvalue) < 0)
+       { 
+         status = LAN8742_STATUS_READ_ERROR;
+         /* Can't read from this device address 
+            continue with next address */
+         continue;
+       }
+     
+       if((regvalue & LAN8742_SMR_PHY_ADDR) == addr)
+       {
+         pObj->DevAddr = addr;
+         status = LAN8742_STATUS_OK;
+         break;
+       }
+     }
+   
+     if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR)
+     {
+       status = LAN8742_STATUS_ADDRESS_ERROR;
+     }
+     
+     /* if device address is matched */
+     if(status == LAN8742_STATUS_OK)
+     {
+       /* set a software reset  */
+       if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0)
+       { 
+         /* get software reset status */
+         if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) >= 0)
+         { 
+           tickstart = pObj->IO.GetTick();
+           
+           /* wait until software reset is done or timeout occured  */
+           while(regvalue & LAN8742_BCR_SOFT_RESET)
+           {
+             if((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO)
+             {
+               if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) < 0)
+               { 
+                 status = LAN8742_STATUS_READ_ERROR;
+                 break;
+               }
+             }
+             else
+             {
+               status = LAN8742_STATUS_RESET_TIMEOUT;
+               break;
+             }
+           } 
+         }
+         else
+         {
+           status = LAN8742_STATUS_READ_ERROR;
+         }
+       }
+       else
+       {
+         status = LAN8742_STATUS_WRITE_ERROR;
+       }
+     }
+   }
+      
+   if(status == LAN8742_STATUS_OK)
+   {
+     tickstart =  pObj->IO.GetTick();
+     
+     /* Wait for 2s to perform initialization */
+     while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO)
+     {
+     }
+     pObj->Is_Initialized = 1;
+   }
+   
+   return status;
+ }
+
+/**
+  * @brief  De-Initialize the lan8742 and it's hardware resources
+  * @param  pObj: device object LAN8742_Object_t. 
+  * @retval None
+  */
+int32_t LAN8742_DeInit(lan8742_Object_t *pObj)
+{
+  if(pObj->Is_Initialized)
+  {
+    if(pObj->IO.DeInit != 0)
+    {
+      if(pObj->IO.DeInit() < 0)
+      {
+        return LAN8742_STATUS_ERROR;
+      }
+    }
+  
+    pObj->Is_Initialized = 0;  
+  }
+  
+  return LAN8742_STATUS_OK;
+}
+
+/**
+  * @brief  Disable the LAN8742 power down mode.
+  * @param  pObj: device object LAN8742_Object_t.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval &= ~LAN8742_BCR_POWER_DOWN;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Enable the LAN8742 power down mode.
+  * @param  pObj: device object LAN8742_Object_t.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval |= LAN8742_BCR_POWER_DOWN;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Start the auto negotiation process.
+  * @param  pObj: device object LAN8742_Object_t.  
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval |= LAN8742_BCR_AUTONEGO_EN;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Get the link state of LAN8742 device.
+  * @param  pObj: Pointer to device object. 
+  * @param  pLinkState: Pointer to link state
+  * @retval LAN8742_STATUS_LINK_DOWN  if link is down
+  *         LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed 
+  *         LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
+  *         LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
+  *         LAN8742_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
+  *         LAN8742_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD       
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  
+  /* Read Status register  */
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0)
+  {
+    return LAN8742_STATUS_READ_ERROR;
+  }
+  
+  /* Read Status register again */
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0)
+  {
+    return LAN8742_STATUS_READ_ERROR;
+  }
+  
+  if((readval & LAN8742_BSR_LINK_STATUS) == 0)
+  {
+    /* Return Link Down status */
+    return LAN8742_STATUS_LINK_DOWN;    
+  }
+  
+  /* Check Auto negotiaition */
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0)
+  {
+    return LAN8742_STATUS_READ_ERROR;
+  }
+  
+  if((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN)
+  {
+    if(((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)) 
+    {
+      return LAN8742_STATUS_100MBITS_FULLDUPLEX;
+    }
+    else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT)
+    {
+      return LAN8742_STATUS_100MBITS_HALFDUPLEX;
+    }        
+    else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)
+    {
+      return LAN8742_STATUS_10MBITS_FULLDUPLEX;
+    }
+    else
+    {
+      return LAN8742_STATUS_10MBITS_HALFDUPLEX;
+    }  		
+  }
+  else /* Auto Nego enabled */
+  {
+    if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0)
+    {
+      return LAN8742_STATUS_READ_ERROR;
+    }
+    
+    /* Check if auto nego not done */
+    if((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0)
+    {
+      return LAN8742_STATUS_AUTONEGO_NOTDONE;
+    }
+    
+    if((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD)
+    {
+      return LAN8742_STATUS_100MBITS_FULLDUPLEX;
+    }
+    else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD)
+    {
+      return LAN8742_STATUS_100MBITS_HALFDUPLEX;
+    }
+    else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD)
+    {
+      return LAN8742_STATUS_10MBITS_FULLDUPLEX;
+    }
+    else
+    {
+      return LAN8742_STATUS_10MBITS_HALFDUPLEX;
+    }				
+  }
+}
+
+/**
+  * @brief  Set the link state of LAN8742 device.
+  * @param  pObj: Pointer to device object. 
+  * @param  pLinkState: link state can be one of the following
+  *         LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
+  *         LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
+  *         LAN8742_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
+  *         LAN8742_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD   
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_ERROR  if parameter error  
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState)
+{
+  uint32_t bcrvalue = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &bcrvalue) >= 0)
+  {
+    /* Disable link config (Auto nego, speed and duplex) */
+    bcrvalue &= ~(LAN8742_BCR_AUTONEGO_EN | LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);
+    
+    if(LinkState == LAN8742_STATUS_100MBITS_FULLDUPLEX)
+    {
+      bcrvalue |= (LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);
+    }
+    else if (LinkState == LAN8742_STATUS_100MBITS_HALFDUPLEX)
+    {
+      bcrvalue |= LAN8742_BCR_SPEED_SELECT;
+    }
+    else if (LinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX)
+    {
+      bcrvalue |= LAN8742_BCR_DUPLEX_MODE;
+    }
+    else
+    {
+      /* Wrong link status parameter */
+      status = LAN8742_STATUS_ERROR;
+    }	
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+  
+  if(status == LAN8742_STATUS_OK)
+  {
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, bcrvalue) < 0)
+    {
+      status = LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  
+  return status;
+}
+
+/**
+  * @brief  Enable loopback mode.
+  * @param  pObj: Pointer to device object. 
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval |= LAN8742_BCR_LOOPBACK;
+    
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status = LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+  
+  return status;
+}
+
+/**
+  * @brief  Disable loopback mode.
+  * @param  pObj: Pointer to device object. 
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0)
+  {
+    readval &= ~LAN8742_BCR_LOOPBACK;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Enable IT source.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT source to be enabled
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0)
+  {
+    readval |= Interrupt;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0)
+    {
+      status =  LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Disable IT source.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT source to be disabled
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
+  */
+int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0)
+  {
+    readval &= ~Interrupt;
+  
+    /* Apply configuration */
+    if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0)
+    {
+      status = LAN8742_STATUS_WRITE_ERROR;
+    }
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+   
+  return status;
+}
+
+/**
+  * @brief  Clear IT flag.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT flag to be cleared
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT
+  * @retval LAN8742_STATUS_OK  if OK
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  */
+int32_t  LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = LAN8742_STATUS_OK;  
+  
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) < 0)
+  {
+    status =  LAN8742_STATUS_READ_ERROR;
+  }
+  
+  return status;
+}
+
+/**
+  * @brief  Get IT Flag status.
+  * @param  pObj: Pointer to device object. 
+  * @param  Interrupt: IT Flag to be checked, 
+  *         should be a value or a combination of the following:
+  *         LAN8742_WOL_IT                     
+  *         LAN8742_ENERGYON_IT                
+  *         LAN8742_AUTONEGO_COMPLETE_IT       
+  *         LAN8742_REMOTE_FAULT_IT            
+  *         LAN8742_LINK_DOWN_IT               
+  *         LAN8742_AUTONEGO_LP_ACK_IT         
+  *         LAN8742_PARALLEL_DETECTION_FAULT_IT
+  *         LAN8742_AUTONEGO_PAGE_RECEIVED_IT  
+  * @retval 1 IT flag is SET
+  *         0 IT flag is RESET
+  *         LAN8742_STATUS_READ_ERROR if connot read register
+  */
+int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt)
+{
+  uint32_t readval = 0;
+  int32_t status = 0;
+
+  if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) >= 0)
+  {
+    status = ((readval & Interrupt) == Interrupt);
+  }
+  else
+  {
+    status = LAN8742_STATUS_READ_ERROR;
+  }
+	
+  return status;
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */      
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/lwip/ports/drivers/stm32h7/lan8742.h b/lwip/ports/drivers/stm32h7/lan8742.h
new file mode 100644
index 0000000..c1620dd
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/lan8742.h
@@ -0,0 +1,448 @@
+/**
+  ******************************************************************************
+  * @file    lan8742.h
+  * @author  MCD Application Team
+  * @brief   This file contains all the functions prototypes for the
+  *          lan8742.c PHY driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef LAN8742_H
+#define LAN8742_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif   
+   
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Component
+  * @{
+  */
+    
+/** @defgroup LAN8742
+  * @{
+  */    
+/* Exported constants --------------------------------------------------------*/
+/** @defgroup LAN8742_Exported_Constants LAN8742 Exported Constants
+  * @{
+  */ 
+  
+/** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping
+  * @{
+  */ 
+#define LAN8742_BCR      ((uint16_t)0x0000U)
+#define LAN8742_BSR      ((uint16_t)0x0001U)
+#define LAN8742_PHYI1R   ((uint16_t)0x0002U)
+#define LAN8742_PHYI2R   ((uint16_t)0x0003U)
+#define LAN8742_ANAR     ((uint16_t)0x0004U)
+#define LAN8742_ANLPAR   ((uint16_t)0x0005U)
+#define LAN8742_ANER     ((uint16_t)0x0006U)
+#define LAN8742_ANNPTR   ((uint16_t)0x0007U)
+#define LAN8742_ANNPRR   ((uint16_t)0x0008U)
+#define LAN8742_MMDACR   ((uint16_t)0x000DU)
+#define LAN8742_MMDAADR  ((uint16_t)0x000EU)
+#define LAN8742_ENCTR    ((uint16_t)0x0010U)
+#define LAN8742_MCSR     ((uint16_t)0x0011U)
+#define LAN8742_SMR      ((uint16_t)0x0012U)
+#define LAN8742_TPDCR    ((uint16_t)0x0018U)
+#define LAN8742_TCSR     ((uint16_t)0x0019U)
+#define LAN8742_SECR     ((uint16_t)0x001AU)
+#define LAN8742_SCSIR    ((uint16_t)0x001BU)
+#define LAN8742_CLR      ((uint16_t)0x001CU)
+#define LAN8742_ISFR     ((uint16_t)0x001DU)
+#define LAN8742_IMR      ((uint16_t)0x001EU)
+#define LAN8742_PHYSCSR  ((uint16_t)0x001FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_BCR_Bit_Definition LAN8742 BCR Bit Definition
+  * @{
+  */    
+#define LAN8742_BCR_SOFT_RESET         ((uint16_t)0x8000U)
+#define LAN8742_BCR_LOOPBACK           ((uint16_t)0x4000U)
+#define LAN8742_BCR_SPEED_SELECT       ((uint16_t)0x2000U)
+#define LAN8742_BCR_AUTONEGO_EN        ((uint16_t)0x1000U)
+#define LAN8742_BCR_POWER_DOWN         ((uint16_t)0x0800U)
+#define LAN8742_BCR_ISOLATE            ((uint16_t)0x0400U)
+#define LAN8742_BCR_RESTART_AUTONEGO   ((uint16_t)0x0200U)
+#define LAN8742_BCR_DUPLEX_MODE        ((uint16_t)0x0100U) 
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_BSR_Bit_Definition LAN8742 BSR Bit Definition
+  * @{
+  */   
+#define LAN8742_BSR_100BASE_T4       ((uint16_t)0x8000U)
+#define LAN8742_BSR_100BASE_TX_FD    ((uint16_t)0x4000U)
+#define LAN8742_BSR_100BASE_TX_HD    ((uint16_t)0x2000U)
+#define LAN8742_BSR_10BASE_T_FD      ((uint16_t)0x1000U)
+#define LAN8742_BSR_10BASE_T_HD      ((uint16_t)0x0800U)
+#define LAN8742_BSR_100BASE_T2_FD    ((uint16_t)0x0400U)
+#define LAN8742_BSR_100BASE_T2_HD    ((uint16_t)0x0200U)
+#define LAN8742_BSR_EXTENDED_STATUS  ((uint16_t)0x0100U)
+#define LAN8742_BSR_AUTONEGO_CPLT    ((uint16_t)0x0020U)
+#define LAN8742_BSR_REMOTE_FAULT     ((uint16_t)0x0010U)
+#define LAN8742_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
+#define LAN8742_BSR_LINK_STATUS      ((uint16_t)0x0004U)
+#define LAN8742_BSR_JABBER_DETECT    ((uint16_t)0x0002U)
+#define LAN8742_BSR_EXTENDED_CAP     ((uint16_t)0x0001U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_PHYI1R_Bit_Definition LAN8742 PHYI1R Bit Definition
+  * @{
+  */
+#define LAN8742_PHYI1R_OUI_3_18           ((uint16_t)0xFFFFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_PHYI2R_Bit_Definition LAN8742 PHYI2R Bit Definition
+  * @{
+  */
+#define LAN8742_PHYI2R_OUI_19_24          ((uint16_t)0xFC00U)
+#define LAN8742_PHYI2R_MODEL_NBR          ((uint16_t)0x03F0U)
+#define LAN8742_PHYI2R_REVISION_NBR       ((uint16_t)0x000FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANAR_Bit_Definition LAN8742 ANAR Bit Definition
+  * @{
+  */
+#define LAN8742_ANAR_NEXT_PAGE               ((uint16_t)0x8000U)
+#define LAN8742_ANAR_REMOTE_FAULT            ((uint16_t)0x2000U)
+#define LAN8742_ANAR_PAUSE_OPERATION         ((uint16_t)0x0C00U)
+#define LAN8742_ANAR_PO_NOPAUSE              ((uint16_t)0x0000U)
+#define LAN8742_ANAR_PO_SYMMETRIC_PAUSE      ((uint16_t)0x0400U)
+#define LAN8742_ANAR_PO_ASYMMETRIC_PAUSE     ((uint16_t)0x0800U)
+#define LAN8742_ANAR_PO_ADVERTISE_SUPPORT    ((uint16_t)0x0C00U)
+#define LAN8742_ANAR_100BASE_TX_FD           ((uint16_t)0x0100U)
+#define LAN8742_ANAR_100BASE_TX              ((uint16_t)0x0080U)
+#define LAN8742_ANAR_10BASE_T_FD             ((uint16_t)0x0040U)
+#define LAN8742_ANAR_10BASE_T                ((uint16_t)0x0020U)
+#define LAN8742_ANAR_SELECTOR_FIELD          ((uint16_t)0x000FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANLPAR_Bit_Definition LAN8742 ANLPAR Bit Definition
+  * @{
+  */
+#define LAN8742_ANLPAR_NEXT_PAGE            ((uint16_t)0x8000U)
+#define LAN8742_ANLPAR_REMOTE_FAULT         ((uint16_t)0x2000U)
+#define LAN8742_ANLPAR_PAUSE_OPERATION      ((uint16_t)0x0C00U)
+#define LAN8742_ANLPAR_PO_NOPAUSE           ((uint16_t)0x0000U)
+#define LAN8742_ANLPAR_PO_SYMMETRIC_PAUSE   ((uint16_t)0x0400U)
+#define LAN8742_ANLPAR_PO_ASYMMETRIC_PAUSE  ((uint16_t)0x0800U)
+#define LAN8742_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
+#define LAN8742_ANLPAR_100BASE_TX_FD        ((uint16_t)0x0100U)
+#define LAN8742_ANLPAR_100BASE_TX           ((uint16_t)0x0080U)
+#define LAN8742_ANLPAR_10BASE_T_FD          ((uint16_t)0x0040U)
+#define LAN8742_ANLPAR_10BASE_T             ((uint16_t)0x0020U)
+#define LAN8742_ANLPAR_SELECTOR_FIELD       ((uint16_t)0x000FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANER_Bit_Definition LAN8742 ANER Bit Definition
+  * @{
+  */
+#define LAN8742_ANER_RX_NP_LOCATION_ABLE    ((uint16_t)0x0040U)
+#define LAN8742_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
+#define LAN8742_ANER_PARALLEL_DETECT_FAULT  ((uint16_t)0x0010U)
+#define LAN8742_ANER_LP_NP_ABLE             ((uint16_t)0x0008U)
+#define LAN8742_ANER_NP_ABLE                ((uint16_t)0x0004U)
+#define LAN8742_ANER_PAGE_RECEIVED          ((uint16_t)0x0002U)
+#define LAN8742_ANER_LP_AUTONEG_ABLE        ((uint16_t)0x0001U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANNPTR_Bit_Definition LAN8742 ANNPTR Bit Definition
+  * @{
+  */
+#define LAN8742_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
+#define LAN8742_ANNPTR_MESSAGE_PAGE      ((uint16_t)0x2000U)
+#define LAN8742_ANNPTR_ACK2              ((uint16_t)0x1000U)
+#define LAN8742_ANNPTR_TOGGLE            ((uint16_t)0x0800U)
+#define LAN8742_ANNPTR_MESSAGGE_CODE     ((uint16_t)0x07FFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ANNPRR_Bit_Definition LAN8742 ANNPRR Bit Definition
+  * @{
+  */
+#define LAN8742_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
+#define LAN8742_ANNPRR_ACK               ((uint16_t)0x4000U)
+#define LAN8742_ANNPRR_MESSAGE_PAGE      ((uint16_t)0x2000U)
+#define LAN8742_ANNPRR_ACK2              ((uint16_t)0x1000U)
+#define LAN8742_ANNPRR_TOGGLE            ((uint16_t)0x0800U)
+#define LAN8742_ANNPRR_MESSAGGE_CODE     ((uint16_t)0x07FFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_MMDACR_Bit_Definition LAN8742 MMDACR Bit Definition
+  * @{
+  */
+#define LAN8742_MMDACR_MMD_FUNCTION       ((uint16_t)0xC000U) 
+#define LAN8742_MMDACR_MMD_FUNCTION_ADDR  ((uint16_t)0x0000U)
+#define LAN8742_MMDACR_MMD_FUNCTION_DATA  ((uint16_t)0x4000U)
+#define LAN8742_MMDACR_MMD_DEV_ADDR       ((uint16_t)0x001FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_ENCTR_Bit_Definition LAN8742 ENCTR Bit Definition
+  * @{
+  */
+#define LAN8742_ENCTR_TX_ENABLE             ((uint16_t)0x8000U)
+#define LAN8742_ENCTR_TX_TIMER              ((uint16_t)0x6000U)
+#define LAN8742_ENCTR_TX_TIMER_1S           ((uint16_t)0x0000U)
+#define LAN8742_ENCTR_TX_TIMER_768MS        ((uint16_t)0x2000U)
+#define LAN8742_ENCTR_TX_TIMER_512MS        ((uint16_t)0x4000U)
+#define LAN8742_ENCTR_TX_TIMER_265MS        ((uint16_t)0x6000U)
+#define LAN8742_ENCTR_RX_ENABLE             ((uint16_t)0x1000U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL       ((uint16_t)0x0C00U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_64MS  ((uint16_t)0x0000U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
+#define LAN8742_ENCTR_RX_MAX_INTERVAL_1S    ((uint16_t)0x0C00U)
+#define LAN8742_ENCTR_EX_CROSS_OVER         ((uint16_t)0x0002U)
+#define LAN8742_ENCTR_EX_MANUAL_CROSS_OVER  ((uint16_t)0x0001U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_MCSR_Bit_Definition LAN8742 MCSR Bit Definition
+  * @{
+  */
+#define LAN8742_MCSR_EDPWRDOWN        ((uint16_t)0x2000U)
+#define LAN8742_MCSR_FARLOOPBACK      ((uint16_t)0x0200U)
+#define LAN8742_MCSR_ALTINT           ((uint16_t)0x0040U)
+#define LAN8742_MCSR_ENERGYON         ((uint16_t)0x0002U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_SMR_Bit_Definition LAN8742 SMR Bit Definition
+  * @{
+  */
+#define LAN8742_SMR_MODE       ((uint16_t)0x00E0U)
+#define LAN8742_SMR_PHY_ADDR   ((uint16_t)0x001FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_TPDCR_Bit_Definition LAN8742 TPDCR Bit Definition
+  * @{
+  */
+#define LAN8742_TPDCR_DELAY_IN                 ((uint16_t)0x8000U)
+#define LAN8742_TPDCR_LINE_BREAK_COUNTER       ((uint16_t)0x7000U)
+#define LAN8742_TPDCR_PATTERN_HIGH             ((uint16_t)0x0FC0U)
+#define LAN8742_TPDCR_PATTERN_LOW              ((uint16_t)0x003FU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_TCSR_Bit_Definition LAN8742 TCSR Bit Definition
+  * @{
+  */
+#define LAN8742_TCSR_TDR_ENABLE           ((uint16_t)0x8000U)
+#define LAN8742_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
+#define LAN8742_TCSR_TDR_CH_CABLE_TYPE    ((uint16_t)0x0600U)
+#define LAN8742_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
+#define LAN8742_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
+#define LAN8742_TCSR_TDR_CH_CABLE_OPEN    ((uint16_t)0x0400U)
+#define LAN8742_TCSR_TDR_CH_CABLE_MATCH   ((uint16_t)0x0600U)
+#define LAN8742_TCSR_TDR_CH_STATUS        ((uint16_t)0x0100U)
+#define LAN8742_TCSR_TDR_CH_LENGTH        ((uint16_t)0x00FFU)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_SCSIR_Bit_Definition LAN8742 SCSIR Bit Definition
+  * @{
+  */
+#define LAN8742_SCSIR_AUTO_MDIX_ENABLE    ((uint16_t)0x8000U)
+#define LAN8742_SCSIR_CHANNEL_SELECT      ((uint16_t)0x2000U)
+#define LAN8742_SCSIR_SQE_DISABLE         ((uint16_t)0x0800U)
+#define LAN8742_SCSIR_XPOLALITY           ((uint16_t)0x0010U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_CLR_Bit_Definition LAN8742 CLR Bit Definition
+  * @{
+  */
+#define LAN8742_CLR_CABLE_LENGTH       ((uint16_t)0xF000U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_IMR_ISFR_Bit_Definition LAN8742 IMR ISFR Bit Definition
+  * @{
+  */
+#define LAN8742_INT_8       ((uint16_t)0x0100U)
+#define LAN8742_INT_7       ((uint16_t)0x0080U)
+#define LAN8742_INT_6       ((uint16_t)0x0040U)
+#define LAN8742_INT_5       ((uint16_t)0x0020U)
+#define LAN8742_INT_4       ((uint16_t)0x0010U)
+#define LAN8742_INT_3       ((uint16_t)0x0008U)
+#define LAN8742_INT_2       ((uint16_t)0x0004U)
+#define LAN8742_INT_1       ((uint16_t)0x0002U)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_PHYSCSR_Bit_Definition LAN8742 PHYSCSR Bit Definition
+  * @{
+  */
+#define LAN8742_PHYSCSR_AUTONEGO_DONE   ((uint16_t)0x1000U)
+#define LAN8742_PHYSCSR_HCDSPEEDMASK    ((uint16_t)0x001CU)
+#define LAN8742_PHYSCSR_10BT_HD         ((uint16_t)0x0004U)
+#define LAN8742_PHYSCSR_10BT_FD         ((uint16_t)0x0014U)
+#define LAN8742_PHYSCSR_100BTX_HD       ((uint16_t)0x0008U)
+#define LAN8742_PHYSCSR_100BTX_FD       ((uint16_t)0x0018U) 
+/**
+  * @}
+  */
+    
+/** @defgroup LAN8742_Status LAN8742 Status
+  * @{
+  */    
+
+#define  LAN8742_STATUS_READ_ERROR            ((int32_t)-5)
+#define  LAN8742_STATUS_WRITE_ERROR           ((int32_t)-4)
+#define  LAN8742_STATUS_ADDRESS_ERROR         ((int32_t)-3)
+#define  LAN8742_STATUS_RESET_TIMEOUT         ((int32_t)-2)
+#define  LAN8742_STATUS_ERROR                 ((int32_t)-1)
+#define  LAN8742_STATUS_OK                    ((int32_t) 0)
+#define  LAN8742_STATUS_LINK_DOWN             ((int32_t) 1)
+#define  LAN8742_STATUS_100MBITS_FULLDUPLEX   ((int32_t) 2)
+#define  LAN8742_STATUS_100MBITS_HALFDUPLEX   ((int32_t) 3)
+#define  LAN8742_STATUS_10MBITS_FULLDUPLEX    ((int32_t) 4)
+#define  LAN8742_STATUS_10MBITS_HALFDUPLEX    ((int32_t) 5)
+#define  LAN8742_STATUS_AUTONEGO_NOTDONE      ((int32_t) 6)
+/**
+  * @}
+  */
+
+/** @defgroup LAN8742_IT_Flags LAN8742 IT Flags
+  * @{
+  */     
+#define  LAN8742_WOL_IT                        LAN8742_INT_8
+#define  LAN8742_ENERGYON_IT                   LAN8742_INT_7
+#define  LAN8742_AUTONEGO_COMPLETE_IT          LAN8742_INT_6
+#define  LAN8742_REMOTE_FAULT_IT               LAN8742_INT_5
+#define  LAN8742_LINK_DOWN_IT                  LAN8742_INT_4
+#define  LAN8742_AUTONEGO_LP_ACK_IT            LAN8742_INT_3
+#define  LAN8742_PARALLEL_DETECTION_FAULT_IT   LAN8742_INT_2
+#define  LAN8742_AUTONEGO_PAGE_RECEIVED_IT     LAN8742_INT_1
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported types ------------------------------------------------------------*/ 
+/** @defgroup LAN8742_Exported_Types LAN8742 Exported Types
+  * @{
+  */
+typedef int32_t  (*lan8742_Init_Func) (void); 
+typedef int32_t  (*lan8742_DeInit_Func) (void);
+typedef int32_t  (*lan8742_ReadReg_Func)   (uint32_t, uint32_t, uint32_t *);
+typedef int32_t  (*lan8742_WriteReg_Func)  (uint32_t, uint32_t, uint32_t);
+typedef int32_t  (*lan8742_GetTick_Func)  (void);
+
+typedef struct 
+{                   
+  lan8742_Init_Func      Init; 
+  lan8742_DeInit_Func    DeInit;
+  lan8742_WriteReg_Func  WriteReg;
+  lan8742_ReadReg_Func   ReadReg; 
+  lan8742_GetTick_Func   GetTick;   
+} lan8742_IOCtx_t;  
+
+  
+typedef struct 
+{
+  uint32_t            DevAddr;
+  uint32_t            Is_Initialized;
+  lan8742_IOCtx_t     IO;
+  void               *pData;
+}lan8742_Object_t;
+/**
+  * @}
+  */ 
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup LAN8742_Exported_Functions LAN8742 Exported Functions
+  * @{
+  */
+int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx);
+int32_t LAN8742_Init(lan8742_Object_t *pObj);
+int32_t LAN8742_DeInit(lan8742_Object_t *pObj);
+int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj);
+int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj);
+int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj);
+int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj);
+int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState);
+int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj);
+int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj);
+int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
+int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
+int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt);
+int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt);
+/**
+  * @}
+  */ 
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* LAN8742_H */
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */       
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/lwip/ports/drivers/stm32h7/port_conf.h b/lwip/ports/drivers/stm32h7/port_conf.h
new file mode 100644
index 0000000..06c130d
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/port_conf.h
@@ -0,0 +1,44 @@
+#ifndef RTEMS_LWIP_LWIP_PORTS_DRIVERS_STM32H7_RTEMS_CONF_H_
+#define RTEMS_LWIP_LWIP_PORTS_DRIVERS_STM32H7_RTEMS_CONF_H_
+
+#include "lwipopts.h"
+
+/* RTEMS priorities range from 1 (highest) to 255 (lowest) */
+#ifndef RTEMS_LWIP_INTERFACE_THREAD_PRIORITY
+#define RTEMS_LWIP_INTERFACE_THREAD_PRIORITY    ( 50 )
+#endif
+
+/* Stack size of the interface thread */
+#ifndef RTEMS_LWIP_INTERFACE_THREAD_STACK_SIZE
+#define RTEMS_LWIP_INTERFACE_THREAD_STACK_SIZE  ( RTEMS_MINIMUM_STACK_SIZE )
+#endif
+
+#ifndef RTEMS_LWIP_ETH_DMA_TRANSMIT_TIMEOUT
+#define RTEMS_LWIP_ETH_DMA_TRANSMIT_TIMEOUT     ( 20U )
+#endif
+
+/* The MPU protection is unreliable for the Socket API. The exact cause is not know yet.
+It's safer to always clean data cache for now */
+#ifndef RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU
+#define RTEMS_LWIP_PROTECT_LWIP_HEAP_WITH_MPU     1
+#endif
+
+#ifndef RTEMS_LWIP_DHCP_PRINTOUT
+#define RTEMS_LWIP_DHCP_PRINTOUT                  1
+#endif
+
+#ifndef LWIP_RAM_HEAP_POINTER
+#define LWIP_RAM_HEAP_POINTER                     (0x30040000)
+#endif
+
+#ifndef MEM_SIZE
+#define MEM_SIZE                                  (8 * 1024)
+#endif
+
+#if NO_SYS == 1
+#ifndef RTEMS_LWIP_DHCP_TASK_INTERVAL_MS
+#define RTEMS_LWIP_DHCP_TASK_INTERVAL_MS 500
+#endif
+#endif /* NO_SYS == 1 */
+
+#endif /* RTEMS_LWIP_LWIP_PORTS_DRIVERS_STM32H7_RTEMS_CONF_H_ */
diff --git a/lwip/ports/drivers/stm32h7/template/lwipopts_template.h b/lwip/ports/drivers/stm32h7/template/lwipopts_template.h
new file mode 100644
index 0000000..b5f4b58
--- /dev/null
+++ b/lwip/ports/drivers/stm32h7/template/lwipopts_template.h
@@ -0,0 +1,292 @@
+/**
+  ******************************************************************************
+  * @file    LwIP/LwIP_HTTP_Server_Netconn_RTOS/Inc/lwipopts.h
+  * @author  MCD Application Team
+  * @brief   lwIP Options Configuration.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>© Copyright (c) 2017 STMicroelectronics International N.V.
+  * All rights reserved.</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted, provided that the following conditions are met:
+  *
+  * 1. Redistribution of source code must retain the above copyright notice,
+  *    this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright notice,
+  *    this list of conditions and the following disclaimer in the documentation
+  *    and/or other materials provided with the distribution.
+  * 3. Neither the name of STMicroelectronics nor the names of other
+  *    contributors to this software may be used to endorse or promote products
+  *    derived from this software without specific written permission.
+  * 4. This software, including modifications and/or derivative works of this
+  *    software, must execute solely and exclusively on microcontroller or
+  *    microprocessor devices manufactured by or for STMicroelectronics.
+  * 5. Redistribution and use of this software other than as permitted under
+  *    this license is void and will automatically terminate your rights under
+  *    this license.
+  *
+  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
+  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
+  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
+  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+#ifdef __rtems__
+#include "bsp.h"
+#endif
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT        0
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS                      1
+
+#define LWIP_NETIF_API              0
+
+/* ---------- Memory options ---------- */
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+   byte alignment -> define MEM_ALIGNMENT to 2. */
+#define MEM_ALIGNMENT               4
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#define MEM_SIZE                    (8*1024)
+
+/* Relocate the LwIP RAM heap pointer. Place in SRAM3 */
+#define LWIP_RAM_HEAP_POINTER       (0x30040000)
+
+/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
+   sends a lot of data out of ROM (or other static memory), this
+   should be set high. */
+#define MEMP_NUM_PBUF               10
+/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+   per active UDP "connection". */
+#define MEMP_NUM_UDP_PCB            6
+/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
+   connections. */
+#define MEMP_NUM_TCP_PCB            10
+/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
+   connections. */
+#define MEMP_NUM_TCP_PCB_LISTEN     5
+/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
+   segments. */
+#define MEMP_NUM_TCP_SEG            8
+/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
+   timeouts. */
+#define MEMP_NUM_SYS_TIMEOUT        10
+
+
+/* ---------- Pbuf options ---------- */
+/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
+   @ note: used to allocate Tx pbufs only */
+#define PBUF_POOL_SIZE              4
+
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#define PBUF_POOL_BUFSIZE           1528
+
+/* LWIP_SUPPORT_CUSTOM_PBUF == 1: to pass directly MAC Rx buffers to the stack
+   no copy is needed */
+#define LWIP_SUPPORT_CUSTOM_PBUF    1
+
+/* ---------- IPv4 options ---------- */
+#define LWIP_IPV4                   1
+
+/* ---------- TCP options ---------- */
+#define LWIP_TCP                    1
+#define TCP_TTL                     255
+
+/* Controls if TCP should queue segments that arrive out of
+   order. Define to 0 if your device is low on memory. */
+#define TCP_QUEUE_OOSEQ             0
+
+/* TCP Maximum segment size. */
+#define TCP_MSS                     (1500 - 40)   /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
+
+/* TCP sender buffer space (bytes). */
+#define TCP_SND_BUF                 (4*TCP_MSS)
+
+/*  TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
+  as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
+
+#define TCP_SND_QUEUELEN            (2* TCP_SND_BUF/TCP_MSS)
+
+/* TCP receive window. */
+#define TCP_WND                     (2*TCP_MSS)
+
+/* ---------- ICMP options ---------- */
+#define LWIP_ICMP                   1
+
+/* ---------- DHCP options ---------- */
+#define LWIP_DHCP                   1
+
+/* ---------- UDP options ---------- */
+#define LWIP_UDP                    1
+#define UDP_TTL                     255
+
+/* ---------- link callback options ---------- */
+/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
+ * whenever the link changes (i.e., link down)
+ */
+#define LWIP_NETIF_LINK_CALLBACK    1
+
+
+/* Static IP ADDRESS */
+#define IP_ADDR0   169
+#define IP_ADDR1   254
+#define IP_ADDR2   1
+#define IP_ADDR3   38
+
+/* NETMASK */
+#define NETMASK_ADDR0   255
+#define NETMASK_ADDR1   255
+#define NETMASK_ADDR2   0
+#define NETMASK_ADDR3   0
+
+/* Gateway Address */
+#define GW_ADDR0   192
+#define GW_ADDR1   168
+#define GW_ADDR2   178
+#define GW_ADDR3   1
+
+
+/*
+   --------------------------------------
+   ---------- Checksum options ----------
+   --------------------------------------
+*/
+
+/*
+The STM32H7xx allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
+ - To use this feature let the following define uncommented.
+ - To disable it and process by CPU comment the  the checksum.
+*/
+#define CHECKSUM_BY_HARDWARE
+
+
+#ifdef CHECKSUM_BY_HARDWARE
+  /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
+  #define CHECKSUM_GEN_IP                 0
+  /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
+  #define CHECKSUM_GEN_UDP                0
+  /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
+  #define CHECKSUM_GEN_TCP                0
+  /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
+  #define CHECKSUM_CHECK_IP               0
+  /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
+  #define CHECKSUM_CHECK_UDP              0
+  /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
+  #define CHECKSUM_CHECK_TCP              0
+  /* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
+  #define CHECKSUM_GEN_ICMP               0
+#else
+  /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
+  #define CHECKSUM_GEN_IP                 1
+  /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
+  #define CHECKSUM_GEN_UDP                1
+  /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
+  #define CHECKSUM_GEN_TCP                1
+  /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
+  #define CHECKSUM_CHECK_IP               1
+  /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
+  #define CHECKSUM_CHECK_UDP              1
+  /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
+  #define CHECKSUM_CHECK_TCP              1
+  /* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/
+  #define CHECKSUM_GEN_ICMP               1
+#endif
+
+
+/*
+   ----------------------------------------------
+   ---------- Sequential layer options ----------
+   ----------------------------------------------
+*/
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN                    0
+
+/*
+   ------------------------------------
+   ---------- Socket options ----------
+   ------------------------------------
+*/
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET                     0
+
+/*
+   ------------------------------------
+   ---------- httpd options ----------
+   ------------------------------------
+*/
+/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the
+ * file system (to prevent changing the file included in CVS) */
+#define HTTPD_USE_CUSTOM_FSDATA   1
+
+
+/*
+   ---------------------------------
+   ---------- OS options ----------
+   ---------------------------------
+*/
+
+#ifdef __rtems__
+#define TCPIP_THREAD_NAME              "LWIP"
+#define TCPIP_THREAD_STACKSIZE          RTEMS_MINIMUM_STACK_SIZE
+#define TCPIP_MBOX_SIZE                 6
+#define DEFAULT_UDP_RECVMBOX_SIZE       6
+#define DEFAULT_TCP_RECVMBOX_SIZE       6
+#define DEFAULT_ACCEPTMBOX_SIZE         6
+#define DEFAULT_THREAD_STACKSIZE        500
+#define TCPIP_THREAD_PRIO               60
+#endif /* __rtems__ */
+
+/*
+   ---------------------------------
+   ---------- ASSERT options ----------
+   ---------------------------------
+*/
+#define LWIP_NOASSERT
+
+
+#define ETH_MAC_ADDR0    ((uint8_t)0x02)
+#define ETH_MAC_ADDR1    ((uint8_t)0x00)
+#define ETH_MAC_ADDR2    ((uint8_t)0x00)
+#define ETH_MAC_ADDR3    ((uint8_t)0x00)
+#define ETH_MAC_ADDR4    ((uint8_t)0x00)
+#define ETH_MAC_ADDR5    ((uint8_t)0x00)
+#define ETH_MAC_ADDR     { ETH_MAC_ADDR0, ETH_MAC_ADDR1, \
+                           ETH_MAC_ADDR2, ETH_MAC_ADDR3, \
+                           ETH_MAC_ADDR4, ETH_MAC_ADDR5 }
+
+/* #undef LWIP_DEBUG */
+
+#endif /* __LWIPOPTS_H__ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff --git a/lwip/ports/drivers/tms570_netif.h b/lwip/ports/drivers/tms570/include/rtems_lwip/tms570_netif.h
similarity index 74%
rename from lwip/ports/drivers/tms570_netif.h
rename to lwip/ports/drivers/tms570/include/rtems_lwip/tms570_netif.h
index 325249a..6636f3f 100644
--- a/lwip/ports/drivers/tms570_netif.h
+++ b/lwip/ports/drivers/tms570/include/rtems_lwip/tms570_netif.h
@@ -36,6 +36,37 @@
 
 //#define TMS570_NETIF_DEBUG 1
 
+/**
+ * While scanning phy addresses no alive phy was found.
+ * Return value of rpp_eth_hw_init() function.
+ */
+#define NO_PHY_ALIVE             -1
+/**
+ * Scanning default phy address, it was found it's not alive.
+ * Return value of rpp_eth_hw_init() function.
+ */
+#define DFLT_PHY_NOT_ALIVE       -1
+/**
+ * When setting autonegotiation parameters to EMAC module, there was found impossible mode (usually on timeout of autonegotiation).
+ * Return value of rpp_eth_hw_init_postInit() function.
+ */
+#define UNKN_DUPLEX_MODE         -2 /* this could mean that autonegotiation was not completed yet */
+/**
+ * Phy is down error.
+ * Return value of rpp_eth_init_postInit() function.
+ */
+#define PHY_LINK_DOWN            -3
+
+/**
+ * Memory requirements couldn't be satisfied.
+ */
+#define DHCP_MEM_ERR             -11
+
+/**
+ * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
+ */
+#define MAC_BIG_LETTERS           1
+
 #ifdef TMS570_NETIF_DEBUG
 #define tms570_eth_debug_printf sys_arch_printk
 #else
diff --git a/lwip/ports/drivers/phy_dp83848h.c b/lwip/ports/drivers/tms570/phy_dp83848h.c
similarity index 100%
rename from lwip/ports/drivers/phy_dp83848h.c
rename to lwip/ports/drivers/tms570/phy_dp83848h.c
diff --git a/lwip/ports/drivers/phy_dp83848h.h b/lwip/ports/drivers/tms570/phy_dp83848h.h
similarity index 100%
rename from lwip/ports/drivers/phy_dp83848h.h
rename to lwip/ports/drivers/tms570/phy_dp83848h.h
diff --git a/lwip/ports/drivers/tms570/template/lwipopts_template.h b/lwip/ports/drivers/tms570/template/lwipopts_template.h
new file mode 100644
index 0000000..fb55e7a
--- /dev/null
+++ b/lwip/ports/drivers/tms570/template/lwipopts_template.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ * 
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef LWIP_HDR_LWIPOPTS_H__
+#define LWIP_HDR_LWIPOPTS_H__
+
+/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
+#define NO_SYS                          0
+#define LWIP_NETCONN                    1
+#define LWIP_SOCKET                     1
+#define LWIP_DNS                        1
+
+#define LWIP_IPV6                       1
+#define LWIP_IPV4                       1
+
+#define LWIP_ETHERNET                   1
+#define LWIP_NETIF_API                  1
+/* Enable DHCP to test it, disable UDP checksum to easier inject packets */
+#define LWIP_DHCP                       1
+#define LWIP_TIMEVAL_PRIVATE            0
+#define LWIP_POSIX_SOCKETS_IO_NAMES     0
+
+/* Minimal changes to opt.h required for tcp unit tests: */
+#define MEM_SIZE                        16000
+#define TCP_SND_QUEUELEN                40
+#define MEMP_NUM_TCP_SEG                TCP_SND_QUEUELEN
+#define TCP_SND_BUF                     (12 * TCP_MSS)
+#define TCP_WND                         (10 * TCP_MSS)
+#define LWIP_WND_SCALE                  1
+#define TCP_RCV_SCALE                   0
+#define PBUF_POOL_SIZE                  400 // pbuf tests need ~200KByte
+
+/* Minimal changes to opt.h required for etharp unit tests: */
+#define ETHARP_SUPPORT_STATIC_ENTRIES   1
+
+#define ETH_IP_ADDR               0xC0A8F701 /* 192.168.247.1   */
+#define ETH_NETMASK               0xFFFFFF00 /* 255.255.255.0   */
+#define ETH_GW                    0xC0A8F7FE /* 192.168.247.254 */
+
+#define LWIP_NETIF_LINK_CALLBACK        1
+
+void tms570_eth_memp_avaible(int type);
+
+/*called from memp_free() when a memp pool was empty and an item is now available*/
+#define LWIP_HOOK_MEMP_AVAILABLE tms570_eth_memp_avaible
+
+#endif /* LWIP_HDR_LWIPOPTS_H__ */
diff --git a/lwip/ports/drivers/ti_drv_emac.h b/lwip/ports/drivers/tms570/ti_drv_emac.h
similarity index 100%
rename from lwip/ports/drivers/ti_drv_emac.h
rename to lwip/ports/drivers/tms570/ti_drv_emac.h
diff --git a/lwip/ports/drivers/ti_drv_mdio.h b/lwip/ports/drivers/tms570/ti_drv_mdio.h
similarity index 100%
rename from lwip/ports/drivers/ti_drv_mdio.h
rename to lwip/ports/drivers/tms570/ti_drv_mdio.h
diff --git a/lwip/ports/drivers/tms570_emac.h b/lwip/ports/drivers/tms570/tms570_emac.h
similarity index 100%
rename from lwip/ports/drivers/tms570_emac.h
rename to lwip/ports/drivers/tms570/tms570_emac.h
diff --git a/lwip/ports/drivers/tms570_netif.c b/lwip/ports/drivers/tms570/tms570_netif.c
similarity index 99%
rename from lwip/ports/drivers/tms570_netif.c
rename to lwip/ports/drivers/tms570/tms570_netif.c
index 8d14687..2c99362 100644
--- a/lwip/ports/drivers/tms570_netif.c
+++ b/lwip/ports/drivers/tms570/tms570_netif.c
@@ -54,13 +54,15 @@
 #include <bsp/tms570.h>
 #include <bsp/tms570-pinmux.h>
 #include "arch/cc.h"
-#include "eth_lwip.h"
+#include "rtems_lwip.h"
 #include "tms570_netif.h"
 #include "ti_drv_emac.h"
 #include "ti_drv_mdio.h"
 #include "phy_dp83848h.h"
 #include "tms570_emac.h"
 
+netif_init_fn eth_lwip_init_fnc = &tms570_eth_init_netif;
+
 #define LINK_SPEED_OF_YOUR_NETIF_IN_BPS 10000000
 
 /* Number of EMAC Instances */
@@ -150,6 +152,7 @@ static err_t tms570_eth_init_control_structures(struct netif *netif);
 static void tms570_eth_init_netif_fill(struct netif *netif);
 static void tms570_eth_init_buffer_descriptors(struct tms570_netif_state *nf_state);
 static void tms570_eth_init_set_pinmux();
+static void sys_arch_data_sync_barier();
 
 /***** initializing functions **********************************************/
 
@@ -1122,10 +1125,12 @@ tms570_eth_memp_avaible(int type)
     return;
   if (type != MEMP_PBUF_POOL)
     return;
-  netifapi_netif_common(eth_lwip_get_netif(0), tms570_eth_rx_pbuf_refill_single, NULL);
+  netifapi_netif_common(rtems_lwip_get_netif(0), tms570_eth_rx_pbuf_refill_single, NULL);
 }
 
-
+void sys_arch_data_sync_barier() {
+    _ARM_Data_synchronization_barrier();
+}
 
 #if TMS570_NETIF_DEBUG
 
diff --git a/lwip/ports/os/rtems/arch/cc.h b/lwip/ports/os/rtems/arch/cc.h
index 84138ff..0e298c7 100644
--- a/lwip/ports/os/rtems/arch/cc.h
+++ b/lwip/ports/os/rtems/arch/cc.h
@@ -39,6 +39,9 @@
 #ifndef __CC_H__
 #define __CC_H__
 
+/* Use timeval provided by RTEMS be defining this to 0 */
+#define LWIP_TIMEVAL_PRIVATE 0
+
 #include <stdio.h>
 #include <rtems/malloc.h>  /*printk*/
 #include <inttypes.h>
diff --git a/lwip/ports/os/rtems/arch/sys_arch.c b/lwip/ports/os/rtems/arch/sys_arch.c
index ca7f8be..5fd8064 100644
--- a/lwip/ports/os/rtems/arch/sys_arch.c
+++ b/lwip/ports/os/rtems/arch/sys_arch.c
@@ -37,15 +37,21 @@
  * DETAILS: ./lwip/doc/sys_arch.txt
  */
 
+/* lwIP includes. */
+#include "lwip/debug.h"
+#include "lwip/def.h"
+#include "lwip/sys.h"
+#include "lwip/mem.h"
+#include "lwip/stats.h"
+
+#if !NO_SYS
+
+#include "sys_arch.h"
 #include <stdint.h>
 #include <arch/cc.h>
 #include <rtems/rtems/clock.h>
 #include <rtems/rtems/sem.h>
 #include <rtems.h>
-#include "sys_arch.h"
-#include "lwip/err.h"
-#include "lwip/tcpip.h"
-#include "lwipopts.h"
 
 #define SYS_LWIP_MBOX_SIZE (sizeof(void *))
 
@@ -268,8 +274,21 @@ sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stack_s
   rtems_id id;
   rtems_status_code res;
 
+  rtems_name lwip_task_name = 0;
+  if(name == NULL) {
+    lwip_task_name = rtems_build_name('L', 'W', 'I', 'P');
+  }
+  else {
+    if(name[0] == '\0') {
+      lwip_task_name = rtems_build_name('L', 'W', 'I', 'P');
+    }
+    else {
+      lwip_task_name = rtems_build_name(name[0], name[1], name[2], name[3]);
+    }
+  }
+
   res = rtems_task_create(
-    rtems_build_name('L', 'W', 'I', 'P'),
+    lwip_task_name,
     prio,
     stack_size,
     RTEMS_PREEMPT,
@@ -376,3 +395,5 @@ sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
   return sys_mbox_trypost(q, msg);
 }
 
+#endif /* NO_SYS == 0 */
+
diff --git a/lwip/ports/os/rtems/arch/sys_arch.h b/lwip/ports/os/rtems/arch/sys_arch.h
index c89abd4..f4a73a7 100644
--- a/lwip/ports/os/rtems/arch/sys_arch.h
+++ b/lwip/ports/os/rtems/arch/sys_arch.h
@@ -39,17 +39,23 @@
 #ifndef __ARCH_SYS_ARCH_H__
 #define __ARCH_SYS_ARCH_H__
 
+#include "lwip/opt.h"
+
+#if (NO_SYS != 0)
+#error "RTEMS SYS_ARCH cannot be compiled in NO_SYS variant"
+#endif
+
 #include <rtems/rtems/sem.h>
 #include <rtems/rtems/intr.h>
 #include <rtems/score/cpu.h>
 #include <bsp/irq-generic.h>
-//#include "eth_lwip_default.h"
 
-/* Typedefs for the various port-specific types. */
-#if defined(NO_SYS) && NO_SYS
-  #error "RTEMS SYS_ARCH cannot be compiled in NO_SYS variant"
+#ifdef __cplusplus
+extern "C" {
 #endif
 
+/* Typedefs for the various port-specific types. */
+
 #define sys_arch_printk printk
 
 typedef struct {
@@ -105,4 +111,8 @@ sys_prot_t sys_arch_protect();
 
 void sys_arch_unprotect(sys_prot_t pval);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* __ARCH_SYS_ARCH_H__ */
diff --git a/lwip/ports/os/rtems/defaults/lwipopts.h b/lwip/ports/os/rtems/defaults/lwipopts.h
new file mode 100644
index 0000000..12fe795
--- /dev/null
+++ b/lwip/ports/os/rtems/defaults/lwipopts.h
@@ -0,0 +1,37 @@
+#ifndef RTEMS_LWIP_LWIP_PORTS_OS_RTEMS_LWIPOPTS_H_
+#define RTEMS_LWIP_LWIP_PORTS_OS_RTEMS_LWIPOPTS_H_
+
+/**
+ * @brief   This is the default lwipopts.h file which will be used if none is supplied by the
+ *          user.
+ * @details
+ * This might not work on each port depending on which configuration options are used
+ * and required by the port
+ */
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS                          0
+
+/* DHCP will be enabled by default */
+#define LWIP_DHCP                       1
+
+/* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) */
+#define LWIP_NETCONN                    1
+
+/* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) */
+#define LWIP_SOCKET                     1
+
+/* OS specific options */
+#define TCPIP_THREAD_NAME              "LWIP"
+#define TCPIP_THREAD_STACKSIZE          RTEMS_MINIMUM_STACK_SIZE
+#define TCPIP_MBOX_SIZE                 6
+#define DEFAULT_UDP_RECVMBOX_SIZE       6
+#define DEFAULT_TCP_RECVMBOX_SIZE       6
+#define DEFAULT_ACCEPTMBOX_SIZE         6
+#define DEFAULT_THREAD_STACKSIZE        500
+#define TCPIP_THREAD_PRIO               60
+
+#endif /* RTEMS_LWIP_LWIP_PORTS_OS_RTEMS_LWIPOPTS_H_ */
diff --git a/lwip/src/include/lwip/sys.h b/lwip/src/include/lwip/sys.h
index 1933590..168e465 100644
--- a/lwip/src/include/lwip/sys.h
+++ b/lwip/src/include/lwip/sys.h
@@ -38,7 +38,6 @@
 #define LWIP_HDR_SYS_H
 
 #include "lwip/opt.h"
-#include "arch/sys_arch.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/lwip/ports/os/lwipopts.h b/lwip/test/lwipopts.h
similarity index 100%
rename from lwip/ports/os/lwipopts.h
rename to lwip/test/lwipopts.h
diff --git a/wscript b/wscript
index 0393e8c..48ea861 100644
--- a/wscript
+++ b/wscript
@@ -46,9 +46,11 @@ def init(ctx):
 
 def options(opt):
     rtems.options(opt)
+    lwip.options(opt)
 
 
 def configure(conf):
+    lwip.configure(conf)
     rtems.configure(conf)
 
 
-- 
2.27.0



More information about the devel mailing list