]> rtime.felk.cvut.cz Git - pes-rpp/rpp-simulink.git/commitdiff
Add TCP/IP interface for extmode
authorJakub <nejedjak@fel.cvut.cz>
Wed, 28 Aug 2019 08:52:38 +0000 (10:52 +0200)
committerMichal Sojka <michal.sojka@cvut.cz>
Sun, 8 Sep 2019 23:57:43 +0000 (01:57 +0200)
Support basic communication and reconnecting to target.
Basic communication and reconnecting stress tested.

Implementation inspired from
http://git.savannah.nongnu.org/cgit/lwip/lwip-contrib.git/tree/apps/tcpecho/tcpecho.c
matlabroot/rtw/c/src/rtiostream/rtiostreamtcpip/rtiostream_tcpip.c

rpp/rpp/.gitattributes
rpp/rpp/rtiostream_tcpip.c [new file with mode: 0644]

index 0967701a3baa23899b878cc155fe2a0d6bd7b37f..a1503240b0f7b442fd7fad8a609a8ce3d337cf6b 100644 (file)
@@ -12,5 +12,6 @@
 /rpp_simulink_runtime.h        eaton
 /rpp_srmain.tlc        eaton
 /rtiostream_serial.c   eaton
+/rtiostream_tcpip.c    eaton
 /sl_customization.m    eaton
 /target_tools.mk       eaton
diff --git a/rpp/rpp/rtiostream_tcpip.c b/rpp/rpp/rtiostream_tcpip.c
new file mode 100644 (file)
index 0000000..c20a47d
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright 1994-2012 The MathWorks, Inc.
+ *
+ * Modified for RPP target by Jakub NejedlĂ˝ <nejedjak@fel.cvut.cz>
+ *
+ * File: rtiostream_tcpip.c
+ *
+ * Abstract:
+
+ */
+
+#include "rtiostream.h"
+
+#include "rpp/rpp.h"
+
+#include "lwip/mem.h"
+#include "lwip/raw.h"
+#include "lwip/icmp.h"
+#include "lwip/netif.h"
+#include "lwip/sys.h"
+#include "lwip/timers.h"
+#include "lwip/inet_chksum.h"
+#include "lwip/sockets.h"
+#include "lwip/inet.h"
+
+
+typedef int SOCKET;
+typedef const char * send_buffer_t;
+typedef socklen_t rtiostream_socklen_t;
+
+SOCKET socketBase = 0;
+SOCKET socketNum = 0;
+
+int sockStatus = 0;
+
+
+
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+
+#define RECEIVE_TIMEOUT             1000 //ms
+#define PORT_RPP                    17725U 
+
+#define INT_MAX                     2147483647
+
+# define INVALID_SOCKET             (-1)
+# define SOCK_ERR                   (-1)
+
+
+int ethinit(){
+        // // test eth init
+    int8_t retVal = rpp_eth_init_postInit(0, NULL); /* post OS startup init of eth (LwIP) for application usage -- waits for a while, for auto-negotiation of ethernet speed and DHCP if used */
+
+    switch (retVal) {
+    case FAILURE:
+        rpp_sci_printf("already initialized\n");
+        break;
+    case NETIF_ADD_ERR:
+        rpp_sci_printf("initialization of physical part of ethernet failed\n");
+        break;
+    case DHCP_MEM_ERR:
+        rpp_sci_printf("DHCP couldn't be started due to insufficient memory\n");
+        break;
+    case PHY_LINK_DOWN:
+        rpp_sci_printf("cable is not connected\n");
+        break;
+    default:
+        rpp_sci_printf("ethinit DONE\n");
+    }
+    return retVal;
+}
+
+int acceptComunication(){
+
+    // accept communication
+    struct sockaddr_in clientAddr;
+    rtiostream_socklen_t sFdAddSize = sizeof(struct sockaddr_in); 
+
+    sockStatus = lwip_accept(socketBase, (struct sockaddr *)&clientAddr, &sFdAddSize);
+    socketNum = sockStatus;
+
+    if (sockStatus == INVALID_SOCKET) {
+        rpp_sci_printf("accept() for comm socket failed.\n");
+        lwip_close(socketBase);
+        return RTIOSTREAM_ERROR;
+    }
+
+    return sockStatus;
+
+}
+
+
+/****** VISIBLE FUNCTIONS ***************/
+
+/* Function: rtIOStreamOpen =================================================
+ * Abstract:
+ *  Open the connection with the target.
+ */
+int rtIOStreamOpen(int argc, void * argv[])
+{
+
+    // rpp_sci_printf("##   Open  ##\n");
+
+    if (!isPostInitialized()) {
+        int errStat = ethinit();
+        if (errStat < 0){
+            rpp_sci_printf("Eth not initialized");
+            return RTIOSTREAM_ERROR;
+        }
+    }
+
+    // socket creation
+    socketBase = lwip_socket(AF_INET, SOCK_STREAM, 0);
+    if (socketBase == -1){
+        rpp_sci_printf("ERR: lwip socket init\r\n");
+        return RTIOSTREAM_ERROR;
+    }  
+
+    // socket options
+    int option = 1;
+    sockStatus = lwip_setsockopt(socketBase,SOL_SOCKET,SO_KEEPALIVE,(char*)&option,sizeof(option)); 
+    if (sockStatus == -1){
+        rpp_sci_printf("ERR: lwip socket opts\r\n");
+        return RTIOSTREAM_ERROR;
+    }  
+
+    // Bind socket 
+    struct sockaddr_in serverAddr;
+    rtiostream_socklen_t socketSize = (rtiostream_socklen_t) sizeof(struct sockaddr_in);
+
+    serverAddr.sin_family      = AF_INET;
+    serverAddr.sin_port        = htons((unsigned short int) PORT_RPP);
+    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY );
+
+
+    sockStatus = lwip_bind(socketBase, (struct sockaddr *) &serverAddr, socketSize);
+    if (sockStatus == -1){
+        rpp_sci_printf("bind() call failed. \r\n");
+        lwip_close(socketBase);
+        return RTIOSTREAM_ERROR;
+    }  
+
+    // listen socket
+    sockStatus = lwip_listen(socketBase, 2);
+    if (sockStatus == SOCK_ERR) {
+        rpp_sci_printf("listen() call failed.\n");
+        lwip_close(socketBase);
+        return RTIOSTREAM_ERROR;
+    }
+
+    int sockStatus = acceptComunication();
+
+    return sockStatus;
+}
+
+
+/* Function: rtIOStreamSend =====================================================
+ * Abstract:
+ *  Sends the specified number of bytes on the comm line. Returns the number of
+ *  bytes sent (if successful) or a negative value if an error occurred. As long
+ *  as an error does not occur, this function is guaranteed to set the requested
+ *  number of bytes.
+ */
+int rtIOStreamSend(
+    int streamID,
+    const void * const src,
+    size_t size,
+    size_t *sizeSent)
+{
+
+    int nSend;
+    const void *sendSrc = src;
+
+    /* Ensure size is not out of range for socket API send function */
+    int sizeLim = (int) MIN(size, INT_MAX);
+
+    nSend = lwip_send(socketNum, (send_buffer_t)sendSrc, sizeLim, 0);
+
+    if(nSend == -1){
+        return RTIOSTREAM_ERROR;
+    }
+    *sizeSent = (size_t)nSend;
+
+    return nSend;
+}
+
+
+int testCounter = 0;
+
+/* Function: rtIOStreamRecv ================================================
+ * Abstract:
+ *  Attempts to gets the specified number of bytes from socket.
+ *  The number of bytes read is returned via the 'sizeRecvd' parameter.
+ *  RTIOSTREAM_NO_ERROR is returned on success, RTIOSTREAM_ERROR is returned on
+ *  failure.
+ *  Function waiting for reconecting if read EOF from stream. 
+ *
+ */
+int rtIOStreamRecv(
+    int      streamID,
+    void   * const dst,
+    size_t   size,
+    size_t * sizeRecvd)
+{
+
+    int nRecv = 0;
+
+    /* Ensure size is not out of range for socket API recv function */
+    int sizeLim = (int) MIN(size, INT_MAX);
+
+    nRecv = lwip_recv(socketNum, dst, sizeLim, 0U);
+
+    if (nRecv == 0 ){
+        lwip_close(socketNum);
+
+        int sockStatus = acceptComunication();
+        if (sockStatus == RTIOSTREAM_ERROR){
+             rpp_sci_printf("acceptComunication() failed reconnecting \n");  
+        }
+        
+    }
+
+    if (nRecv == -1) {
+        return RTIOSTREAM_ERROR;
+    }
+    *sizeRecvd = (size_t) nRecv;
+    
+    return RTIOSTREAM_NO_ERROR;
+
+}
+
+
+/* Function: rtIOStreamClose ================================================
+ * Abstract: 
+ *  Close the connection.
+ *
+ */
+int rtIOStreamClose(int streamID)
+{
+    lwip_close(socketNum);
+    lwip_close(socketBase);
+    return RTIOSTREAM_NO_ERROR;
+}