test public

Fork of Modbus by Cam Marshall

Files at this revision

API Documentation at this revision

Comitter:
TomTom83
Date:
Mon Jul 02 14:36:46 2018 +0000
Parent:
0:0453a0a7e500
Child:
2:9e76d51d9fb6
Commit message:
adaptation de bafian modbus

Changed in this revision

ethernetif.cpp Show annotated file Show diff for this revision Revisions of this file
ethernetif.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbconfig.h Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show diff for this revision Revisions of this file
mbtcp.cpp Show annotated file Show diff for this revision Revisions of this file
mbtcp.h Show annotated file Show diff for this revision Revisions of this file
netconf.cpp Show annotated file Show diff for this revision Revisions of this file
netconf.h Show annotated file Show diff for this revision Revisions of this file
port.h Show annotated file Show diff for this revision Revisions of this file
portother.cpp Show annotated file Show diff for this revision Revisions of this file
porttcp.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ethernetif.cpp	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,304 @@
+/**
+ * @file
+ * Ethernet Interface for standalone applications (without RTOS) - works only for 
+ * ethernet polling mode (polling for ethernet frame reception)
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 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: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#include "lwip/mem.h"
+#include "netif/etharp.h"
+#include "ethernetif.h"
+#include "main.h"
+#include <string.h>
+
+/* Network interface name */
+#define IFNAME0 's'
+#define IFNAME1 't'
+
+
+/* Ethernet Rx & Tx DMA Descriptors */
+extern ETH_DMADESCTypeDef  DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
+
+/* Ethernet Driver Receive buffers  */
+extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; 
+
+/* Ethernet Driver Transmit buffers */
+extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; 
+
+/* Global pointers to track current transmit and receive descriptors */
+extern ETH_DMADESCTypeDef  *DMATxDescToSet;
+extern ETH_DMADESCTypeDef  *DMARxDescToGet;
+
+/* Global pointer for last received frame infos */
+extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;
+
+
+
+
+/**
+ * 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)
+{
+#ifdef CHECKSUM_BY_HARDWARE
+  int i; 
+#endif
+  /* set MAC hardware address length */
+  netif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+  /* set MAC hardware address */
+  netif->hwaddr[0] =  MAC_ADDR0;
+  netif->hwaddr[1] =  MAC_ADDR1;
+  netif->hwaddr[2] =  MAC_ADDR2;
+  netif->hwaddr[3] =  MAC_ADDR3;
+  netif->hwaddr[4] =  MAC_ADDR4;
+  netif->hwaddr[5] =  MAC_ADDR5;
+  
+  /* initialize MAC address in ethernet MAC */ 
+  ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); 
+
+  /* maximum transfer unit */
+  netif->mtu = 1500;
+
+  /* device capabilities */
+  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
+  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+
+  /* Initialize Tx Descriptors list: Chain Mode */
+  ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
+  /* Initialize Rx Descriptors list: Chain Mode  */
+  ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
+  
+#ifdef CHECKSUM_BY_HARDWARE
+  /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */
+  for(i=0; i<ETH_TXBUFNB; i++)
+    {
+      ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
+    }
+#endif
+
+   /* Note: TCP, UDP, ICMP checksum checking for received frame are enabled in DMA config */
+
+  /* Enable MAC and DMA transmission and reception */
+  ETH_Start();
+
+}
+
+/**
+ * This function should do the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
+ * @return ERR_OK if the packet could be sent
+ *         an err_t value if the packet couldn't be sent
+ *
+ * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
+ *       strange results. You might consider waiting for space in the DMA queue
+ *       to become availale since the stack doesn't retry to send a packet
+ *       dropped because of memory failure (except for the TCP timers).
+ */
+
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+  struct pbuf *q;
+  int framelength = 0;
+  u8 *buffer =  (u8 *)(DMATxDescToSet->Buffer1Addr);
+  
+  /* copy frame from pbufs to driver buffers */
+  for(q = p; q != NULL; q = q->next) 
+  {
+    memcpy((u8_t*)&buffer[framelength], q->payload, q->len);
+	framelength = framelength + q->len;
+  }
+  
+  /* Note: padding and CRC for transmitted frame 
+     are automatically inserted by DMA */
+
+  /* Prepare transmit descriptors to give to DMA*/ 
+  ETH_Prepare_Transmit_Descriptors(framelength);
+
+  return ERR_OK;
+}
+
+/**
+ * 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, *q;
+  u16_t len;
+  int l =0;
+  FrameTypeDef frame;
+  u8 *buffer;
+  uint32_t i=0;
+  __IO ETH_DMADESCTypeDef *DMARxNextDesc;
+  
+  
+  p = NULL;
+  
+  /* get received frame */
+  frame = ETH_Get_Received_Frame();
+  
+  /* Obtain the size of the packet and put it into the "len" variable. */
+  len = frame.length;
+  buffer = (u8 *)frame.buffer;
+  
+  /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
+  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+  
+  /* copy received frame to pbuf chain */
+  if (p != NULL)
+  {
+    for (q = p; q != NULL; q = q->next)
+    {
+      memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
+      l = l + q->len;
+    }    
+  }
+  
+  /* Release descriptors to DMA */
+  /* Check if frame with multiple DMA buffer segments */
+  if (DMA_RX_FRAME_infos->Seg_Count > 1)
+  {
+    DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
+  }
+  else
+  {
+    DMARxNextDesc = frame.descriptor;
+  }
+  
+  /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
+  for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
+  {  
+    DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
+    DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
+  }
+  
+  /* Clear Segment_Count */
+  DMA_RX_FRAME_infos->Seg_Count =0;
+  
+  /* When Rx Buffer unavailable flag is set: clear it and resume reception */
+  if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)  
+  {
+    /* Clear RBUS ETHERNET DMA flag */
+    ETH->DMASR = ETH_DMASR_RBUS;
+    /* Resume DMA reception */
+    ETH->DMARPDR = 0;
+  }
+  return p;
+}
+
+/**
+ * This function should be called when a packet is ready to be read
+ * from the interface. It uses the function low_level_input() that
+ * should handle the actual reception of bytes from the network
+ * interface. Then the type of the received packet is determined and
+ * the appropriate input function is called.
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ */
+err_t 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 ERR_MEM;
+
+  /* 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;
+  }
+  return err;
+}
+
+/**
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ * This function should be passed as a parameter to netif_add().
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ * @return ERR_OK if the loopif is initialized
+ *         ERR_MEM if private data couldn't be allocated
+ *         any other err_t on error
+ */
+err_t ethernetif_init(struct netif *netif)
+{
+  LWIP_ASSERT("netif != NULL", (netif != NULL));
+  
+#if LWIP_NETIF_HOSTNAME
+  /* Initialize interface hostname */
+  netif->hostname = "RAIMA";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+  strncpy(netif->name,"RAIMA",5);
+
+  /* We directly use etharp_output() here to save a function call.
+   * You can instead declare your own function an call etharp_output()
+   * from it if you have to do some checks before sending (e.g. if link
+   * is available...) */
+  netif->output = etharp_output;
+  netif->linkoutput = low_level_output;
+
+  /* initialize the hardware */
+  low_level_init(netif);
+
+  return ERR_OK;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ethernetif.h	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,12 @@
+#ifndef __ETHERNETIF_H__
+#define __ETHERNETIF_H__
+
+
+#include "lwip/err.h"
+#include "lwip/netif.h"
+
+err_t ethernetif_init(struct netif *netif);
+err_t ethernetif_input(struct netif *netif);
+
+#endif
+
--- a/main.cpp	Thu Apr 15 12:10:34 2010 +0000
+++ b/main.cpp	Mon Jul 02 14:36:46 2018 +0000
@@ -22,12 +22,15 @@
 /* ----------------------- System includes --------------------------------*/
 
 /* ----------------------- Modbus includes ----------------------------------*/
+#include "mbed.h"
+#include "EthernetInterface.h"
 #include "mb.h"
 #include "mbport.h"
+#include "netconf.h"
 
 /* ----------------------- Defines ------------------------------------------*/
 #define REG_INPUT_START 1000
-#define REG_INPUT_NREGS 4
+#define REG_INPUT_NREGS 5
 #define SLAVE_ID 0x0A
 
 /* ----------------------- Static variables ---------------------------------*/
@@ -35,24 +38,39 @@
 static USHORT   usRegInputBuf[REG_INPUT_NREGS];
 
 /* ----------------------- Start implementation -----------------------------*/
+
+DigitalIn mybutton(USER_BUTTON);
+DigitalOut myled2(LED2);
+
 int
 main( void )
 {
     eMBErrorCode    eStatus;
 
-    eStatus = eMBInit( MB_RTU, SLAVE_ID, 0, 9600, MB_PAR_NONE );
-
+    //eStatus = eMBInit( MB_RTU, SLAVE_ID, 0, 9600, MB_PAR_NONE );
+    
+    EthernetInterface eth;
+    eth.set_network("169.254.178.1","255.255.0.0","169.254.178.3");
+    eth.connect();
+    
+    /* inicializacion del Stack de Modbus */
+    eMBTCPInit(502);
+    
     /* Enable the Modbus Protocol Stack. */
     eStatus = eMBEnable(  );
+    myled2=1;
     
     // Initialise some registers
-    usRegInputBuf[1] = 0x1234;
-    usRegInputBuf[2] = 0x5678;
-    usRegInputBuf[3] = 0x9abc;        
+    usRegInputBuf[1] = 83;
+    usRegInputBuf[2] = 65;
+    usRegInputBuf[3] = 76; 
+    usRegInputBuf[4] = 85;       
 
     for( ;; )
     {
         ( void )eMBPoll(  );
+        
+         LwIP_Pkt_Handle();
                 
         /* Here we simply count the number of poll cycles. */
         usRegInputBuf[0]++;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,110 @@
+/**
+  ******************************************************************************
+  * @file    main.h
+  * @author  MCD Application Team
+  * @version V1.1.0
+  * @date    31-July-2013 
+  * @brief   This file contains all the functions prototypes for the main.c 
+  *          file.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+//#define USE_LCD        /* enable LCD  */
+//#define USE_DHCP       /* enable DHCP, if disabled static address is used */
+   
+/* Uncomment SERIAL_DEBUG to enables retarget of printf to serial port (COM1 on STM32 evalboard) 
+   for debug purpose */   
+//#define SERIAL_DEBUG 
+
+ 
+/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
+#define IP_ADDR0   192
+#define IP_ADDR1   168
+#define IP_ADDR2   2
+#define IP_ADDR3   10
+   
+/*NETMASK*/
+#define NETMASK_ADDR0   255
+#define NETMASK_ADDR1   255
+#define NETMASK_ADDR2   255
+#define NETMASK_ADDR3   0
+
+/*Gateway Address*/
+#define GW_ADDR0   192
+#define GW_ADDR1   168
+#define GW_ADDR2   2
+#define GW_ADDR3   5
+
+/* MII and RMII mode selection, for STM324xG-EVAL Board(MB786) RevB ***********/
+//#define RMII_MODE  // User have to provide the 50 MHz clock by soldering a 50 MHz
+                     // oscillator (ref SM7745HEV-50.0M or equivalent) on the U3
+                     // footprint located under CN3 and also removing jumper on JP5. 
+                     // This oscillator is not provided with the board. 
+                     // For more details, please refer to STM3240G-EVAL evaluation
+                     // board User manual (UM1461).
+
+                                     
+#define MII_MODE
+
+/* Uncomment the define below to clock the PHY from external 25MHz crystal (only for MII mode) */
+#ifdef 	MII_MODE
+ #define PHY_CLOCK_MCO
+#endif
+
+/* STM324xG-EVAL jumpers setting
+    +==========================================================================================+
+    +  Jumper |       MII mode configuration            |      RMII mode configuration         +
+    +==========================================================================================+
+    +  JP5    | 2-3 provide 25MHz clock by MCO(PA8)     |  Not fitted                          +
+    +         | 1-2 provide 25MHz clock by ext. Crystal |                                      +
+    + -----------------------------------------------------------------------------------------+
+    +  JP6    |          2-3                            |  1-2                                 +
+    + -----------------------------------------------------------------------------------------+
+    +  JP8    |          Open                           |  Close                               +
+    +==========================================================================================+
+  */
+   
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void Time_Update(void);  
+void Delay(uint32_t nCount);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MAIN_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
+
--- a/mbconfig.h	Thu Apr 15 12:10:34 2010 +0000
+++ b/mbconfig.h	Mon Jul 02 14:36:46 2018 +0000
@@ -49,9 +49,9 @@
 /*! \brief If Modbus ASCII support is enabled. */
 #define MB_ASCII_ENABLED                        (  0 )
 /*! \brief If Modbus RTU support is enabled. */
-#define MB_RTU_ENABLED                          (  1 )
+#define MB_RTU_ENABLED                          (  0 )
 /*! \brief If Modbus TCP support is enabled. */
-#define MB_TCP_ENABLED                          (  0 )
+#define MB_TCP_ENABLED                          (  1 )
 /*! \brief The character timeout value for Modbus ASCII.
  *
  * The character timeout value is not fixed for Modbus ASCII and is therefore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#62f8b922b420626514fd4690107aff4188469833
--- a/mbed.bld	Thu Apr 15 12:10:34 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbtcp.cpp	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,159 @@
+/* 
+ * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
+ * Copyright (c) 2006 Christian Walter <wolti@sil.at>
+ * 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.
+ *
+ * File: $Id: mbtcp.c,v 1.3 2006/12/07 22:10:34 wolti Exp $
+ */
+
+/* ----------------------- System includes ----------------------------------*/
+#include "stdlib.h"
+#include "string.h"
+
+/* ----------------------- Platform includes --------------------------------*/
+#include "port.h"
+
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mbconfig.h"
+#include "mbtcp.h"
+#include "mbframe.h"
+#include "mbport.h"
+
+#if MB_TCP_ENABLED > 0
+
+/* ----------------------- Defines ------------------------------------------*/
+
+/* ----------------------- MBAP Header --------------------------------------*/
+/*
+ *
+ * <------------------------ MODBUS TCP/IP ADU(1) ------------------------->
+ *              <----------- MODBUS PDU (1') ---------------->
+ *  +-----------+---------------+------------------------------------------+
+ *  | TID | PID | Length | UID  |Code | Data                               |
+ *  +-----------+---------------+------------------------------------------+
+ *  |     |     |        |      |                                           
+ * (2)   (3)   (4)      (5)    (6)                                          
+ *
+ * (2)  ... MB_TCP_TID          = 0 (Transaction Identifier - 2 Byte) 
+ * (3)  ... MB_TCP_PID          = 2 (Protocol Identifier - 2 Byte)
+ * (4)  ... MB_TCP_LEN          = 4 (Number of bytes - 2 Byte)
+ * (5)  ... MB_TCP_UID          = 6 (Unit Identifier - 1 Byte)
+ * (6)  ... MB_TCP_FUNC         = 7 (Modbus Function Code)
+ *
+ * (1)  ... Modbus TCP/IP Application Data Unit
+ * (1') ... Modbus Protocol Data Unit
+ */
+
+#define MB_TCP_TID          0
+#define MB_TCP_PID          2
+#define MB_TCP_LEN          4
+#define MB_TCP_UID          6
+#define MB_TCP_FUNC         7
+
+#define MB_TCP_PROTOCOL_ID  0   /* 0 = Modbus Protocol */
+
+
+/* ----------------------- Start implementation -----------------------------*/
+eMBErrorCode
+eMBTCPDoInit( USHORT ucTCPPort )
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+
+    if( xMBTCPPortInit( ucTCPPort ) == FALSE )
+    {
+        eStatus = MB_EPORTERR;
+    }
+    return eStatus;
+}
+
+void
+eMBTCPStart( void )
+{
+}
+
+void
+eMBTCPStop( void )
+{
+    /* Make sure that no more clients are connected. */
+    vMBTCPPortDisable( );
+}
+
+eMBErrorCode
+eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** ppucFrame, USHORT * pusLength )
+{
+    eMBErrorCode    eStatus = MB_EIO;
+    UCHAR          *pucMBTCPFrame;
+    USHORT          usLength;
+    USHORT          usPID;
+
+    if( xMBTCPPortGetRequest( &pucMBTCPFrame, &usLength ) != FALSE )
+    {
+        usPID = pucMBTCPFrame[MB_TCP_PID] << 8U;
+        usPID |= pucMBTCPFrame[MB_TCP_PID + 1];
+
+        if( usPID == MB_TCP_PROTOCOL_ID )
+        {
+            *ppucFrame = &pucMBTCPFrame[MB_TCP_FUNC];
+            *pusLength = usLength - MB_TCP_FUNC;
+            eStatus = MB_ENOERR;
+
+            /* Modbus TCP does not use any addresses. Fake the source address such
+             * that the processing part deals with this frame.
+             */
+            *pucRcvAddress = MB_TCP_PSEUDO_ADDRESS;
+        }
+    }
+    else
+    {
+        eStatus = MB_EIO;
+    }
+    return eStatus;
+}
+
+eMBErrorCode
+eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame, USHORT usLength )
+{
+    eMBErrorCode    eStatus = MB_ENOERR;
+    UCHAR          *pucMBTCPFrame = ( UCHAR * ) pucFrame - MB_TCP_FUNC;
+    USHORT          usTCPLength = usLength + MB_TCP_FUNC;
+
+    /* The MBAP header is already initialized because the caller calls this
+     * function with the buffer returned by the previous call. Therefore we 
+     * only have to update the length in the header. Note that the length 
+     * header includes the size of the Modbus PDU and the UID Byte. Therefore 
+     * the length is usLength plus one.
+     */
+    pucMBTCPFrame[MB_TCP_LEN] = ( usLength + 1 ) >> 8U;
+    pucMBTCPFrame[MB_TCP_LEN + 1] = ( usLength + 1 ) & 0xFF;
+    if( xMBTCPPortSendResponse( pucMBTCPFrame, usTCPLength ) == FALSE )
+    {
+        eStatus = MB_EIO;
+    }
+    return eStatus;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbtcp.h	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,54 @@
+/* 
+ * FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
+ * Copyright (c) 2006 Christian Walter <wolti@sil.at>
+ * 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.
+ *
+ * File: $Id: mbtcp.h,v 1.2 2006/12/07 22:10:34 wolti Exp $
+ */
+
+#ifndef _MB_TCP_H
+#define _MB_TCP_H
+
+#ifdef __cplusplus
+PR_BEGIN_EXTERN_C
+#endif
+
+/* ----------------------- Defines ------------------------------------------*/
+#define MB_TCP_PSEUDO_ADDRESS   1
+
+/* ----------------------- Function prototypes ------------------------------*/
+    eMBErrorCode eMBTCPDoInit( USHORT ucTCPPort );
+void            eMBTCPStart( void );
+void            eMBTCPStop( void );
+eMBErrorCode    eMBTCPReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame,
+                               USHORT * pusLength );
+eMBErrorCode    eMBTCPSend( UCHAR _unused, const UCHAR * pucFrame,
+                            USHORT usLength );
+
+#ifdef __cplusplus
+PR_END_EXTERN_C
+#endif
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netconf.cpp	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,297 @@
+/**
+  ******************************************************************************
+  * @file    netconf.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    31-October-2011
+  * @brief   Network connection configuration
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; Portions COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+/**
+  ******************************************************************************
+  * <h2><center>&copy; Portions COPYRIGHT 2012 Embest Tech. Co., Ltd.</center></h2>
+  * @file    netconf.c
+  * @author  CMP Team
+  * @version V1.0.0
+  * @date    28-December-2012
+  * @brief   Network connection configuration     
+  *          Modified to support the STM32F4DISCOVERY, STM32F4DIS-BB and
+  *          STM32F4DIS-LCD modules. 
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, Embest SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
+  * OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+  * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+  * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  ******************************************************************************
+  */ 
+/* Includes ------------------------------------------------------------------*/
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/tcp.h"
+#include "lwip/udp.h"
+#include "netif/etharp.h"
+#include "lwip/dhcp.h"
+#include "ethernetif.h"
+#include "main.h"
+#include "netconf.h"
+#include <stdio.h>
+
+/* Private typedef -----------------------------------------------------------*/
+#define MAX_DHCP_TRIES        4
+
+/* Private define ------------------------------------------------------------*/
+typedef enum 
+{ 
+  DHCP_START=0,
+  DHCP_WAIT_ADDRESS,
+  DHCP_ADDRESS_ASSIGNED,
+  DHCP_TIMEOUT
+} 
+DHCP_State_TypeDef;
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+struct netif netif;
+uint32_t TCPTimer = 0;
+uint32_t ARPTimer = 0;
+uint32_t IPaddress = 0;
+
+#ifdef USE_DHCP
+uint32_t DHCPfineTimer = 0;
+uint32_t DHCPcoarseTimer = 0;
+DHCP_State_TypeDef DHCP_state = DHCP_START;
+#endif
+
+/* Private functions ---------------------------------------------------------*/
+void LwIP_DHCP_Process_Handle(void);
+/**
+  * @brief  Initializes the lwIP stack
+  * @param  None
+  * @retval None
+  */
+void LwIP_Init(void)
+{
+  struct ip_addr ipaddr;
+  struct ip_addr netmask;
+  struct ip_addr gw;
+#ifndef USE_DHCP
+  uint8_t iptab[4];
+  uint8_t iptxt[20];
+#endif
+
+  /* Initializes the dynamic memory heap defined by MEM_SIZE.*/
+  mem_init();
+
+  /* Initializes the memory pools defined by MEMP_NUM_x.*/
+  memp_init();
+
+#ifdef USE_DHCP
+  ipaddr.addr = 0;
+  netmask.addr = 0;
+  gw.addr = 0;
+#else
+  IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+  IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
+  IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+
+#ifdef USE_LCD  
+  iptab[0] = IP_ADDR3;
+  iptab[1] = IP_ADDR2;
+  iptab[2] = IP_ADDR1;
+  iptab[3] = IP_ADDR0;
+
+  sprintf((char*)iptxt, "  %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]); 
+     
+  LCD_DisplayStringLine(Line8, (uint8_t*)"  Static IP address   ");
+  LCD_DisplayStringLine(Line9, iptxt);
+#endif
+#endif
+
+  /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
+            struct ip_addr *netmask, struct ip_addr *gw,
+            void *state, err_t (* init)(struct netif *netif),
+            err_t (* input)(struct pbuf *p, struct netif *netif))
+    
+   Adds your network interface to the netif_list. Allocate a struct
+  netif and pass a pointer to this structure as the first argument.
+  Give pointers to cleared ip_addr structures when using DHCP,
+  or fill them with sane numbers otherwise. The state pointer may be NULL.
+
+  The init function pointer must point to a initialization function for
+  your ethernet netif interface. The following code illustrates it's use.*/
+  netif_add(&netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);
+
+  /*  Registers the default network interface.*/
+  netif_set_default(&netif);
+
+  /*  When the netif is fully configured this function must be called.*/
+  netif_set_up(&netif);
+}
+
+/**
+  * @brief  Called when a frame is received
+  * @param  None
+  * @retval None
+  */
+void LwIP_Pkt_Handle(void)
+{
+  /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
+  ethernetif_input(&netif);
+}
+
+/**
+  * @brief  LwIP periodic tasks
+  * @param  localtime the current LocalTime value
+  * @retval None
+  */
+void LwIP_Periodic_Handle(__IO uint32_t localtime)
+{
+#if LWIP_TCP
+  /* TCP periodic process every 250 ms */
+  if (localtime - TCPTimer >= TCP_TMR_INTERVAL) {
+    TCPTimer =  localtime;
+    tcp_tmr();
+  }
+#endif
+  
+  /* ARP periodic process every 5s */
+  if ((localtime - ARPTimer) >= ARP_TMR_INTERVAL) {
+    ARPTimer =  localtime;
+    etharp_tmr();
+  }
+
+#ifdef USE_DHCP
+  /* Fine DHCP periodic process every 500ms */
+  if (localtime - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) {
+    DHCPfineTimer =  localtime;
+    dhcp_fine_tmr();
+    if ((DHCP_state != DHCP_ADDRESS_ASSIGNED)&&(DHCP_state != DHCP_TIMEOUT)) {
+      /* process DHCP state machine */
+      LwIP_DHCP_Process_Handle();    
+    }
+  }
+
+  /* DHCP Coarse periodic process every 60s */
+  if (localtime - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS) {
+    DHCPcoarseTimer =  localtime;
+    dhcp_coarse_tmr();
+  }
+  
+#endif
+}
+
+#ifdef USE_DHCP
+/**
+  * @brief  LwIP_DHCP_Process_Handle
+  * @param  None
+  * @retval None
+  */
+void LwIP_DHCP_Process_Handle()
+{
+  struct ip_addr ipaddr;
+  struct ip_addr netmask;
+  struct ip_addr gw;
+  uint8_t iptab[4];
+  uint8_t iptxt[20];
+
+  switch (DHCP_state)
+  {
+    case DHCP_START:
+    {
+      dhcp_start(&netif);
+      IPaddress = 0;
+      DHCP_state = DHCP_WAIT_ADDRESS;
+#ifdef USE_LCD
+      LCD_DisplayStringLine(Line4, (uint8_t*)"     Looking for    ");
+      LCD_DisplayStringLine(Line5, (uint8_t*)"     DHCP server    ");
+      LCD_DisplayStringLine(Line6, (uint8_t*)"     please wait... ");
+#endif
+    }
+    break;
+
+    case DHCP_WAIT_ADDRESS:
+    {
+      /* Read the new IP address */
+      IPaddress = netif.ip_addr.addr;
+
+      if (IPaddress!=0) {
+        DHCP_state = DHCP_ADDRESS_ASSIGNED;	
+
+        /* Stop DHCP */
+        dhcp_stop(&netif);
+
+        iptab[0] = (uint8_t)(IPaddress >> 24);
+        iptab[1] = (uint8_t)(IPaddress >> 16);
+        iptab[2] = (uint8_t)(IPaddress >> 8);
+        iptab[3] = (uint8_t)(IPaddress);
+
+        sprintf((char*)iptxt, " %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]);       
+
+#ifdef USE_LCD
+
+
+        LCD_ClearLine(Line4);
+        LCD_ClearLine(Line5);
+        LCD_ClearLine(Line6);
+
+        /* Display the IP address */
+        LCD_DisplayStringLine(Line7, (uint8_t*)"IP address assigned ");
+        LCD_DisplayStringLine(Line8, (uint8_t*)"  by a DHCP server  ");
+        LCD_DisplayStringLine(Line9, iptxt);
+#endif
+      } else {
+        /* DHCP timeout */
+        if (netif.dhcp->tries > MAX_DHCP_TRIES) {
+          DHCP_state = DHCP_TIMEOUT;
+
+          /* Stop DHCP */
+          dhcp_stop(&netif);
+
+          /* Static address used */
+          IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );
+          IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+          IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+          netif_set_addr(&netif, &ipaddr , &netmask, &gw);
+
+#ifdef USE_LCD   
+          LCD_DisplayStringLine(Line7, (uint8_t*)"    DHCP timeout    ");
+
+          iptab[0] = IP_ADDR3;
+          iptab[1] = IP_ADDR2;
+          iptab[2] = IP_ADDR1;
+          iptab[3] = IP_ADDR0;
+
+          sprintf((char*)iptxt, "  %d.%d.%d.%d", iptab[3], iptab[2], iptab[1], iptab[0]); 
+
+          LCD_ClearLine(Line4);
+          LCD_ClearLine(Line5);
+          LCD_ClearLine(Line6);
+
+          LCD_DisplayStringLine(Line8, (uint8_t*)"  Static IP address   ");
+          LCD_DisplayStringLine(Line9, iptxt);         
+#endif
+        }
+      }
+    }
+    break;
+    default: break;
+  }
+}
+#endif      
+
+/*********** Portions COPYRIGHT 2012 Embest Tech. Co., Ltd.*****END OF FILE****/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/netconf.h	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,70 @@
+/**
+  ******************************************************************************
+  * @file    netconf.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    31-October-2011 
+  * @brief   This file contains all the functions prototypes for the netconf.c 
+  *          file.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; Portions COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+/**
+  ******************************************************************************
+  * <h2><center>&copy; Portions COPYRIGHT 2012 Embest Tech. Co., Ltd.</center></h2>
+  * @file    netconf.h
+  * @author  CMP Team
+  * @version V1.0.0
+  * @date    28-December-2012
+  * @brief   This file contains all the functions prototypes for the netconf.c 
+  *          file.
+  *          Modified to support the STM32F4DISCOVERY, STM32F4DIS-BB and
+  *          STM32F4DIS-LCD modules. 
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, Embest SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
+  * OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+  * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+  * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  ******************************************************************************
+  */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __NETCONF_H
+#define __NETCONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+   
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void LwIP_Init(void);
+void LwIP_Pkt_Handle(void);
+void LwIP_Periodic_Handle(__IO uint32_t localtime);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NETCONF_H */
+
+
+/*********** Portions COPYRIGHT 2012 Embest Tech. Co., Ltd.*****END OF FILE****/
+
+
--- a/port.h	Thu Apr 15 12:10:34 2010 +0000
+++ b/port.h	Mon Jul 02 14:36:46 2018 +0000
@@ -51,4 +51,23 @@
 #define FALSE           0
 #endif
 
+#define MB_TCP_DEBUG            1
+
+#ifdef MB_TCP_DEBUG
+typedef enum
+{
+    MB_LOG_DEBUG,
+    MB_LOG_INFO,
+    MB_LOG_WARN,
+    MB_LOG_ERROR
+} eMBPortLogLevel;
 #endif
+
+/* ----------------------- Function prototypes ------------------------------*/
+#ifdef MB_TCP_DEBUG
+void            vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule,
+                            const CHAR * szFmt, ... );
+void            prvvMBTCPLogFrame( UCHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen );
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/portother.cpp	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,125 @@
+/*
+ * FreeModbus Libary: lwIP Port
+ * Copyright (C) 2006 Christian Walter <wolti@sil.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * File: $Id: portother.c,v 1.2 2006/09/04 14:39:20 wolti Exp $
+ */
+
+/* ----------------------- System includes ----------------------------------*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "port.h"
+
+/* ----------------------- Defines ------------------------------------------*/
+#define MB_FRAME_LOG_BUFSIZE    512
+
+/* ----------------------- Start implementation -----------------------------*/
+
+#ifdef MB_TCP_DEBUG
+void
+prvvMBTCPLogFrame( UCHAR * pucMsg, UCHAR * pucFrame, USHORT usFrameLen )
+{
+    int             i;
+    int             res = 0;
+    int             iBufPos = 0;
+    size_t          iBufLeft = MB_FRAME_LOG_BUFSIZE;
+    static CHAR     arcBuffer[MB_FRAME_LOG_BUFSIZE];
+
+    assert( pucFrame != NULL );
+
+    for( i = 0; i < usFrameLen; i++ )
+    {
+        /* Print some additional frame information. */
+        switch ( i )
+        {
+        case 0:
+            /* TID = Transaction Identifier. */
+            res = snprintf( &arcBuffer[iBufPos], iBufLeft, "| TID = " );
+            break;
+        case 2:
+            /* PID = Protocol Identifier. */
+            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | PID = " );
+            break;
+        case 4:
+            /* Length */
+            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | LEN = " );
+            break;
+        case 6:
+            /* UID = Unit Identifier. */
+            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | UID = " );
+            break;
+        case 7:
+            /* MB Function Code. */
+            res = snprintf( &arcBuffer[iBufPos], iBufLeft, "|| FUNC = " );
+            break;
+        case 8:
+            /* MB PDU rest. */
+            res = snprintf( &arcBuffer[iBufPos], iBufLeft, " | DATA = " );
+            break;
+        default:
+            res = 0;
+            break;
+        }
+        if( res == -1 )
+        {
+            break;
+        }
+        else
+        {
+            iBufPos += res;
+            iBufLeft -= res;
+        }
+
+        /* Print the data. */
+        res = snprintf( &arcBuffer[iBufPos], iBufLeft, "%02X", pucFrame[i] );
+        if( res == -1 )
+        {
+            break;
+        }
+        else
+        {
+            iBufPos += res;
+            iBufLeft -= res;
+        }
+    }
+
+    if( res != -1 )
+    {
+        /* Append an end of frame string. */
+        res = snprintf( &arcBuffer[iBufPos], iBufLeft, " |\r\n" );
+        if( res != -1 )
+        {
+            vMBPortLog( MB_LOG_DEBUG, (const char*)pucMsg, "%s", arcBuffer );
+        }
+    }
+}
+#endif
+
+void
+vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule, const CHAR * szFmt, ... )
+{
+    va_list         args;
+    static const char *arszLevel2Str[] = { "DEBUG", "INFO", "WARN", "ERROR" };
+
+    ( void )printf( "%s: %s: ", arszLevel2Str[eLevel], szModule );
+    va_start( args, szFmt );
+    vprintf( szFmt, args );
+    va_end( args );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/porttcp.cpp	Mon Jul 02 14:36:46 2018 +0000
@@ -0,0 +1,332 @@
+/*
+ * FreeModbus Libary: lwIP Port
+ * Copyright (C) 2006 Christian Walter <wolti@sil.at>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * File: $Id: porttcp.c,v 1.2 2006/09/04 14:39:20 wolti Exp $
+ */
+
+/* ----------------------- System includes ----------------------------------*/
+#include <stdio.h>
+#include "string.h"
+
+#include "port.h"
+
+/* ----------------------- lwIP includes ------------------------------------*/
+#include "lwip/api.h"
+#include "lwip/tcp.h"
+
+/* ----------------------- Modbus includes ----------------------------------*/
+#include "mb.h"
+#include "mbport.h"
+
+/* ----------------------- MBAP Header --------------------------------------*/
+#define MB_TCP_UID          6
+#define MB_TCP_LEN          4
+#define MB_TCP_FUNC         7
+
+/* ----------------------- Defines  -----------------------------------------*/
+#define MB_TCP_DEFAULT_PORT 502 /* TCP listening port. */
+#define MB_TCP_BUF_SIZE     ( 256 + 7 ) /* Must hold a complete Modbus TCP frame. */
+
+/* ----------------------- Prototypes ---------------------------------------*/
+void            vMBPortEventClose( void ){};
+void            vMBPortLog( eMBPortLogLevel eLevel, const CHAR * szModule,
+                            const CHAR * szFmt, ... );
+
+/* ----------------------- Static variables ---------------------------------*/
+static struct tcp_pcb *pxPCBListen;
+static struct tcp_pcb *pxPCBClient;
+
+static UCHAR    aucTCPBuf[MB_TCP_BUF_SIZE];
+static USHORT   usTCPBufPos;
+
+/* ----------------------- Static functions ---------------------------------*/
+static err_t    prvxMBTCPPortAccept( void *pvArg, struct tcp_pcb *pxPCB, err_t xErr );
+static err_t    prvxMBTCPPortReceive( void *pvArg, struct tcp_pcb *pxPCB, struct pbuf *p,
+                                      err_t xErr );
+static void     prvvMBTCPPortError( void *pvArg, err_t xErr );
+
+/* ----------------------- Begin implementation -----------------------------*/
+BOOL
+xMBTCPPortInit( USHORT usTCPPort )
+{
+    struct tcp_pcb *pxPCBListenNew, *pxPCBListenOld;
+    BOOL            bOkay = FALSE;
+    USHORT          usPort;
+
+    if( usTCPPort == 0 )
+    {
+        usPort = MB_TCP_DEFAULT_PORT;
+    }
+    else
+    {
+        usPort = ( USHORT ) usTCPPort;
+    }
+
+    if( ( pxPCBListenNew = pxPCBListenOld = tcp_new(  ) ) == NULL )
+    {
+        /* Can't create TCP socket. */
+        bOkay = FALSE;
+    }
+    else if( tcp_bind( pxPCBListenNew, IP_ADDR_ANY, ( u16_t ) usPort ) != ERR_OK )
+    {
+        /* Bind failed - Maybe illegal port value or in use. */
+        ( void )tcp_close( pxPCBListenOld );
+        bOkay = FALSE;
+    }
+    else if( ( pxPCBListenNew = tcp_listen( pxPCBListenNew ) ) == NULL )
+    {
+        ( void )tcp_close( pxPCBListenOld );
+        bOkay = FALSE;
+    }
+    else
+    {
+        /* Register callback function for new clients. */
+        tcp_accept( pxPCBListenNew, prvxMBTCPPortAccept );
+
+        /* Everything okay. Set global variable. */
+        pxPCBListen = pxPCBListenNew;
+
+#ifdef MB_TCP_DEBUG
+        vMBPortLog( MB_LOG_DEBUG, "MBTCP-ACCEPT", "Protocol stack ready.\r\n" );
+#endif
+    }
+    bOkay = TRUE;
+    return bOkay;
+}
+
+void
+prvvMBPortReleaseClient( struct tcp_pcb *pxPCB )
+{
+    if( pxPCB != NULL )
+    {
+        if( tcp_close( pxPCB ) != ERR_OK )
+        {
+            tcp_abort( pxPCB );
+        }
+       // vPortEnterCritical(  );
+        if( pxPCB == pxPCBClient )
+        {
+#ifdef MB_TCP_DEBUG
+            vMBPortLog( MB_LOG_DEBUG, "MBTCP-CLOSE", "Closed connection to %d.%d.%d.%d.\r\n",
+                        ip4_addr1( &( pxPCB->remote_ip ) ),
+                        ip4_addr2( &( pxPCB->remote_ip ) ),
+                        ip4_addr3( &( pxPCB->remote_ip ) ), ip4_addr4( &( pxPCB->remote_ip ) ) );
+#endif
+            pxPCBClient = NULL;
+        }
+        if( pxPCB == pxPCBListen )
+        {
+            pxPCBListen = NULL;
+        }
+        //vPortExitCritical(  );
+    }
+}
+void
+vMBTCPPortClose(  )
+{
+    /* Shutdown any open client sockets. */
+    prvvMBPortReleaseClient( pxPCBClient );
+
+    /* Shutdown or listening socket. */
+    prvvMBPortReleaseClient( pxPCBListen );
+
+    /* Release resources for the event queue. */
+    vMBPortEventClose(  );
+}
+
+void
+vMBTCPPortDisable( void )
+{
+    prvvMBPortReleaseClient( pxPCBClient );
+}
+
+err_t
+prvxMBTCPPortAccept( void *pvArg, struct tcp_pcb *pxPCB, err_t xErr )
+{
+    err_t           error;
+
+    if( xErr != ERR_OK )
+    {
+        return xErr;
+    }
+
+    /* We can handle only one client. */
+    if( pxPCBClient == NULL )
+    {
+        /* Register the client. */
+        pxPCBClient = pxPCB;
+
+        /* Set up the receive function prvxMBTCPPortReceive( ) to be called when data
+         * arrives.
+         */
+        tcp_recv( pxPCB, prvxMBTCPPortReceive );
+
+        /* Register error handler. */
+        tcp_err( pxPCB, prvvMBTCPPortError );
+
+        /* Set callback argument later used in the error handler. */
+        tcp_arg( pxPCB, pxPCB );
+
+        /* Reset the buffers and state variables. */
+        usTCPBufPos = 0;
+
+#ifdef MB_TCP_DEBUG
+        vMBPortLog( MB_LOG_DEBUG, "MBTCP-ACCEPT", "Accepted new client %d.%d.%d.%d\r\n",
+                    ip4_addr1( &( pxPCB->remote_ip ) ),
+                    ip4_addr2( &( pxPCB->remote_ip ) ),
+                    ip4_addr3( &( pxPCB->remote_ip ) ), ip4_addr4( &( pxPCB->remote_ip ) ) );
+#endif
+
+        error = ERR_OK;
+    }
+    else
+    {
+        prvvMBPortReleaseClient( pxPCB );
+        error = ERR_OK;
+    }
+    return error;
+}
+
+/* Called in case of an unrecoverable error. In any case we drop the client
+ * connection. */
+void
+prvvMBTCPPortError( void *pvArg, err_t xErr )
+{
+    struct tcp_pcb *pxPCB = (struct tcp_pcb *)pvArg;
+
+    if( pxPCB != NULL )
+    {
+#ifdef MB_TCP_DEBUG
+        vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR", "Error with client connection! Droping it.\r\n" );
+#endif
+        prvvMBPortReleaseClient( pxPCB );
+    }
+}
+
+err_t
+prvxMBTCPPortReceive( void *pvArg, struct tcp_pcb *pxPCB, struct pbuf *p, err_t xErr )
+{
+    USHORT          usLength;
+
+    err_t           error = xErr;
+
+    if( error != ERR_OK )
+    {
+        return error;
+    }
+
+    /* If pbuf is NULL then remote end has closed connection. */
+    if( p == NULL )
+    {
+        prvvMBPortReleaseClient( pxPCB );
+        return ERR_OK;
+    }
+
+    /* Acknowledge that we have received the data bytes. */
+    tcp_recved( pxPCB, p->len );
+
+    /* Check for internal buffer overflow. In case of an error drop the
+     * client. */
+    if( ( usTCPBufPos + p->len ) >= MB_TCP_BUF_SIZE )
+    {
+        prvvMBPortReleaseClient( pxPCB );
+        error = ERR_OK;
+    }
+    else
+    {
+        memcpy( &aucTCPBuf[usTCPBufPos], p->payload, p->len );
+        usTCPBufPos += p->len;
+
+        /* If we have received the MBAP header we can analyze it and calculate
+         * the number of bytes left to complete the current request. If complete
+         * notify the protocol stack.
+         */
+        if( usTCPBufPos >= MB_TCP_FUNC )
+        {
+            /* Length is a byte count of Modbus PDU (function code + data) and the
+             * unit identifier. */
+            usLength = aucTCPBuf[MB_TCP_LEN] << 8U;
+            usLength |= aucTCPBuf[MB_TCP_LEN + 1];
+
+            /* Is the frame already complete. */
+            if( usTCPBufPos < ( MB_TCP_UID + usLength ) )
+            {
+            }
+            else if( usTCPBufPos == ( MB_TCP_UID + usLength ) )
+            {
+#ifdef MB_TCP_DEBUG
+                prvvMBTCPLogFrame( (UCHAR*)"MBTCP-RECV", &aucTCPBuf[0], usTCPBufPos );
+#endif
+                ( void )xMBPortEventPost( EV_FRAME_RECEIVED );
+            }
+            else
+            {
+#ifdef MB_TCP_DEBUG
+                vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR",
+                            "Received to many bytes! Droping client.\r\n" );
+#endif
+                /* This should not happen. We can't deal with such a client and
+                 * drop the connection for security reasons.
+                 */
+                prvvMBPortReleaseClient( pxPCB );
+            }
+        }
+    }
+    pbuf_free( p );
+    return error;
+}
+
+BOOL
+xMBTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength )
+{
+    *ppucMBTCPFrame = &aucTCPBuf[0];
+    *usTCPLength = usTCPBufPos;
+
+    /* Reset the buffer. */
+    usTCPBufPos = 0;
+    return TRUE;
+}
+
+BOOL
+xMBTCPPortSendResponse( const UCHAR * pucMBTCPFrame, USHORT usTCPLength )
+{
+    BOOL            bFrameSent = FALSE;
+
+    if( pxPCBClient )
+    {
+        /* Make sure we can send the packet. */
+        assert( tcp_sndbuf( pxPCBClient ) >= usTCPLength );
+
+        if( tcp_write( pxPCBClient, pucMBTCPFrame, ( u16_t ) usTCPLength, TCP_WRITE_FLAG_COPY ) == ERR_OK )
+        {
+#ifdef MB_TCP_DEBUG
+            prvvMBTCPLogFrame( (UCHAR*)"MBTCP-SENT", &aucTCPBuf[0], usTCPLength );
+#endif
+            /* Make sure data gets sent immediately. */
+            ( void )tcp_output( pxPCBClient );
+            bFrameSent = TRUE;
+        }
+        else
+        {
+            /* Drop the connection in case of an write error. */
+            prvvMBPortReleaseClient( pxPCBClient );
+        }
+    }
+    return bFrameSent;
+}
+