ADDED: - dynamic memory allocation for sdo transfer using malloc and free
authorChristian Taedcke
Thu, 09 Sep 2010 15:56:06 +0200
changeset 636 033fe6f1ec3c
parent 635 30a0e926bb2e
child 637 c676669ec3c1
ADDED: - dynamic memory allocation for sdo transfer using malloc and free
CHANGED: - enabled lss, enabled dynamic buffer allocation and set max sim sdo transfers to 32
include/data.h
include/sdo.h
include/win32/config.h
src/sdo.c
--- a/include/data.h	Thu Sep 09 15:38:20 2010 +0200
+++ b/include/data.h	Thu Sep 09 15:56:06 2010 +0200
@@ -128,6 +128,25 @@
 
 #define NMTable_Initializer Unknown_state,
 
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+#define s_transfer_Initializer {\
+		0,          /* nodeId */\
+		0,          /* wohami */\
+		SDO_RESET,  /* state */\
+		0,          /* toggle */\
+		0,          /* abortCode */\
+		0,          /* index */\
+		0,          /* subIndex */\
+		0,          /* count */\
+		0,          /* offset */\
+		{0},        /* data (static use, so that all the table is initialize at 0)*/\
+    NULL,       /* dynamicData */ \
+    0,          /* dynamicDataSize */ \
+		0,          /* dataType */\
+		-1,         /* timer */\
+		NULL        /* Callback */\
+	  },
+#else
 #define s_transfer_Initializer {\
 		0,          /* nodeId */\
 		0,          /* wohami */\
@@ -143,6 +162,7 @@
 		-1,         /* timer */\
 		NULL        /* Callback */\
 	  },
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
 
 #define ERROR_DATA_INITIALIZER \
 	{\
--- a/include/sdo.h	Thu Sep 09 15:38:20 2010 +0200
+++ b/include/sdo.h	Thu Sep 09 15:56:06 2010 +0200
@@ -65,6 +65,10 @@
                               * (with respect to CANOPEN_BIG_ENDIAN)
                               */
   UNS8           data [SDO_MAX_LENGTH_TRANSFERT];
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  UNS8           *dynamicData;
+  UNS32          dynamicDataSize;
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
   UNS8           dataType;   /**< Defined in objdictdef.h Value is visible_string
                               * if it is a string, any other value if it is not a string,
                               * like 0. In fact, it is used only if client.
--- a/include/win32/config.h	Thu Sep 09 15:38:20 2010 +0200
+++ b/include/win32/config.h	Thu Sep 09 15:56:06 2010 +0200
@@ -22,9 +22,13 @@
 #ifndef _CONFIG_H_
 #define _CONFIG_H_
 
+#define CO_ENABLE_LSS
+
 #define MAX_CAN_BUS_ID 1
+#define SDO_DYNAMIC_BUFFER_ALLOCATION //New define, if SDO_MAX_LENGTH_TRANSFERT is exceeded allocate data buffer dynamically
+#define SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE (1024 * 128)
 #define SDO_MAX_LENGTH_TRANSFERT 32
-#define SDO_MAX_SIMULTANEOUS_TRANSFERTS 4
+#define SDO_MAX_SIMULTANEOUS_TRANSFERTS 32
 #define NMT_MAX_NODE_ID 128
 #define SDO_TIMEOUT_MS 3000
 #define MAX_NB_TIMER 32
@@ -38,7 +42,7 @@
 #define LSS_FS_TIMEOUT_MS 100
 
 #define REPEAT_SDO_MAX_SIMULTANEOUS_TRANSFERTS_TIMES(repeat)\
-repeat repeat repeat repeat
+repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat
 #define REPEAT_NMT_MAX_NODE_ID_TIMES(repeat)\
 repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat repeat
 #define REPEAT_EMCY_MAX_ERRORS_TIMES(repeat)\
--- a/src/sdo.c	Thu Sep 09 15:38:20 2010 +0200
+++ b/src/sdo.c	Thu Sep 09 15:56:06 2010 +0200
@@ -191,8 +191,23 @@
   if( d->transfers[line].count == 0)
   	d->transfers[line].count = d->transfers[line].offset;
   size = d->transfers[line].count;
+
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if (size > SDO_MAX_LENGTH_TRANSFERT)
+  {
+    errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
+			 (void *) d->transfers[line].dynamicData, &size, 1);
+  }
+  else
+  {
+   errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
+			 (void *) d->transfers[line].data, &size, 1);
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
   errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
 			 (void *) d->transfers[line].data, &size, 1);
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
   if (errorCode != OD_SUCCESSFUL)
     return errorCode;
   MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);
@@ -217,10 +232,18 @@
   MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);
   MSG_WAR(0x3A06, "  subIndex : ", d->transfers[line].subIndex);
 
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  //TODO: Read the size of the object. Depending o it put data into data or dynamicData
   errorCode = getODentry(d, 	d->transfers[line].index,
   				d->transfers[line].subIndex,
   				(void *)d->transfers[line].data,
   				&size, &dataType, 1);
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+  errorCode = getODentry(d, 	d->transfers[line].index,
+  				d->transfers[line].subIndex,
+  				(void *)d->transfers[line].data,
+  				&size, &dataType, 1);
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
 
   if (errorCode != OD_SUCCESSFUL)
     return errorCode;
@@ -245,17 +268,38 @@
   UNS8 i;
   UNS32 offset;
 
+#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION
   if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
     MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
     return 0xFF;
   }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
     if ((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {
     MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);
     return 0xFF;
   }
   offset = d->transfers[line].offset;
-  for (i = 0 ; i < nbBytes ; i++)
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  if (d->transfers[line].count <= SDO_MAX_LENGTH_TRANSFERT)
+  {
+    for (i = 0 ; i < nbBytes ; i++)
+      * (data + i) = d->transfers[line].data[offset + i];
+  }
+  else
+  {
+    if (d->transfers[line].dynamicData == NULL)
+    {
+      MSG_ERR(0x1A11,"SDO's dynamic buffer not allocated. Line", line);
+      return 0xFF;
+    }
+    for (i = 0 ; i < nbBytes ; i++)
+      * (data + i) = d->transfers[line].dynamicData[offset + i];
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
+    for (i = 0 ; i < nbBytes ; i++)
     * (data + i) = d->transfers[line].data[offset + i];
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
   d->transfers[line].offset = d->transfers[line].offset + nbBytes;
   return 0;
 }
@@ -274,14 +318,50 @@
 {
   UNS8 i;
   UNS32 offset;
-
+#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION
   if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
     MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
     return 0xFF;
   }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
   offset = d->transfers[line].offset;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  {
+    UNS8* lineData = d->transfers[line].data;
+    if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
+      if (d->transfers[line].dynamicData == NULL) {
+        d->transfers[line].dynamicData = (UNS8*) malloc(SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+        d->transfers[line].dynamicDataSize = SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE;
+
+        if (d->transfers[line].dynamicData == NULL) {
+          MSG_ERR(0x1A15,"SDO allocating dynamic buffer failed, size", SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+          return 0xFF;
+        }
+        //Copy present data
+        memcpy(d->transfers[line].dynamicData, d->transfers[line].data, offset);
+      }
+      else if ((d->transfers[line].offset + nbBytes) > d->transfers[line].dynamicDataSize)
+      {
+        UNS8* newDynamicBuffer = (UNS8*) realloc(d->transfers[line].dynamicData, d->transfers[line].dynamicDataSize + SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+        if (newDynamicBuffer == NULL) {
+          MSG_ERR(0x1A15,"SDO reallocating dynamic buffer failed, size", d->transfers[line].dynamicDataSize + SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);
+          return 0xFF;
+        }
+        d->transfers[line].dynamicData = newDynamicBuffer;
+        d->transfers[line].dynamicDataSize += SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE;
+      }
+      lineData = d->transfers[line].dynamicData;
+    }
+    
+    for (i = 0 ; i < nbBytes ; i++)
+      lineData[offset + i] = * (data + i);
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
   for (i = 0 ; i < nbBytes ; i++)
     d->transfers[line].data[offset + i] = * (data + i);
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
   d->transfers[line].offset = d->transfers[line].offset + nbBytes;
   return 0;
 }
@@ -338,6 +418,11 @@
     d->transfers[line].data[i] = 0;
   d->transfers[line].whoami = 0;
   d->transfers[line].abortCode = 0;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  free(d->transfers[line].dynamicData);
+  d->transfers[line].dynamicData = 0;
+  d->transfers[line].dynamicDataSize = 0;
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
 }
 
 /*!
@@ -369,6 +454,11 @@
   d->transfers[line].offset = 0;
   d->transfers[line].dataType = 0;
   d->transfers[line].Callback = NULL;
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  free(d->transfers[line].dynamicData);
+  d->transfers[line].dynamicData = 0;
+  d->transfers[line].dynamicDataSize = 0;
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
   return 0;
 }
 
@@ -417,7 +507,7 @@
      (d->transfers[i].state != SDO_ABORTED_INTERNAL) &&
 	 (d->transfers[i].nodeId == nodeId) &&
 	 (d->transfers[i].whoami == whoami) ) {
-      *line = i;
+      if (line) *line = i;
       return 0;
     }
   }
@@ -476,10 +566,13 @@
 **/
 UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 nbBytes)
 {
+#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION
   if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
     MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
     return 0xFF;
   }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
   d->transfers[line].count = nbBytes;
   return 0;
 }
@@ -1315,8 +1408,35 @@
   d->transfers[line].count = count;
   d->transfers[line].dataType = dataType;
 
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  {
+    UNS8* lineData = d->transfers[line].data;
+    if (count > SDO_MAX_LENGTH_TRANSFERT)
+    {
+      d->transfers[line].dynamicData = (UNS8*) malloc(count);
+      d->transfers[line].dynamicDataSize = count;
+      if (d->transfers[line].dynamicData == NULL)
+      {
+        MSG_ERR(0x1AC9, "SDO. Error. Could not allocate enough bytes : ", count);
+        return 0xFE;
+      }
+      lineData = d->transfers[line].dynamicData;
+    }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
+
   /* Copy data to transfers structure. */
   for (j = 0 ; j < count ; j++) {
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+# ifdef CANOPEN_BIG_ENDIAN
+      if (dataType == 0 && endianize)
+        lineData[count - 1 - j] = ((char *)data)[j];
+      else /* String of bytes. */
+        lineData[j] = ((char *)data)[j];
+#  else
+      lineData[j] = ((char *)data)[j];
+#  endif
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
 # ifdef CANOPEN_BIG_ENDIAN
     if (dataType == 0 && endianize)
       d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
@@ -1325,6 +1445,7 @@
 #  else
     d->transfers[line].data[j] = ((char *)data)[j];
 #  endif
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
   }
   /* Send the SDO to the server. Initiate download, cs=1. */
   sdo.nodeId = nodeId;
@@ -1655,7 +1776,28 @@
   /* use transfers[line].count as max size */
   if( d->transfers[line].count < *size )
   	*size = d->transfers[line].count;
+
   /* Copy payload to data pointer */
+#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION
+  {
+    UNS8 *lineData = d->transfers[line].data;
+
+    if (d->transfers[line].dynamicData && d->transfers[line].dynamicDataSize)
+    {
+      lineData = d->transfers[line].dynamicData;
+    }
+    for  ( i = 0 ; i < *size ; i++) {
+# ifdef CANOPEN_BIG_ENDIAN
+      if (d->transfers[line].dataType != visible_string)
+        ( (char *) data)[*size - 1 - i] = lineData[i];
+      else /* String of bytes. */
+        ( (char *) data)[i] = lineData[i];
+# else
+      ( (char *) data)[i] = lineData[i];
+# endif
+    }
+  }
+#else //SDO_DYNAMIC_BUFFER_ALLOCATION
   for  ( i = 0 ; i < *size ; i++) {
 # ifdef CANOPEN_BIG_ENDIAN
     if (d->transfers[line].dataType != visible_string)
@@ -1666,6 +1808,7 @@
     ( (char *) data)[i] = d->transfers[line].data[i];
 # endif
   }
+#endif //SDO_DYNAMIC_BUFFER_ALLOCATION
   return SDO_FINISHED;
 }