commit d54d2f07cf55f262267ac5bae4ff1549e315a0a6
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Fri Mar 16 11:43:09 2018 +0100

    Major overhaul (to version 1.1.0):
    - The bootloader toolchain now works with 32 bit device IDs (DiWheelDrive 1.1 = 0x01000101; PowerManagement 1.1 = 0x01010101; LightRing 1.0 = 0x017F0100).
      However, the system is still compatible to the old numbering scheme and legacy IDs for compatibility reasons.
      As a result, the new bootloader can be used with the old SerialBoot tool and vice versa.
    - In order to allow for 32 bit IDs, the CAN communication as modified.
      Packages which are larger than a single transmit are split into multiple CAN messages.
      An according handshaking mechanism (receiver acknowledges everey message) has been implemented.
      The device ID is not coded into the CAN message identifier anymore, but is transmitted as the first four bytes of the first CAN message of a XCP package transmission.
      However, the two lowermost bit of the CAN message identifier are now used as indicator flags for acknowledgment and subsequent transmission for simple filtering.
    - The bootloaders will not "double blink" the LED anymore, but indicate the XCP connection status.
    - The bootloader version has been incremented to 1.1.0.

diff --git a/Host/Source/SerialBoot/main.c b/Host/Source/SerialBoot/main.c
index a41964d..a05c4ff 100644
--- a/Host/Source/SerialBoot/main.c
+++ b/Host/Source/SerialBoot/main.c
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 
@@ -42,6 +42,7 @@
 #include "xcpmaster.h"                                /* XCP master protocol module    */
 #include "srecord.h"                                  /* S-record file handling        */
 #include "timeutil.h"                                 /* time utility module           */
+#include "stdlib.h"                                   /* ascii to integral conversion  */
 
 
 /****************************************************************************************
@@ -95,28 +96,28 @@ static sb_int32 programCode(sb_file *hSrecord, tSrecordParseResults *fileParseRe
 * Local data declarations
 ****************************************************************************************/
 /** \brief Name of the serial device, such as COM4 or /dev/ttyUSB0. */
-static sb_char serialDeviceName[32]; 
+static sb_char serialDeviceName[32];
 
 /** \brief Id of the bluetooth device, such as 01:23:45:67:89:AB. */
-static sb_char bluetoothID[18]; 
+static sb_char bluetoothID[18];
 
 /** \brief Serial communication speed in bits per second. */
-static sb_uint32 serialBaudrate; 
+static sb_uint32 serialBaudrate;
 
 /** \brief Name of the S-record file. */
-static sb_char *srecordFileName; 
+static sb_char *srecordFileName;
 
 /* program status */
 static sb_uint8 prog_state = 1;
 
 /* id of flashing target */
-static sb_uint8 flashingTargetID = 0;
+static sb_uint32 flashingTargetID = 0;
 
 /* list of program names */
 static sb_char *srecordFileNames[MAX_COUNT_FLASHING_PROGRAMS];
 
 /* list of target ids */
-static sb_uint8 flashingTargetIDs[MAX_COUNT_FLASHING_PROGRAMS];
+static sb_uint32 flashingTargetIDs[MAX_COUNT_FLASHING_PROGRAMS];
 
 /* list of errors */
 static sb_uint8 errors[MAX_COUNT_FLASHING_PROGRAMS];
@@ -181,7 +182,8 @@ sb_int32 main(sb_int32 argc, sb_char *argv[])
     errorDetected = ERROR_NO;
     flashingTargetID = flashingTargetIDs[flashIdx];
     srecordFileName = srecordFileNames[flashIdx];
-    printf("\nFlash %i: Flashing %s on device %i\n\n", flashIdx+1, srecordFileName, flashingTargetID);
+    printf("\nFlash %i: Flashing %s on device 0x%08X\n\n", flashIdx+1, srecordFileName, flashingTargetID);
+
     if (flashProgram() == PROG_RESULT_ERROR) {
       closeSerialPort();
       openSerialPortConnect(0);
@@ -278,14 +280,14 @@ static void DisplayProgramInput(void) {
   printf("Programming will start immediately in following order:\n");
   sb_uint8 idx;
   for (idx=0; idx<countFlashingPrograms; idx++) {
-    printf("  %i) device %i: %s\n", idx+1, flashingTargetIDs[idx], srecordFileNames[idx]);
+    printf("  %i) device 0x%08X: %s\n", idx+1, flashingTargetIDs[idx], srecordFileNames[idx]);
   }
 }
 
 
 /************************************************************************************//**
 ** \brief     Parses the command line arguments. A fixed amount of arguments is expected.
-**            The program should be called as: 
+**            The program should be called as:
 **              SerialBoot -d[device] -b[baudrate] [s-record file]
 ** \param     argc Number of program parameters.
 ** \param     argv array to program parameter strings.
@@ -330,7 +332,7 @@ static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[])
         printf("The bluetooth ID %s has not the format xx:xx:xx:xx:xx:xx\n", &argv[paramIdx][2]);
         return SB_FALSE;
       }
-      // copy the bluetooth id and set flag that this parameter was found 
+      // copy the bluetooth id and set flag that this parameter was found
       strcpy(serialDeviceName, &argv[paramIdx][2]);
       paramAfound = SB_TRUE;
       comIsUart = SB_FALSE;
@@ -359,7 +361,7 @@ static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[])
       }
       if (registerRTSvalue > 1 || registerRTSvalue < 0 || setValue[1] != 0x0) {
         registerRTSvalue = 0;
-	printf("Not allowed value for RTS register. RTS=[0,1]\n");
+        printf("Not allowed value for RTS register. RTS=[0,1]\n");
         return SB_FALSE;
       }
       paramRTSfound = SB_TRUE;
@@ -414,7 +416,7 @@ static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[])
       srecordfound = SB_TRUE;
     }
   }
-  
+
   /* verify if all parameters were found */
   if ( ( ((paramDfound == SB_FALSE) || (paramBfound == SB_FALSE)) && (paramAfound == SB_FALSE)) || (srecordfound == SB_FALSE) )
   {
@@ -445,7 +447,7 @@ static void printErrors(void) {
       printf("\n%i ERRORs detected!\nOnly in the following %i cases SerialBoot updated the firmware:\n", detected, countFlashingPrograms-detected);
       for (errorIdx=0; errorIdx<countFlashingPrograms; errorIdx++) {
         if (errors[errorIdx] == ERROR_NO) {
-          printf(" * Flash %i: %s on device %i\n", errorIdx+1, srecordFileNames[errorIdx], flashingTargetIDs[errorIdx]);
+          printf(" * Flash %i: %s on device 0x%08X\n", errorIdx+1, srecordFileNames[errorIdx], flashingTargetIDs[errorIdx]);
         }
       }
       printf("In the following %i cases SerialBoot could not update the firmware:\n", detected);
@@ -459,7 +461,7 @@ static void printErrors(void) {
           case ERROR_FILE:
             printf("The file %s couldn't be read!\n", srecordFileNames[errorIdx]); break;
           case ERROR_DEVICE:
-            printf("No connection to device %i!\n", flashingTargetIDs[errorIdx]); break;
+            printf("No connection to device 0x%08X!\n", flashingTargetIDs[errorIdx]); break;
           default:
             printf("Couldn't specify the error. Please check output above!\n"); break;
         }
@@ -504,12 +506,8 @@ static sb_int32 flashProgram(void) {
   tSrecordLineParseResults lineParseResults;
 
   /* -------------------- start the firmware update procedure ------------------------ */
-  printf("Starting firmware update for \"%s\" on device %i (0x", srecordFileName, flashingTargetID);
-  if (flashingTargetID < 16)
-  {
-    printf("0");
-  }
-  printf("%X)\nUsing %s @ %u bits/s\n", flashingTargetID, serialDeviceName, serialBaudrate);
+  printf("Starting firmware update for \"%s\" on device 0x%08X\n", srecordFileName, flashingTargetID);
+  printf("Using %s @ %u bits/s\n", serialDeviceName, serialBaudrate);
 
   /* -------------------- prepare programming session -------------------------------- */
   if (prepareProgrammingSession(&hSrecord, &fileParseResults) == PROG_RESULT_ERROR) {
@@ -707,11 +705,7 @@ static sb_int32 buildConnection(sb_uint8 start) {
     } else if (flashingTargetID == 0) {
       printf("Try to connect to device...");
     } else {
-      printf("Try to connect to device 0x");
-      if (flashingTargetID < 16) {
-        printf("0");
-      }
-      printf("%X...", flashingTargetID);
+      printf("Try to connect to device 0x%08X...", flashingTargetID);
     }
   }
   /* now keep retrying until we get a response */
diff --git a/Host/Source/SerialBoot/xcpmaster.c b/Host/Source/SerialBoot/xcpmaster.c
index 4186861..52786c9 100644
--- a/Host/Source/SerialBoot/xcpmaster.c
+++ b/Host/Source/SerialBoot/xcpmaster.c
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 
@@ -91,7 +91,7 @@
 /****************************************************************************************
 * Function prototypes
 ****************************************************************************************/
-static sb_uint8 XcpMasterSendCmdConnect(sb_uint8 flashingTargetID);
+static sb_uint8 XcpMasterSendCmdConnect(sb_uint32 flashingTargetID);
 static sb_uint8 XcpMasterSendCmdSetMta(sb_uint32 address);
 static sb_uint8 XcpMasterSendCmdUpload(sb_uint8 data[], sb_uint8 length);
 static sb_uint8 XcpMasterSendCmdProgramStart(void);
@@ -155,14 +155,14 @@ void XcpMasterDeinit(void)
 ** \return    SB_TRUE is successfull, SB_FALSE otherwise.
 **
 ****************************************************************************************/
-sb_uint8 XcpMasterConnect(sb_uint8 flashingTargetID)
+sb_uint8 XcpMasterConnect(sb_uint32 flashingTargetID)
 {
   sb_uint8 cnt;
   sb_uint8 retries = 1;
   if (flashingTargetID <= 0) {
     retries = XCP_MASTER_CONNECT_RETRIES;
   }
-  
+
   /* try to connect with a finite amount of retries */
   for (cnt=0; cnt<retries; cnt++)
   {
@@ -357,31 +357,38 @@ sb_uint8 XcpMasterProgramData(sb_uint32 addr, sb_uint32 len, sb_uint8 data[])
 ** \return    SB_TRUE is successfull, SB_FALSE otherwise.
 **
 ****************************************************************************************/
-static sb_uint8 XcpMasterSendCmdConnect(sb_uint8 flashingTargetID)
+static sb_uint8 XcpMasterSendCmdConnect(sb_uint32 flashingTargetID)
 {
-  sb_uint8 packetData[2];
+  sb_uint8 packetData[1+4];
   tXcpTransportResponsePacket *responsePacketPtr;
-  
+
   /* prepare the command packet */
   packetData[0] = XCP_MASTER_CMD_CONNECT;
-  packetData[1] = flashingTargetID; /* normal mode */
-  
-  /* send the packet */
-  if (XcpTransportSendPacket(packetData, 2, XCP_MASTER_CONNECT_TIMEOUT_MS) == SB_FALSE)
+  packetData[1] = (sb_uint8)(0xFF & flashingTargetID >> 0);
+  packetData[2] = (sb_uint8)(0xFF & flashingTargetID >> 8);
+  packetData[3] = (sb_uint8)(0xFF & flashingTargetID >> 16);
+  packetData[4] = (sb_uint8)(0xFF & flashingTargetID >> 24);
+
+  /* send the packet
+   * NOTE: For legacy support the following code depends on the MSB if the flashingTargetID.
+   *       If the MSB (packData[4]) is zero (i.e. 0x00??????) the system switches to legacy mode.
+   *       In legacy mode, the flashingTargetID was only one byte - the LSB (packingData[1]).
+   */
+  if (XcpTransportSendPacket(packetData, 1 + ((packetData[4] != 0) ? 4 : 1), XCP_MASTER_CONNECT_TIMEOUT_MS) == SB_FALSE)
   {
     /* cound not set packet or receive response within the specified timeout */
     return SB_FALSE;
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
     /* not a valid or positive response */
     return SB_FALSE;
   }
-  
+
   /* process response data */
   if ((responsePacketPtr->data[2] & 0x01) == 0)
   {
@@ -400,12 +407,12 @@ static sb_uint8 XcpMasterSendCmdConnect(sb_uint8 flashingTargetID)
   {
     xcpMaxDto = responsePacketPtr->data[5] + (responsePacketPtr->data[4] << 8);
   }
-  
+
   /* double check size configuration of the master */
   assert(XCP_MASTER_TX_MAX_DATA >= xcpMaxCto);
   assert(XCP_MASTER_RX_MAX_DATA >= xcpMaxDto);
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdConnect ***/
 
@@ -420,16 +427,16 @@ static sb_uint8 XcpMasterSendCmdSetMta(sb_uint32 address)
 {
   sb_uint8 packetData[8];
   tXcpTransportResponsePacket *responsePacketPtr;
-  
+
   /* prepare the command packet */
   packetData[0] = XCP_MASTER_CMD_SET_MTA;
   packetData[1] = 0; /* reserved */
   packetData[2] = 0; /* reserved */
   packetData[3] = 0; /* address extension not supported */
-  
+
   /* set the address taking into account byte ordering */
   XcpMasterSetOrderedLong(address, &packetData[4]);
-  
+
   /* send the packet */
   if (XcpTransportSendPacket(packetData, 8, XCP_MASTER_TIMEOUT_T4_MS) == SB_FALSE) //XCP_MASTER_TIMEOUT_T1_MS
   {
@@ -439,7 +446,7 @@ static sb_uint8 XcpMasterSendCmdSetMta(sb_uint32 address)
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
@@ -452,8 +459,8 @@ static sb_uint8 XcpMasterSendCmdSetMta(sb_uint32 address)
     printf(" (set MTA)\n");
     return SB_FALSE;
   }
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdSetMta ***/
 
@@ -470,10 +477,10 @@ static sb_uint8 XcpMasterSendCmdUpload(sb_uint8 data[], sb_uint8 length)
   sb_uint8 packetData[2];
   tXcpTransportResponsePacket *responsePacketPtr;
   sb_uint8 data_index;
-  
+
   /* cannot request more data then the max rx data - 1 */
   assert(length < XCP_MASTER_RX_MAX_DATA);
-  
+
   /* prepare the command packet */
   packetData[0] = XCP_MASTER_CMD_UPLOAD;
   packetData[1] = length;
@@ -487,7 +494,7 @@ static sb_uint8 XcpMasterSendCmdUpload(sb_uint8 data[], sb_uint8 length)
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
@@ -500,14 +507,14 @@ static sb_uint8 XcpMasterSendCmdUpload(sb_uint8 data[], sb_uint8 length)
     printf(" (upload)\n");
     return SB_FALSE;
   }
-  
+
   /* now store the uploaded data */
   for (data_index=0; data_index<length; data_index++)
   {
     data[data_index] = responsePacketPtr->data[data_index+1];
   }
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdUpload ***/
 
@@ -534,7 +541,7 @@ static sb_uint8 XcpMasterSendCmdProgramStart(void)
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
@@ -547,13 +554,13 @@ static sb_uint8 XcpMasterSendCmdProgramStart(void)
     printf(" (program start)\n");
     return SB_FALSE;
   }
-  
+
   /* store max number of bytes the slave allows for master->slave packets during the
    * programming session
    */
   xcpMaxProgCto = responsePacketPtr->data[3];
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdProgramStart ***/
 
@@ -579,21 +586,21 @@ static sb_uint8 XcpMasterSendCmdDisconnect(void)
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
     /* not a valid or positive response */
     return SB_FALSE;
   }
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdProgramStart ***/
 
 
 /************************************************************************************//**
-** \brief     Sends the XCP PROGRAM RESET command. Note that this command is a bit 
+** \brief     Sends the XCP PROGRAM RESET command. Note that this command is a bit
 **            different as in it does not require a response.
 ** \return    SB_TRUE is successfull, SB_FALSE otherwise.
 **
@@ -626,7 +633,7 @@ static sb_uint8 XcpMasterSendCmdProgramReset(void)
 
 //  /* still here so a response was received */
 //  responsePacketPtr = XcpTransportReadResponsePacket();
-//  
+//
 //  /* check if the reponse was valid */
 //  printf("response not valid\nlength: %u\nresponse: %i", responsePacketPtr->len, *(responsePacketPtr->data));
 //  if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
@@ -635,8 +642,8 @@ static sb_uint8 XcpMasterSendCmdProgramReset(void)
 //    return SB_FALSE;
 //  }
 
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdProgramReset ***/
 
@@ -653,10 +660,10 @@ static sb_uint8 XcpMasterSendCmdProgram(sb_uint8 length, sb_uint8 data[])
   sb_uint8 packetData[XCP_MASTER_TX_MAX_DATA];
   tXcpTransportResponsePacket *responsePacketPtr;
   sb_uint8 cnt;
-  
+
   /* verify that this number of bytes actually first in this command */
   assert(length <= (xcpMaxProgCto-2) && (xcpMaxProgCto <= XCP_MASTER_TX_MAX_DATA));
-  
+
   /* prepare the command packet */
   packetData[0] = XCP_MASTER_CMD_PROGRAM;
   packetData[1] = length;
@@ -674,7 +681,7 @@ static sb_uint8 XcpMasterSendCmdProgram(sb_uint8 length, sb_uint8 data[])
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
@@ -687,8 +694,8 @@ static sb_uint8 XcpMasterSendCmdProgram(sb_uint8 length, sb_uint8 data[])
     printf(" (program)\n");
     return SB_FALSE;
   }
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdProgram ***/
 
@@ -704,10 +711,10 @@ static sb_uint8 XcpMasterSendCmdProgramMax(sb_uint8 data[])
   sb_uint8 packetData[XCP_MASTER_TX_MAX_DATA];
   tXcpTransportResponsePacket *responsePacketPtr;
   sb_uint8 cnt;
-  
+
   /* verify that this number of bytes actually first in this command */
   assert(xcpMaxProgCto <= XCP_MASTER_TX_MAX_DATA);
-  
+
   /* prepare the command packet */
   packetData[0] = XCP_MASTER_CMD_PROGRAM_MAX;
   for (cnt=0; cnt<(xcpMaxProgCto-1); cnt++)
@@ -724,7 +731,7 @@ static sb_uint8 XcpMasterSendCmdProgramMax(sb_uint8 data[])
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
@@ -737,8 +744,8 @@ static sb_uint8 XcpMasterSendCmdProgramMax(sb_uint8 data[])
     printf(" (program max)\n");
     return SB_FALSE;
   }
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdProgramMax ***/
 
@@ -772,7 +779,7 @@ static sb_uint8 XcpMasterSendCmdProgramClear(sb_uint32 length)
   }
   /* still here so a response was received */
   responsePacketPtr = XcpTransportReadResponsePacket();
-  
+
   /* check if the reponse was valid */
   if ( (responsePacketPtr->len == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
   {
@@ -785,8 +792,8 @@ static sb_uint8 XcpMasterSendCmdProgramClear(sb_uint32 length)
     printf(" (program clear)\n");
     return SB_FALSE;
   }
-  
-  /* still here so all went well */  
+
+  /* still here so all went well */
   return SB_TRUE;
 } /*** end of XcpMasterSendCmdProgramClear ***/
 
diff --git a/Host/Source/SerialBoot/xcpmaster.h b/Host/Source/SerialBoot/xcpmaster.h
index 1e63d58..2bea9ed 100644
--- a/Host/Source/SerialBoot/xcpmaster.h
+++ b/Host/Source/SerialBoot/xcpmaster.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef XCPMASTER_H
@@ -58,7 +58,7 @@
 ****************************************************************************************/
 sb_uint8 XcpMasterInit(sb_char *device, sb_uint32 baudrate, sb_uint8 comIsUart);
 void     XcpMasterDeinit(void);
-sb_uint8 XcpMasterConnect(sb_uint8 flashingTargetID);
+sb_uint8 XcpMasterConnect(sb_uint32 flashingTargetID);
 sb_uint8 XcpMasterDisconnect(void);
 sb_uint8 XcpMasterProgramReset(void);
 sb_uint8 XcpMasterStartProgrammingSession(void);
diff --git a/Target/Modules/DiWheelDrive_1-1/Boot/blt_conf.h b/Target/Modules/DiWheelDrive_1-1/Boot/blt_conf.h
index 90e62d8..2d5f344 100644
--- a/Target/Modules/DiWheelDrive_1-1/Boot/blt_conf.h
+++ b/Target/Modules/DiWheelDrive_1-1/Boot/blt_conf.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef BLT_CONF_H
@@ -37,17 +37,17 @@
 *   C P U   D R I V E R   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* To properly initialize the baudrate clocks of the communication interface, typically
- * the speed of the crystal oscillator and/or the speed at which the system runs is 
+ * the speed of the crystal oscillator and/or the speed at which the system runs is
  * needed. Set these through configurables BOOT_CPU_XTAL_SPEED_KHZ and
  * BOOT_CPU_SYSTEM_SPEED_KHZ, respectively. To enable data exchange with the host that is
- * not dependent on the targets architecture, the byte ordering needs to be known. 
- * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects 
+ * not dependent on the targets architecture, the byte ordering needs to be known.
+ * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects
  * big endian mode.
- * 
+ *
  * Set BOOT_CPU_USER_PROGRAM_START_HOOK to 1 if you would like a hook function to be
  * called the moment the user program is about to be started. This could be used to
  * de-initialize application specific parts, for example to stop blinking an LED, etc.
- */ 
+ */
 /** \brief Frequency of the external crystal oscillator. */
 #define BOOT_CPU_XTAL_SPEED_KHZ         (8000)
 /** \brief Desired system speed. */
@@ -66,7 +66,7 @@
  * have to be controlled by this bootloader. Additionally the bootloader should be able
  * to send program code of user programs for other devices.
  * Make sure that one of the communication interfaces is the gateway!
- */ 
+ */
 /** \brief Bootloader of main device. */
 #define BOOTLOADER_OF_MAIN_DEVICE       (1)
 
@@ -74,52 +74,64 @@
 /****************************************************************************************
 *   C O M M U N I C A T I O N   I N T E R F A C E   C O N F I G U R A T I O N
 ****************************************************************************************/
-/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE 
+/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE
  * configurable to 1. Configurable BOOT_COM_CAN_BAUDRATE selects the communication speed
- * in bits/second. Two CAN messages are reserved for communication with the host. The 
+ * in bits/second. Two CAN messages are reserved for communication with the host. The
  * message identifier for sending data from the target to the host is configured with
  * BOOT_COM_CAN_TXMSG_ID. The one for receiving data from the host is configured with
- * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data 
- * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and 
+ * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data
+ * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and
  * BOOT_COM_CAN_RX_MAX_DATA, respectively. It is common for a microcontroller to have more
  * than 1 CAN controller on board. The zero-based BOOT_COM_CAN_CHANNEL_INDEX selects the
  * CAN controller channel.
- * 
+ *
  */
 /** \brief Enable/disable CAN transport layer. */
 #define BOOT_GATE_CAN_ENABLE            (1)
 /** \brief Configure the desired CAN baudrate. */
-#define BOOT_COM_CAN_BAUDRATE           (500000)
+#define BOOT_COM_CAN_BAUDRATE           (1000000)
 /** \brief Configure CAN message ID target->host. */
-#define BOOT_COM_CAN_TX_MSG_ID          (0x700) //(0x7E1)
+#define BOOT_COM_CAN_TX_MSG_ID          (0x700)
 /** \brief Configure number of bytes in the target->host CAN message. */
 #define BOOT_COM_CAN_TX_MAX_DATA        (255)
 /** \brief Configure CAN message ID host->target. */
-#define BOOT_COM_CAN_RX_MSG_ID          (0x600) //(0x667)
+#define BOOT_COM_CAN_RX_MSG_ID          (0x600)
 /** \brief Configure number of bytes in the host->target CAN message. */
 #define BOOT_COM_CAN_RX_MAX_DATA        (255)
 /** \brief Select the desired CAN peripheral as a zero based index. */
 #define BOOT_COM_CAN_CHANNEL_INDEX      (0)
+/** \brief Configure CAN message acknowledgement ID addition (ORed with original ID). */
+#define BOOT_COM_CAN_MSG_ACK            (0x001)
+/** \brief Configure CAN message ID addition for continuous messages (ORed with original ID). */
+#define BOOT_COM_CAN_MSG_SUBSEQUENT     (0x002)
 
-/** \brief Configure device ID for communication (start with 1). */
-#define BOOT_COM_DEVICE_ID              (0x1)
+/**
+ * \brief Configure device ID for communication (start with 1).
+ * \details The device ID is a 32 bit integer, which can be interpreted bytewise:
+ *            <AMiRo_revision>:<moduleID>:<moduleVersion_major>:<moduleVersion_minor>
+ *          For this module the according values are
+ *            1:0:1:1 = 0x01000101
+ */
+#define BOOT_COM_DEVICE_ID              (0x01000101)
+/** \brief Configure legacy device ID. */
+#define BOOT_COM_DEVICE_LEGACY_ID       (0x1)
 
-/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE 
+/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE
  * configurable to 1. Configurable BOOT_COM_UART_BAUDRATE selects the communication speed
- * in bits/second. The maximum amount of data bytes in a message for data transmission 
- * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA, 
+ * in bits/second. The maximum amount of data bytes in a message for data transmission
+ * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA,
  * respectively. It is common for a microcontroller to have more than 1 UART interface
  * on board. The zero-based BOOT_COM_UART_CHANNEL_INDEX selects the UART interface.
- * 
+ *
  */
 /** \brief Enable/disable UART transport layer. */
 #define BOOT_COM_UART_ENABLE            (1)
 /** \brief Configure the desired communication speed. */
-#define BOOT_COM_UART_BAUDRATE          (115200) //(57600)
+#define BOOT_COM_UART_BAUDRATE          (115200)
 /** \brief Configure number of bytes in the target->host data packet. */
-#define BOOT_COM_UART_TX_MAX_DATA       (255) //(64)
+#define BOOT_COM_UART_TX_MAX_DATA       (255)
 /** \brief Configure number of bytes in the host->target data packet. */
-#define BOOT_COM_UART_RX_MAX_DATA       (255) //(64)
+#define BOOT_COM_UART_RX_MAX_DATA       (255)
 /** \brief Select the desired UART peripheral as a zero based index. */
 #define BOOT_COM_UART_CHANNEL_INDEX     (0)
 /* Activate debugging with UART2 */
@@ -130,8 +142,8 @@
 *   F I L E   S Y S T E M   I N T E R F A C E   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* The file system interface is selected by setting the BOOT_FILE_SYS_ENABLE configurable
- * to 1. This enables support for firmware updates from a file stored on a locally 
- * attached file system such as an SD-card. Note that this interface can be enabled 
+ * to 1. This enables support for firmware updates from a file stored on a locally
+ * attached file system such as an SD-card. Note that this interface can be enabled
  * together with one of the remote communication interfaces such as UART, CAN or USB.
  *
  * Set BOOT_FILE_LOGGING_ENABLE to 1 if you would like log messages to be created during
@@ -145,29 +157,29 @@
  * additional information on the error cause.
  *
  * Set BOOT_FILE_STARTED_HOOK_ENABLE to 1 if you would like to be informed when a new
- * firmware update is started by the bootloader. 
+ * firmware update is started by the bootloader.
  *
  * Set BOOT_FILE_COMPLETED_HOOK_ENABLE to 1 if you would like to be informed when a
- * firmware update is completed by the bootloader. 
+ * firmware update is completed by the bootloader.
  */
 /** \brief Enable/disable support for firmware updates from a locally attached storage.*/
 #define BOOT_FILE_SYS_ENABLE            (0)
 /** \brief Enable/disable logging messages during firmware updates. */
 #define BOOT_FILE_LOGGING_ENABLE        (1)
 /** \brief Enable/disable a hook function that is called upon detection of an error. */
-#define BOOT_FILE_ERROR_HOOK_ENABLE     (1)   
+#define BOOT_FILE_ERROR_HOOK_ENABLE     (1)
 /** \brief Enable/disable a hook function that is called at the start of the update. */
-#define BOOT_FILE_STARTED_HOOK_ENABLE   (1)   
+#define BOOT_FILE_STARTED_HOOK_ENABLE   (1)
 /** \brief Enable/disable a hook function that is called at the end of the update. */
-#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)   
+#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)
+
 
-   
 /****************************************************************************************
 *   B A C K D O O R   E N T R Y   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* It is possible to implement an application specific method to force the bootloader to
  * stay active after a reset. Such a backdoor entry into the bootloader is desired in
- * situations where the user program does not run properly and therefore cannot 
+ * situations where the user program does not run properly and therefore cannot
  * reactivate the bootloader. By enabling these hook functions, the application can
  * implement the backdoor, which overrides the default backdoor entry that is programmed
  * into the bootloader. When desired for security purposes, these hook functions can
@@ -213,15 +225,15 @@
 *   S E E D / K E Y   S E C U R I T Y   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* A security mechanism can be enabled in the bootloader's XCP module by setting configu-
- * rable BOOT_XCP_SEED_KEY_ENABLE to 1. Before any memory erase or programming 
- * operations can be performed, access to this resource need to be unlocked. 
- * In the Microboot settings on tab "XCP Protection" you need to specify a DLL that 
- * implements the unlocking algorithm. The demo programs are configured for the (simple) 
- * algorithm in "FeaserKey.dll". The source code for this DLL is available so it can be 
- * customized to your needs. 
+ * rable BOOT_XCP_SEED_KEY_ENABLE to 1. Before any memory erase or programming
+ * operations can be performed, access to this resource need to be unlocked.
+ * In the Microboot settings on tab "XCP Protection" you need to specify a DLL that
+ * implements the unlocking algorithm. The demo programs are configured for the (simple)
+ * algorithm in "FeaserKey.dll". The source code for this DLL is available so it can be
+ * customized to your needs.
  * During the unlock sequence, Microboot requests a seed from the bootloader, which is in
- * the format of a byte array. Using this seed the unlock algorithm in the DLL computes 
- * a key, which is also a byte array, and sends this back to the bootloader. The 
+ * the format of a byte array. Using this seed the unlock algorithm in the DLL computes
+ * a key, which is also a byte array, and sends this back to the bootloader. The
  * bootloader then verifies this key to determine if programming and erase operations are
  * permitted.
  * After enabling this feature the hook functions XcpGetSeedHook() and XcpVerifyKeyHook()
diff --git a/Target/Modules/DiWheelDrive_1-1/Boot/main.c b/Target/Modules/DiWheelDrive_1-1/Boot/main.c
index dbe643f..99c916b 100644
--- a/Target/Modules/DiWheelDrive_1-1/Boot/main.c
+++ b/Target/Modules/DiWheelDrive_1-1/Boot/main.c
@@ -42,7 +42,6 @@
 #include "AMiRo/amiroblt.h"
 #include "AMiRo/helper.h"
 
-
 /****************************************************************************************
 * Defines
 ****************************************************************************************/
@@ -170,7 +169,7 @@ void blCallbackHandleShutdownRequest(void);
 
 const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
   .magicNumber = BL_MAGIC_NUMBER,
-  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 1},
+  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
   .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
   .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
   .cbShutdownHibernate = blCallbackShutdownHibernate,
@@ -797,19 +796,19 @@ ErrorStatus handleColdReset() {
       uint32_t currentTime = loopStartTime;
       while (1)
       {
-        /* make the LED "double-blink" */
-        saTimerUpdate(&currentTime);
-        if (currentTime < loopStartTime + 50) {
-          setLed(BLT_TRUE);
-        } else if (currentTime < loopStartTime + 50+100) {
-          setLed(BLT_FALSE);
-        } else if (currentTime < loopStartTime + 50+100+50) {
-          setLed(BLT_TRUE);
-        } else if ( currentTime < loopStartTime + 50+100+50+300) {
-          setLed(BLT_FALSE);
-        } else {
-          loopStartTime = currentTime;
-        }
+//        /* make the LED "double-blink" */
+//        saTimerUpdate(&currentTime);
+//        if (currentTime < loopStartTime + 50) {
+//          setLed(BLT_TRUE);
+//        } else if (currentTime < loopStartTime + 50+100) {
+//          setLed(BLT_FALSE);
+//        } else if (currentTime < loopStartTime + 50+100+50) {
+//          setLed(BLT_TRUE);
+//        } else if ( currentTime < loopStartTime + 50+100+50+300) {
+//          setLed(BLT_FALSE);
+//        } else {
+//          loopStartTime = currentTime;
+//        }
 
         /* run the bootloader task */
         BootTask();
diff --git a/Target/Modules/LightRing_1-0/Boot/blt_conf.h b/Target/Modules/LightRing_1-0/Boot/blt_conf.h
index d47de8b..7753e4b 100644
--- a/Target/Modules/LightRing_1-0/Boot/blt_conf.h
+++ b/Target/Modules/LightRing_1-0/Boot/blt_conf.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef BLT_CONF_H
@@ -37,17 +37,17 @@
 *   C P U   D R I V E R   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* To properly initialize the baudrate clocks of the communication interface, typically
- * the speed of the crystal oscillator and/or the speed at which the system runs is 
+ * the speed of the crystal oscillator and/or the speed at which the system runs is
  * needed. Set these through configurables BOOT_CPU_XTAL_SPEED_KHZ and
  * BOOT_CPU_SYSTEM_SPEED_KHZ, respectively. To enable data exchange with the host that is
- * not dependent on the targets architecture, the byte ordering needs to be known. 
- * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects 
+ * not dependent on the targets architecture, the byte ordering needs to be known.
+ * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects
  * big endian mode.
- * 
+ *
  * Set BOOT_CPU_USER_PROGRAM_START_HOOK to 1 if you would like a hook function to be
  * called the moment the user program is about to be started. This could be used to
  * de-initialize application specific parts, for example to stop blinking an LED, etc.
- */ 
+ */
 /** \brief Frequency of the external crystal oscillator. */
 #define BOOT_CPU_XTAL_SPEED_KHZ         (8000)
 /** \brief Desired system speed. */
@@ -66,7 +66,7 @@
  * have to be controlled by this bootloader. Additionally the bootloader should be able
  * to send program code of user programs for other devices.
  * Make sure that one of the communication interfaces is the gateway!
- */ 
+ */
 /** \brief Bootloader of main device. */
 #define BOOTLOADER_OF_MAIN_DEVICE       (0)
 
@@ -74,48 +74,61 @@
 /****************************************************************************************
 *   C O M M U N I C A T I O N   I N T E R F A C E   C O N F I G U R A T I O N
 ****************************************************************************************/
-/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE 
+/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE
  * configurable to 1. Configurable BOOT_COM_CAN_BAUDRATE selects the communication speed
- * in bits/second. Two CAN messages are reserved for communication with the host. The 
+ * in bits/second. Two CAN messages are reserved for communication with the host. The
  * message identifier for sending data from the target to the host is configured with
  * BOOT_COM_CAN_TXMSG_ID. The one for receiving data from the host is configured with
- * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data 
- * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and 
+ * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data
+ * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and
  * BOOT_COM_CAN_RX_MAX_DATA, respectively. It is common for a microcontroller to have more
  * than 1 CAN controller on board. The zero-based BOOT_COM_CAN_CHANNEL_INDEX selects the
  * CAN controller channel.
- * 
+ *
  */
 /** \brief Enable/disable CAN transport layer. */
 #define BOOT_COM_CAN_ENABLE             (1)
 /** \brief Configure the desired CAN baudrate. */
-#define BOOT_COM_CAN_BAUDRATE           (500000)
+#define BOOT_COM_CAN_BAUDRATE           (1000000)
 /** \brief Configure CAN message ID target->host. */
-#define BOOT_COM_CAN_TX_MSG_ID          (0x700) //(0x667) //(0x7E1)
+#define BOOT_COM_CAN_TX_MSG_ID          (0x700)
 /** \brief Configure number of bytes in the target->host CAN message. */
 #define BOOT_COM_CAN_TX_MAX_DATA        (255)
 /** \brief Configure CAN message ID host->target. */
-#define BOOT_COM_CAN_RX_MSG_ID          (0x600) //(0x7E1) //(0x667)
+#define BOOT_COM_CAN_RX_MSG_ID          (0x600)
 /** \brief Configure number of bytes in the host->target CAN message. */
 #define BOOT_COM_CAN_RX_MAX_DATA        (255)
 /** \brief Select the desired CAN peripheral as a zero based index. */
 #define BOOT_COM_CAN_CHANNEL_INDEX      (0)
+/** \brief Configure CAN message acknowledgement ID addition (ORed with original ID). */
+#define BOOT_COM_CAN_MSG_ACK            (0x001)
+/** \brief Configure CAN message ID addition for continuous messages (ORed with original ID). */
+#define BOOT_COM_CAN_MSG_SUBSEQUENT     (0x002)
+
+/**
+ * \brief Configure device ID for communication (start with 1).
+ * \details The device ID is a 32 bit integer, which can be interpreted bytewise:
+ *            <AMiRo_revision>:<moduleID>:<moduleVersion_major>:<moduleVersion_minor>
+ *          For this module the according values are
+ *            1:127:1:0 = 0x017F0100
+ */
+#define BOOT_COM_DEVICE_ID              (0x017F0100)
+/** \brief Configure legacy device ID. */
+#define BOOT_COM_DEVICE_LEGACY_ID       (0x3)
 
-/** \brief Configure device ID for communication (start with 1). */
-#define BOOT_COM_DEVICE_ID              (0x3)
 
-/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE 
+/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE
  * configurable to 1. Configurable BOOT_COM_UART_BAUDRATE selects the communication speed
- * in bits/second. The maximum amount of data bytes in a message for data transmission 
- * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA, 
+ * in bits/second. The maximum amount of data bytes in a message for data transmission
+ * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA,
  * respectively. It is common for a microcontroller to have more than 1 UART interface
  * on board. The zero-based BOOT_COM_UART_CHANNEL_INDEX selects the UART interface.
- * 
+ *
  */
 /** \brief Enable/disable UART transport layer. */
 #define BOOT_COM_UART_ENABLE            (1)
 /** \brief Configure the desired communication speed. */
-#define BOOT_COM_UART_BAUDRATE          (115200) //(57600)
+#define BOOT_COM_UART_BAUDRATE          (115200)
 /** \brief Configure number of bytes in the target->host data packet. */
 #define BOOT_COM_UART_TX_MAX_DATA       (255)
 /** \brief Configure number of bytes in the host->target data packet. */
@@ -130,8 +143,8 @@
 *   F I L E   S Y S T E M   I N T E R F A C E   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* The file system interface is selected by setting the BOOT_FILE_SYS_ENABLE configurable
- * to 1. This enables support for firmware updates from a file stored on a locally 
- * attached file system such as an SD-card. Note that this interface can be enabled 
+ * to 1. This enables support for firmware updates from a file stored on a locally
+ * attached file system such as an SD-card. Note that this interface can be enabled
  * together with one of the remote communication interfaces such as UART, CAN or USB.
  *
  * Set BOOT_FILE_LOGGING_ENABLE to 1 if you would like log messages to be created during
@@ -145,29 +158,29 @@
  * additional information on the error cause.
  *
  * Set BOOT_FILE_STARTED_HOOK_ENABLE to 1 if you would like to be informed when a new
- * firmware update is started by the bootloader. 
+ * firmware update is started by the bootloader.
  *
  * Set BOOT_FILE_COMPLETED_HOOK_ENABLE to 1 if you would like to be informed when a
- * firmware update is completed by the bootloader. 
+ * firmware update is completed by the bootloader.
  */
 /** \brief Enable/disable support for firmware updates from a locally attached storage.*/
 #define BOOT_FILE_SYS_ENABLE            (0)
 /** \brief Enable/disable logging messages during firmware updates. */
 #define BOOT_FILE_LOGGING_ENABLE        (1)
 /** \brief Enable/disable a hook function that is called upon detection of an error. */
-#define BOOT_FILE_ERROR_HOOK_ENABLE     (1)   
+#define BOOT_FILE_ERROR_HOOK_ENABLE     (1)
 /** \brief Enable/disable a hook function that is called at the start of the update. */
-#define BOOT_FILE_STARTED_HOOK_ENABLE   (1)   
+#define BOOT_FILE_STARTED_HOOK_ENABLE   (1)
 /** \brief Enable/disable a hook function that is called at the end of the update. */
-#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)   
+#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)
+
 
-   
 /****************************************************************************************
 *   B A C K D O O R   E N T R Y   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* It is possible to implement an application specific method to force the bootloader to
  * stay active after a reset. Such a backdoor entry into the bootloader is desired in
- * situations where the user program does not run properly and therefore cannot 
+ * situations where the user program does not run properly and therefore cannot
  * reactivate the bootloader. By enabling these hook functions, the application can
  * implement the backdoor, which overrides the default backdoor entry that is programmed
  * into the bootloader. When desired for security purposes, these hook functions can
@@ -213,15 +226,15 @@
 *   S E E D / K E Y   S E C U R I T Y   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* A security mechanism can be enabled in the bootloader's XCP module by setting configu-
- * rable BOOT_XCP_SEED_KEY_ENABLE to 1. Before any memory erase or programming 
- * operations can be performed, access to this resource need to be unlocked. 
- * In the Microboot settings on tab "XCP Protection" you need to specify a DLL that 
- * implements the unlocking algorithm. The demo programs are configured for the (simple) 
- * algorithm in "FeaserKey.dll". The source code for this DLL is available so it can be 
- * customized to your needs. 
+ * rable BOOT_XCP_SEED_KEY_ENABLE to 1. Before any memory erase or programming
+ * operations can be performed, access to this resource need to be unlocked.
+ * In the Microboot settings on tab "XCP Protection" you need to specify a DLL that
+ * implements the unlocking algorithm. The demo programs are configured for the (simple)
+ * algorithm in "FeaserKey.dll". The source code for this DLL is available so it can be
+ * customized to your needs.
  * During the unlock sequence, Microboot requests a seed from the bootloader, which is in
- * the format of a byte array. Using this seed the unlock algorithm in the DLL computes 
- * a key, which is also a byte array, and sends this back to the bootloader. The 
+ * the format of a byte array. Using this seed the unlock algorithm in the DLL computes
+ * a key, which is also a byte array, and sends this back to the bootloader. The
  * bootloader then verifies this key to determine if programming and erase operations are
  * permitted.
  * After enabling this feature the hook functions XcpGetSeedHook() and XcpVerifyKeyHook()
diff --git a/Target/Modules/LightRing_1-0/Boot/main.c b/Target/Modules/LightRing_1-0/Boot/main.c
index 02c94bd..0b2ce37 100644
--- a/Target/Modules/LightRing_1-0/Boot/main.c
+++ b/Target/Modules/LightRing_1-0/Boot/main.c
@@ -42,7 +42,6 @@
 #include "AMiRo/amiroblt.h"
 #include "AMiRo/helper.h"
 
-
 /****************************************************************************************
 * Defines
 ****************************************************************************************/
@@ -140,7 +139,7 @@ void blCallbackHandleShutdownRequest(void);
 
 const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
   .magicNumber = BL_MAGIC_NUMBER,
-  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 1},
+  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
   .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
   .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
   .cbShutdownHibernate = blCallbackShutdownHibernate,
@@ -659,19 +658,19 @@ ErrorStatus handleWarmReset() {
   uint32_t currentTime = loopStartTime;
   while (1)
   {
-    /* make the pseudo LED "double-blink" */
-    saTimerUpdate(&currentTime);
-    if (currentTime < loopStartTime + 50) {
-      setLed(BLT_TRUE);
-    } else if (currentTime < loopStartTime + 50+100) {
-      setLed(BLT_FALSE);
-    } else if (currentTime < loopStartTime + 50+100+50) {
-      setLed(BLT_TRUE);
-    } else if ( currentTime < loopStartTime + 50+100+50+300) {
-      setLed(BLT_FALSE);
-    } else {
-      loopStartTime = currentTime;
-    }
+//    /* make the pseudo LED "double-blink" */
+//    saTimerUpdate(&currentTime);
+//    if (currentTime < loopStartTime + 50) {
+//      setLed(BLT_TRUE);
+//    } else if (currentTime < loopStartTime + 50+100) {
+//      setLed(BLT_FALSE);
+//    } else if (currentTime < loopStartTime + 50+100+50) {
+//      setLed(BLT_TRUE);
+//    } else if ( currentTime < loopStartTime + 50+100+50+300) {
+//      setLed(BLT_FALSE);
+//    } else {
+//      loopStartTime = currentTime;
+//    }
 
     /* run the bootloader task */
     BootTask();
diff --git a/Target/Modules/PowerManagement_1-1/Boot/blt_conf.h b/Target/Modules/PowerManagement_1-1/Boot/blt_conf.h
index 6c318d7..298a459 100644
--- a/Target/Modules/PowerManagement_1-1/Boot/blt_conf.h
+++ b/Target/Modules/PowerManagement_1-1/Boot/blt_conf.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef BLT_CONF_H
@@ -37,17 +37,17 @@
 *   C P U   D R I V E R   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* To properly initialize the baudrate clocks of the communication interface, typically
- * the speed of the crystal oscillator and/or the speed at which the system runs is 
+ * the speed of the crystal oscillator and/or the speed at which the system runs is
  * needed. Set these through configurables BOOT_CPU_XTAL_SPEED_KHZ and
  * BOOT_CPU_SYSTEM_SPEED_KHZ, respectively. To enable data exchange with the host that is
- * not dependent on the targets architecture, the byte ordering needs to be known. 
- * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects 
+ * not dependent on the targets architecture, the byte ordering needs to be known.
+ * Setting BOOT_CPU_BYTE_ORDER_MOTOROLA to 1 selects little endian mode and 0 selects
  * big endian mode.
- * 
+ *
  * Set BOOT_CPU_USER_PROGRAM_START_HOOK to 1 if you would like a hook function to be
  * called the moment the user program is about to be started. This could be used to
  * de-initialize application specific parts, for example to stop blinking an LED, etc.
- */ 
+ */
 /** \brief Frequency of the external crystal oscillator. */
 #define BOOT_CPU_XTAL_SPEED_KHZ          (8000)
 /** \brief Desired system speed. */
@@ -66,7 +66,7 @@
  * have to be controlled by this bootloader. Additionally the bootloader should be able
  * to send program code of user programs for other devices.
  * Make sure that one of the communication interfaces is the gateway!
- */ 
+ */
 /** \brief Bootloader of main device. */
 #define BOOTLOADER_OF_MAIN_DEVICE       (1)
 
@@ -74,22 +74,22 @@
 /****************************************************************************************
 *   C O M M U N I C A T I O N   I N T E R F A C E   C O N F I G U R A T I O N
 ****************************************************************************************/
-/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE 
+/* The CAN communication interface is selected by setting the BOOT_COM_CAN_ENABLE
  * configurable to 1. Configurable BOOT_COM_CAN_BAUDRATE selects the communication speed
- * in bits/second. Two CAN messages are reserved for communication with the host. The 
+ * in bits/second. Two CAN messages are reserved for communication with the host. The
  * message identifier for sending data from the target to the host is configured with
  * BOOT_COM_CAN_TXMSG_ID. The one for receiving data from the host is configured with
- * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data 
- * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and 
+ * BOOT_COM_CAN_RXMSG_ID. The maximum amount of data bytes in a message for data
+ * transmission and reception is set through BOOT_COM_CAN_TX_MAX_DATA and
  * BOOT_COM_CAN_RX_MAX_DATA, respectively. It is common for a microcontroller to have more
  * than 1 CAN controller on board. The zero-based BOOT_COM_CAN_CHANNEL_INDEX selects the
  * CAN controller channel.
- * 
+ *
  */
 /** \brief Enable/disable CAN transport layer. */
 #define BOOT_GATE_CAN_ENABLE            (1)
 /** \brief Configure the desired CAN baudrate. */
-#define BOOT_COM_CAN_BAUDRATE           (500000)
+#define BOOT_COM_CAN_BAUDRATE           (1000000)
 /** \brief Configure CAN message ID target->host. */
 #define BOOT_COM_CAN_TX_MSG_ID          (0x700)
 /** \brief Configure number of bytes in the target->host CAN message. */
@@ -100,17 +100,30 @@
 #define BOOT_COM_CAN_RX_MAX_DATA        (255)
 /** \brief Select the desired CAN peripheral as a zero based index. */
 #define BOOT_COM_CAN_CHANNEL_INDEX      (0)
+/** \brief Configure CAN message acknowledgement ID addition (ORed with original ID). */
+#define BOOT_COM_CAN_MSG_ACK            (0x001)
+/** \brief Configure CAN message ID addition for continuous messages (ORed with original ID). */
+#define BOOT_COM_CAN_MSG_SUBSEQUENT     (0x002)
+
+/**
+ * \brief Configure device ID for communication (start with 1).
+ * \details The device ID is a 32 bit integer, which can be interpreted bytewise:
+ *            <AMiRo_revision>:<moduleID>:<moduleVersion_major>:<moduleVersion_minor>
+ *          For this module the according values are
+ *            1:1:1:1 = 0x01010101
+ */
+#define BOOT_COM_DEVICE_ID              (0x01010101)
+/** \brief Configure legacy device ID. */
+#define BOOT_COM_DEVICE_LEGACY_ID       (0x2)
 
-/** \brief Configure device ID for communication (start with 1). */
-#define BOOT_COM_DEVICE_ID              (0x2)
 
-/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE 
+/* The UART communication interface is selected by setting the BOOT_COM_UART_ENABLE
  * configurable to 1. Configurable BOOT_COM_UART_BAUDRATE selects the communication speed
- * in bits/second. The maximum amount of data bytes in a message for data transmission 
- * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA, 
+ * in bits/second. The maximum amount of data bytes in a message for data transmission
+ * and reception is set through BOOT_COM_UART_TX_MAX_DATA and BOOT_COM_UART_RX_MAX_DATA,
  * respectively. It is common for a microcontroller to have more than 1 UART interface
  * on board. The zero-based BOOT_COM_UART_CHANNEL_INDEX selects the UART interface.
- * 
+ *
  */
 /** \brief Enable/disable UART transport layer. */
 #define BOOT_COM_UART_ENABLE            (1)
@@ -129,9 +142,9 @@
 
 
 /* The NET communication interface for firmware updates via TCP/IP is selected by setting
- * the BOOT_COM_NET_ENABLE configurable to 1. The maximum amount of data bytes in a 
- * message for data transmission and reception is set through BOOT_COM_NET_TX_MAX_DATA 
- * and BOOT_COM_NET_RX_MAX_DATA, respectively. The default IP address is configured 
+ * the BOOT_COM_NET_ENABLE configurable to 1. The maximum amount of data bytes in a
+ * message for data transmission and reception is set through BOOT_COM_NET_TX_MAX_DATA
+ * and BOOT_COM_NET_RX_MAX_DATA, respectively. The default IP address is configured
  * with the macros BOOT_COM_NET_IPADDRx. The default netmask is configued with the macros
  * BOOT_COM_NET_NETMASKx. The default gateway is configured with the macros
  * BOOT_COM_NET_GATEWAYx. The bootloader acts and a TCP/IP server. The port the server
@@ -177,8 +190,8 @@
  *         to be set. This allows a dynamic override of the BOOT_COM_NET_NETMASKx values.
  */
 #define BOOT_COM_NET_NETMASK_HOOK_ENABLE (0)
-/** \brief Enable/disable a hook function that is called when the gateway address is 
- *         about to be set. This allows a dynamic override of the BOOT_COM_NET_GATEWAYx 
+/** \brief Enable/disable a hook function that is called when the gateway address is
+ *         about to be set. This allows a dynamic override of the BOOT_COM_NET_GATEWAYx
  *         values.
  */
 #define BOOT_COM_NET_GATEWAY_HOOK_ENABLE (0)
@@ -190,14 +203,14 @@
 #if (BOOT_COM_NET_ENABLE > 0)
 /* Override the default time that the backdoor is open if firmware updates via TCP/IP
  * are supported. in this case a reactivation of the bootloader results in a re-
- * initialization of the ethernet MAC. when directly connected to the ethernet port of 
- * a PC this will go relatively fast (depending on what MS Windows is being used), but 
+ * initialization of the ethernet MAC. when directly connected to the ethernet port of
+ * a PC this will go relatively fast (depending on what MS Windows is being used), but
  * when connected to the network via a router this can take several seconds. feel free to
- * shorten/lengthen this time for finetuning. the only downside of a long backdoor open 
+ * shorten/lengthen this time for finetuning. the only downside of a long backdoor open
  * time is that the starting of the user program will also be delayed for this time.
  *
- * Also note that when the target is directly connected to the ethernet port of a PC, 
- * the checkbox "Automatically retry socket connection" should be checked in the 
+ * Also note that when the target is directly connected to the ethernet port of a PC,
+ * the checkbox "Automatically retry socket connection" should be checked in the
  * Microboot settings. if connecting via a router the uncheck this checkbox.
  */
 #define BACKDOOR_ENTRY_TIMEOUT_MS  (10000)
@@ -208,8 +221,8 @@
 *   F I L E   S Y S T E M   I N T E R F A C E   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* The file system interface is selected by setting the BOOT_FILE_SYS_ENABLE configurable
- * to 1. This enables support for firmware updates from a file stored on a locally 
- * attached file system such as an SD-card. Note that this interface can be enabled 
+ * to 1. This enables support for firmware updates from a file stored on a locally
+ * attached file system such as an SD-card. Note that this interface can be enabled
  * together with one of the remote communication interfaces such as UART, CAN or USB.
  *
  * Set BOOT_FILE_LOGGING_ENABLE to 1 if you would like log messages to be created during
@@ -223,29 +236,29 @@
  * additional information on the error cause.
  *
  * Set BOOT_FILE_STARTED_HOOK_ENABLE to 1 if you would like to be informed when a new
- * firmware update is started by the bootloader. 
+ * firmware update is started by the bootloader.
  *
  * Set BOOT_FILE_COMPLETED_HOOK_ENABLE to 1 if you would like to be informed when a
- * firmware update is completed by the bootloader. 
+ * firmware update is completed by the bootloader.
  */
 /** \brief Enable/disable support for firmware updates from a locally attached storage.*/
 #define BOOT_FILE_SYS_ENABLE            (0)
 /** \brief Enable/disable logging messages during firmware updates. */
 #define BOOT_FILE_LOGGING_ENABLE        (1)
 /** \brief Enable/disable a hook function that is called upon detection of an error. */
-#define BOOT_FILE_ERROR_HOOK_ENABLE     (1)   
+#define BOOT_FILE_ERROR_HOOK_ENABLE     (1)
 /** \brief Enable/disable a hook function that is called at the start of the update. */
-#define BOOT_FILE_STARTED_HOOK_ENABLE   (1)   
+#define BOOT_FILE_STARTED_HOOK_ENABLE   (1)
 /** \brief Enable/disable a hook function that is called at the end of the update. */
-#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)   
+#define BOOT_FILE_COMPLETED_HOOK_ENABLE (1)
+
 
-   
 /****************************************************************************************
 *   B A C K D O O R   E N T R Y   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* It is possible to implement an application specific method to force the bootloader to
  * stay active after a reset. Such a backdoor entry into the bootloader is desired in
- * situations where the user program does not run properly and therefore cannot 
+ * situations where the user program does not run properly and therefore cannot
  * reactivate the bootloader. By enabling these hook functions, the application can
  * implement the backdoor, which overrides the default backdoor entry that is programmed
  * into the bootloader. When desired for security purposes, these hook functions can
@@ -291,15 +304,15 @@
 *   S E E D / K E Y   S E C U R I T Y   C O N F I G U R A T I O N
 ****************************************************************************************/
 /* A security mechanism can be enabled in the bootloader's XCP module by setting configu-
- * rable BOOT_XCP_SEED_KEY_ENABLE to 1. Before any memory erase or programming 
- * operations can be performed, access to this resource need to be unlocked. 
- * In the Microboot settings on tab "XCP Protection" you need to specify a DLL that 
- * implements the unlocking algorithm. The demo programs are configured for the (simple) 
- * algorithm in "FeaserKey.dll". The source code for this DLL is available so it can be 
- * customized to your needs. 
+ * rable BOOT_XCP_SEED_KEY_ENABLE to 1. Before any memory erase or programming
+ * operations can be performed, access to this resource need to be unlocked.
+ * In the Microboot settings on tab "XCP Protection" you need to specify a DLL that
+ * implements the unlocking algorithm. The demo programs are configured for the (simple)
+ * algorithm in "FeaserKey.dll". The source code for this DLL is available so it can be
+ * customized to your needs.
  * During the unlock sequence, Microboot requests a seed from the bootloader, which is in
- * the format of a byte array. Using this seed the unlock algorithm in the DLL computes 
- * a key, which is also a byte array, and sends this back to the bootloader. The 
+ * the format of a byte array. Using this seed the unlock algorithm in the DLL computes
+ * a key, which is also a byte array, and sends this back to the bootloader. The
  * bootloader then verifies this key to determine if programming and erase operations are
  * permitted.
  * After enabling this feature the hook functions XcpGetSeedHook() and XcpVerifyKeyHook()
diff --git a/Target/Modules/PowerManagement_1-1/Boot/main.c b/Target/Modules/PowerManagement_1-1/Boot/main.c
index b3f02c3..c446d43 100644
--- a/Target/Modules/PowerManagement_1-1/Boot/main.c
+++ b/Target/Modules/PowerManagement_1-1/Boot/main.c
@@ -193,7 +193,7 @@ void blCallbackHandleShutdownRequest(void);
 
 const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
   .magicNumber = BL_MAGIC_NUMBER,
-  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 1},
+  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
   .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
   .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
   .cbShutdownHibernate = blCallbackShutdownHibernate,
@@ -893,19 +893,19 @@ ErrorStatus handleColdReset() {
   uint32_t currentTime = loopStartTime;
   while (1)
   {
-    /* make the LED "double-blink" */
-    saTimerUpdate(&currentTime);
-    if (currentTime < loopStartTime + 50) {
-      setLed(BLT_TRUE);
-    } else if (currentTime < loopStartTime + 50+100) {
-      setLed(BLT_FALSE);
-    } else if (currentTime < loopStartTime + 50+100+50) {
-      setLed(BLT_TRUE);
-    } else if (currentTime < loopStartTime + 50+100+50+300) {
-      setLed(BLT_FALSE);
-    } else {
-      loopStartTime = currentTime;
-    }
+//    /* make the LED "double-blink" */
+//    saTimerUpdate(&currentTime);
+//    if (currentTime < loopStartTime + 50) {
+//      setLed(BLT_TRUE);
+//    } else if (currentTime < loopStartTime + 50+100) {
+//      setLed(BLT_FALSE);
+//    } else if (currentTime < loopStartTime + 50+100+50) {
+//      setLed(BLT_TRUE);
+//    } else if (currentTime < loopStartTime + 50+100+50+300) {
+//      setLed(BLT_FALSE);
+//    } else {
+//      loopStartTime = currentTime;
+//    }
 
     /* run the bootloader task */
     BootTask();
diff --git a/Target/Source/AMiRo/amiroblt.h b/Target/Source/AMiRo/amiroblt.h
index 2294fbd..439a6e6 100644
--- a/Target/Source/AMiRo/amiroblt.h
+++ b/Target/Source/AMiRo/amiroblt.h
@@ -50,7 +50,7 @@
 /**
  * @brief   The minor version number of the bootloader.
  */
-#define BL_VERSION_MINOR                          0
+#define BL_VERSION_MINOR                          1
 
 /**
  * @brief   The major version number of the implemented SSSP (Startup & Shutdown Synchronization Protocol).
diff --git a/Target/Source/AMiRo/helper.c b/Target/Source/AMiRo/helper.c
index 3621258..677517b 100644
--- a/Target/Source/AMiRo/helper.c
+++ b/Target/Source/AMiRo/helper.c
@@ -333,6 +333,11 @@ void visualizeData(uint8_t* data, uint32_t bytes, uint32_t loops) {
   saTimerUpdate(&stateStartTime);
   uint32_t currentTime = stateStartTime;
 
+  /* return immediately if the number of bytes is zero */
+  if (bytes == 0) {
+    return;
+  }
+
   /* either loop the specified number, or infinetly */
   while (loop < loops || loops == 0) {
     led = 0;
diff --git a/Target/Source/ARMCM3_STM32/can.c b/Target/Source/ARMCM3_STM32/can.c
index 1dcafc6..c5da070 100644
--- a/Target/Source/ARMCM3_STM32/can.c
+++ b/Target/Source/ARMCM3_STM32/can.c
@@ -23,20 +23,25 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 
+#define CAN_DEBUG       (0)
 
 /****************************************************************************************
 * Include files
 ****************************************************************************************/
 #include "boot.h"                                /* bootloader generic header          */
 
+#if (CAN_DEBUG > 0)
+#include <helper.h>
+#endif
+
 
 #if (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
 /****************************************************************************************
@@ -58,7 +63,7 @@ typedef struct
   volatile blt_int32u RDTR;
   volatile blt_int32u RDLR;
   volatile blt_int32u RDHR;
-} tCanRxFIFOMailBox; 
+} tCanRxFIFOMailBox;
 
 /** \brief CAN filter register layout. */
 typedef struct
@@ -92,7 +97,7 @@ typedef struct
   volatile blt_int32u FA1R;
   blt_int32u          RESERVED5[8];
   tCanFilter          sFilterRegister[14];
-} tCanRegs;                                           
+} tCanRegs;
 
 
 /****************************************************************************************
@@ -144,9 +149,9 @@ typedef struct t_can_bus_timing
 * Local constant declarations
 ****************************************************************************************/
 /** \brief CAN bittiming table for dynamically calculating the bittiming settings.
- *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25 
- *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC 
- *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) * 
+ *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25
+ *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC
+ *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) *
  *           100%. This array contains possible and valid time quanta configurations with
  *           a sample point between 68..78%.
  */
@@ -175,17 +180,17 @@ static const tCanBusTiming canTiming[] =
 
 
 /************************************************************************************//**
-** \brief     Search algorithm to match the desired baudrate to a possible bus 
+** \brief     Search algorithm to match the desired baudrate to a possible bus
 **            timing configuration.
 ** \param     baud The desired baudrate in kbps. Valid values are 10..1000.
 ** \param     prescaler Pointer to where the value for the prescaler will be stored.
 ** \param     tseg1 Pointer to where the value for TSEG2 will be stored.
 ** \param     tseg2 Pointer to where the value for TSEG2 will be stored.
-** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE 
+** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE
 **            otherwise.
 **
 ****************************************************************************************/
-static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler, 
+static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler,
                                   blt_int8u *tseg1, blt_int8u *tseg2)
 {
   blt_int8u  cnt;
@@ -229,10 +234,10 @@ void CanInit(void)
   commandSend = BLT_FALSE;
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
 
-  /* the current implementation supports CAN1. throw an assertion error in case a 
-   * different CAN channel is configured.  
+  /* the current implementation supports CAN1. throw an assertion error in case a
+   * different CAN channel is configured.
    */
-  ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0); 
+  ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0);
   /* obtain bittiming configuration information */
   result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2);
   ASSERT_RT(result == BLT_TRUE);
@@ -275,8 +280,8 @@ void CanInit(void)
   /* 32-bit scale for the filter */
   CANx->FS1R |= CAN_BIT_FILTER0;
   /* open up the acceptance filter to receive all messages */
-  CANx->sFilterRegister[0].FR1 = 0; 
-  CANx->sFilterRegister[0].FR2 = 0; 
+  CANx->sFilterRegister[0].FR1 = 0;
+  CANx->sFilterRegister[0].FR2 = 0;
   /* select id/mask mode for the filter */
   CANx->FM1R &= ~CAN_BIT_FILTER0;
   /* FIFO 0 assignation for the filter */
@@ -296,12 +301,10 @@ void CanInit(void)
 ** \return    none.
 **
 ****************************************************************************************/
-void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
+void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID)
 {
   /* make sure that transmit mailbox 0 is available */
   ASSERT_RT((CANx->TSR&CAN_BIT_TME0) == CAN_BIT_TME0);
-  /* build the message identifier */
-  CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
 
   blt_int32u address;
 #if (BOOT_GATE_CAN_ENABLE > 0)
@@ -311,7 +314,7 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
 #if (BOOT_GATE_CAN_ENABLE > 0)
     commandSend = BLT_FALSE;
   } else {
-    address = ((blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)deviceID);
+    address = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
     commandSend = BLT_TRUE;
   }
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
@@ -320,20 +323,45 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
   blt_int8u canData[8];
   blt_int8u restLen = len;
   blt_int8u canIdx = 0;
+  blt_int32u ackMsgId;
+  blt_int8u ackMsgLen;
 
   /* send the given package in 8 byte packages */
   while (restLen > 0) {
-
+    /* build the message identifier */
+    CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
     CANx->sTxMailBox[0].TIR |= (address << 21);
-    /* store the message date length code (DLC) */
-    if (restLen > 7) {
-      CANx->sTxMailBox[0].TDTR = 8;
-    } else {
-      CANx->sTxMailBox[0].TDTR = restLen+1;
+
+    /* if this is the first transmission of this packet */
+    if (restLen == len) {
+
+      /* store the message date length code (DLC) */
+      CANx->sTxMailBox[0].TDTR = (restLen > 4) ? 8 : restLen+1+4;
+
+      /* store the device ID */
+      canData[0] = (blt_int8u)(0xFF & (deviceID >> 0));
+      canData[1] = (blt_int8u)(0xFF & (deviceID >> 8));
+      canData[2] = (blt_int8u)(0xFF & (deviceID >> 16));
+      canData[3] = (blt_int8u)(0xFF & (deviceID >> 24));
+
+      /* store the remaining packet length */
+      canData[4] = restLen;
+
+      canIdx = 5;
+    }
+    /* if this is a succeeding transmission of this packet */
+    else {
+
+      /* store the message date length code (DLC) */
+      CANx->sTxMailBox[0].TDTR = (restLen > 7) ? 8 : restLen+1;
+
+      /* store the remaining packet length */
+      canData[0] = restLen;
+
+      canIdx = 1;
     }
-    /* Load max 8 bytes into message data bytes */
-    canData[0] = restLen;
-    canIdx = 1;
+
+    /* store the packet payload */
     while (restLen > 0 && canIdx < 8) {
       canData[canIdx] = data[len-restLen];
       canIdx++;
@@ -344,6 +372,7 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
       canData[canIdx] = 0;
       canIdx++;
     }
+
     /* store the message data bytes */
     CANx->sTxMailBox[0].TDLR = (((blt_int32u)canData[3] << 24) | \
                                 ((blt_int32u)canData[2] << 16) | \
@@ -353,6 +382,7 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
                                 ((blt_int32u)canData[6] << 16) | \
                                 ((blt_int32u)canData[5] <<  8) | \
                                 ((blt_int32u)canData[4]));
+
     /* request the start of message transmission */
     CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
     /* wait for transmit completion */
@@ -362,6 +392,52 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
       CopService();
     }
 
+    /* wait for the acknowledgement transmission */
+    while ((CANx->RF0R&(blt_int32u)0x00000003) == 0) {
+      /* keep the watchdog happy */
+      CopService();
+    }
+
+    /* read out the message identifier, length and payload */
+    ackMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
+    ackMsgLen = (blt_int8u)0x0F & CANx->sFIFOMailBox[0].RDTR;
+    canData[0] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDLR;
+    canData[1] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 8);
+    canData[2] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 16);
+    canData[3] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 24);
+    canData[4] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDHR;
+    canData[5] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 8);
+    canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
+    canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
+
+#if (CAN_DEBUG > 0)
+    /* verification:
+     * - ID must be "address & BOOT_COM_CAN_MSG_ACK"
+     * - length must be 1
+     * - canData[0] must b equal to restLen
+     */
+    if (ackMsgId != (address | (blt_int32u)BOOT_COM_CAN_MSG_ACK) ||
+        ackMsgLen != 1 ||
+        canData[0] != restLen) {
+      /* some error occurred */
+      blinkSOS(1);
+      msleep(500);
+      visualizeData((blt_int8u*)&ackMsgId, 2, 1);
+      msleep(500);
+      visualizeByte(ackMsgLen, 1);
+      msleep(500);
+      visualizeByte(canData[0], 1);
+      msleep(500);
+      visualizeByte(restLen, 1);
+      blinkSOSinf();
+    }
+#endif /* CAN_DEBUG > 0 */
+
+    /* release FIFO0 */
+    CANx->RF0R |= CAN_BIT_RFOM0;
+
+    /* modify address so that receivers can filter */
+    address |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
   }
 } /*** end of CanTransmitPacket ***/
 
@@ -385,30 +461,33 @@ blt_int8u CanReceivePacket(blt_int8u *data)
   blt_int8u canData[8];
   blt_int8u restLen;
   blt_int8u canLength;
+  blt_int8u idx;
 
-  /* check if a new message was received */
-  if ((CANx->RF0R&(blt_int32u)0x00000003) > 0)
-  {
-    /* read out the message identifier */
-    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
-    /* is this the packet identifier */
-
-    blt_int32u compID;
+  blt_int32u compID;
 #if (BOOT_GATE_CAN_ENABLE > 0)
-    if (commandSend == BLT_TRUE) {
-      compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
-    } else {
+  if (commandSend == BLT_TRUE) {
+    compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
+  } else {
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
-      compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)BOOT_COM_DEVICE_ID;
+    compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
 #if (BOOT_GATE_CAN_ENABLE > 0)
-    }
+  }
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
 
+  /* check if a new message was received  or is more to come */
+  while ((CANx->RF0R&(blt_int32u)0x00000003) > 0 || receivedLen < toReceive)
+  {
+    /* wait for a transmission if required */
+    while (receivedLen < toReceive && (CANx->RF0R&(blt_int32u)0x00000003) == 0) {
+      /* keep the watchdog happy */
+      CopService();
+    }
+
+    /* read out the message identifier */
+    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
+    /* is this the packet identifier */
     if (rxMsgId == compID)
     {
-#if (BOOT_GATE_CAN_ENABLE > 0)
-      commandSend = BLT_FALSE;
-#endif /* BOOT_GATE_CAN_ENABLE > 0 */
       result = BLT_TRUE;
 
       /* save length */
@@ -423,39 +502,143 @@ blt_int8u CanReceivePacket(blt_int8u *data)
       canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
       canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
 
-      /* Store rest length of package and check if possible */
+#if (CAN_DEBUG > 0)
+      if ((receivedLen == 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) != 0) ||
+          (receivedLen > 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) == 0)) {
+        blinkSOS(4);
+        msleep(500);
+        visualizeByte(toReceive, 1);
+        msleep(500);
+        visualizeByte(receivedLen, 1);
+        msleep(500);
+        visualizeData((blt_int8u*)&rxMsgId, 2, 1);
+        msleep(500);
+        blinkSOSinf();
+      }
+#endif /* CAN_DEBUG > 0 */
+
+      /* if this is the first transmission of this packet */
       if (receivedLen == 0) {
-        toReceive = canData[0];
-        lastLen = canData[0];
-      } else {
+        /* abort if the message was meant for someone else */
+        blt_int32u deviceID = (((blt_int32u)canData[3]) << 24) | \
+                              (((blt_int32u)canData[2]) << 16) | \
+                              (((blt_int32u)canData[1]) <<  8) | \
+                              (((blt_int32u)canData[0]));
+#if (BOOT_GATE_ENABLE > 0)
+        if ((commandSend == BLT_TRUE && deviceID == 0) ||
+            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) || deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID)) {
+#else
+        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID ||
+            deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID) {
+#endif
+          /* store length of the packet */
+          toReceive = canData[4];
+          lastLen = canData[4];
+          idx = 5;
+
+          /* modify the listening address for filtering of subsequent transmissions */
+          compID |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
+        } else {
+          /* release FIFO0 */
+          CANx->RF0R |= CAN_BIT_RFOM0;
+          break;
+        }
+      }
+      /* if this is a subsequent transmission of a packet */
+      else {
+        /* store rest length and check if possible */
         restLen = canData[0];
-        if (lastLen-restLen != 7) {
-          // package has been lost - but nothing happens
+#if (CAN_DEBUG > 0)
+        if (restLen != toReceive-receivedLen ||
+            canLength > restLen+1 ||
+            lastLen-restLen != ((lastLen==toReceive) ? 3 : 7)) {
+          /* transmission has been lost */
+          blinkSOS(2);
+          msleep(500);
+          visualizeData((blt_int8u*)&rxMsgId, 4, 1);
+          msleep(500);
+          visualizeByte(toReceive, 1);
+          msleep(500);
+          visualizeByte(receivedLen, 1);
+          msleep(500);
+          visualizeByte(lastLen, 1);
+          msleep(500);
+          visualizeByte(restLen, 1);
+          msleep(500);
+          visualizeByte(canLength, 1);
+          msleep(500);
+          visualizeData(readData, receivedLen, 1);
+          blinkSOSinf();
         }
+#endif /* CAN_DEBUG > 0 */
         lastLen = restLen;
+        idx = 1;
       }
 
-      /* store data in data package */
-      blt_int8u idx;
-      for (idx=1; idx < canLength; idx++) {
+      /* store the payload */
+      for (; idx < canLength; idx++) {
         readData[receivedLen] = canData[idx];
         receivedLen++;
       }
 
+      /* release FIFO0 */
+      CANx->RF0R |= CAN_BIT_RFOM0;
+
+      /* send acknowledgement */
+      CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
+      CANx->sTxMailBox[0].TIR |= ((rxMsgId | (blt_int32u)BOOT_COM_CAN_MSG_ACK) << 21);
+      CANx->sTxMailBox[0].TDTR = 1;
+      CANx->sTxMailBox[0].TDLR = (((blt_int32u)0 << 24) | \
+                                  ((blt_int32u)0 << 16) | \
+                                  ((blt_int32u)0 <<  8) | \
+                                  ((blt_int32u)(toReceive-receivedLen)));
+      CANx->sTxMailBox[0].TDHR = (((blt_int32u)0 << 24) | \
+                                  ((blt_int32u)0 << 16) | \
+                                  ((blt_int32u)0 <<  8) | \
+                                  ((blt_int32u)0));
+
+      /* request the start of message transmission */
+      CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
+      /* wait for transmit completion */
+      while ((CANx->TSR&CAN_BIT_TME0) == 0)
+      {
+        /* keep the watchdog happy */
+        CopService();
+      }
+
       /* check if full package has been received */
-      if (receivedLen >= toReceive) {
-        receivedLen = 0;
+      if (receivedLen == toReceive) {
+#if (BOOT_GATE_CAN_ENABLE > 0)
+        commandSend = BLT_FALSE;
+#endif /* BOOT_GATE_CAN_ENABLE > 0 */
         for (idx = 0; idx < toReceive; idx++) {
           data[idx] = readData[idx];
         }
         length = toReceive;
+        /* reset static variables */
+        receivedLen = 0;
+        toReceive = 0;
+        break;
       } else {
+#if (CAN_DEBUG > 0)
+        if (receivedLen > toReceive) {
+          /* something strange happened */
+          blinkSOS(3);
+          msleep(500);
+          visualizeByte(toReceive, 1);
+          msleep(500);
+          visualizeByte(receivedLen, 1);
+          blinkSOSinf();
+        }
+#endif /* CAN_DEBUG > 0 */
         length = 0;
       }
+    } else {
+      /* release FIFO0 */
+      CANx->RF0R |= CAN_BIT_RFOM0;
     }
-    /* release FIFO0 */
-    CANx->RF0R |= CAN_BIT_RFOM0;
   }
+
   return length;
 } /*** end of CanReceivePacket ***/
 #endif /* BOOT_COM_CAN_ENABLE > 0  || BOOT_GATE_CAN_ENABLE > 0 */
diff --git a/Target/Source/ARMCM3_STM32/can.h b/Target/Source/ARMCM3_STM32/can.h
index e14cffd..4af0adb 100644
--- a/Target/Source/ARMCM3_STM32/can.h
+++ b/Target/Source/ARMCM3_STM32/can.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef CAN_H
@@ -38,7 +38,7 @@
 * Function prototypes
 ****************************************************************************************/
 void      CanInit(void);
-void      CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID);
+void      CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID);
 blt_int8u CanReceivePacket(blt_int8u *data);
 #endif /* BOOT_COM_CAN_ENABLE > 0  || BOOT_GATE_CAN_ENABLE > 0 */
 
diff --git a/Target/Source/ARMCM4_STM32/can.c b/Target/Source/ARMCM4_STM32/can.c
index 1b9ea70..901603f 100644
--- a/Target/Source/ARMCM4_STM32/can.c
+++ b/Target/Source/ARMCM4_STM32/can.c
@@ -23,20 +23,25 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 
+#define CAN_DEBUG       (0)
 
 /****************************************************************************************
 * Include files
 ****************************************************************************************/
 #include "boot.h"                                /* bootloader generic header          */
 
+#if (CAN_DEBUG > 0)
+#include <helper.h>
+#endif
+
 
 #if (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
 /****************************************************************************************
@@ -58,7 +63,7 @@ typedef struct
   volatile blt_int32u RDTR;
   volatile blt_int32u RDLR;
   volatile blt_int32u RDHR;
-} tCanRxFIFOMailBox; 
+} tCanRxFIFOMailBox;
 
 /** \brief CAN filter register layout. */
 typedef struct
@@ -92,7 +97,7 @@ typedef struct
   volatile blt_int32u FA1R;
   blt_int32u          RESERVED5[8];
   tCanFilter          sFilterRegister[28];
-} tCanRegs;                                           
+} tCanRegs;
 
 
 /****************************************************************************************
@@ -153,9 +158,9 @@ typedef struct t_can_bus_timing
 * Local constant declarations
 ****************************************************************************************/
 /** \brief CAN bittiming table for dynamically calculating the bittiming settings.
- *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25 
- *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC 
- *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) * 
+ *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25
+ *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC
+ *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) *
  *           100%. This array contains possible and valid time quanta configurations with
  *           a sample point between 68..78%.
  */
@@ -184,17 +189,17 @@ static const tCanBusTiming canTiming[] =
 
 int counter = 0;
 /************************************************************************************//**
-** \brief     Search algorithm to match the desired baudrate to a possible bus 
+** \brief     Search algorithm to match the desired baudrate to a possible bus
 **            timing configuration.
 ** \param     baud The desired baudrate in kbps. Valid values are 10..1000.
 ** \param     prescaler Pointer to where the value for the prescaler will be stored.
 ** \param     tseg1 Pointer to where the value for TSEG2 will be stored.
 ** \param     tseg2 Pointer to where the value for TSEG2 will be stored.
-** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE 
+** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE
 **            otherwise.
 **
 ****************************************************************************************/
-static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler, 
+static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler,
                                   blt_int8u *tseg1, blt_int8u *tseg2)
 {
   blt_int8u  cnt;
@@ -238,10 +243,10 @@ void CanInit(void)
   commandSend = BLT_FALSE;
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
 
-  /* the current implementation supports CAN1 and 2. throw an assertion error in case a 
-   * different CAN channel is configured.  
+  /* the current implementation supports CAN1 and 2. throw an assertion error in case a
+   * different CAN channel is configured.
    */
-  ASSERT_CT((BOOT_COM_CAN_CHANNEL_INDEX == 0 || BOOT_COM_CAN_CHANNEL_INDEX == 1)); 
+  ASSERT_CT((BOOT_COM_CAN_CHANNEL_INDEX == 0 || BOOT_COM_CAN_CHANNEL_INDEX == 1));
 
   /* obtain bittiming configuration information */
   result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2);
@@ -297,8 +302,8 @@ void CanInit(void)
   /* 32-bit scale for the filter */
   CAN1->FS1R |= CAN_BIT_FILTER0;
   /* open up the acceptance filter to receive all messages */
-  CAN1->sFilterRegister[0].FR1 = 0; 
-  CAN1->sFilterRegister[0].FR2 = 0; 
+  CAN1->sFilterRegister[0].FR1 = 0;
+  CAN1->sFilterRegister[0].FR2 = 0;
   /* select id/mask mode for the filter */
   CAN1->FM1R &= ~CAN_BIT_FILTER0;
   /* FIFO 0 assignation for the filter */
@@ -315,8 +320,8 @@ void CanInit(void)
   /* 32-bit scale for the filter */
   CAN1->FS1R |= CAN_BIT_FILTER14;
   /* open up the acceptance filter to receive all messages */
-  CAN1->sFilterRegister[14].FR1 = 0; 
-  CAN1->sFilterRegister[14].FR2 = 0; 
+  CAN1->sFilterRegister[14].FR1 = 0;
+  CAN1->sFilterRegister[14].FR2 = 0;
   /* select id/mask mode for the filter */
   CAN1->FM1R &= ~CAN_BIT_FILTER14;
   /* FIFO 0 assignation for the filter */
@@ -325,7 +330,7 @@ void CanInit(void)
   CAN1->FA1R |= CAN_BIT_FILTER14;
   /* leave initialisation mode for the acceptance filter */
   CAN1->FMR &= ~CAN_BIT_FINIT;
-#endif  
+#endif
 } /*** end of CanInit ***/
 
 
@@ -336,12 +341,10 @@ void CanInit(void)
 ** \return    none.
 **
 ****************************************************************************************/
-void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
+void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID)
 {
   /* make sure that transmit mailbox 0 is available */
   ASSERT_RT((CANx->TSR&CAN_BIT_TME0) == CAN_BIT_TME0);
-  /* store the 11-bit message identifier */
-  CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
 
   blt_int32u address;
 #if (BOOT_GATE_CAN_ENABLE > 0)
@@ -351,7 +354,7 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
 #if (BOOT_GATE_CAN_ENABLE > 0)
     commandSend = BLT_FALSE;
   } else {
-    address = ((blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)deviceID);
+    address = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
     commandSend = BLT_TRUE;
   }
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
@@ -360,20 +363,45 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
   blt_int8u canData[8];
   blt_int8u restLen = len;
   blt_int8u canIdx = 0;
+  blt_int32u ackMsgId;
+  blt_int8u ackMsgLen;
 
   /* send the given package in 8 byte packages */
   while (restLen > 0) {
-
+    /* build the message identifier */
+    CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
     CANx->sTxMailBox[0].TIR |= (address << 21);
-    /* store the message date length code (DLC) */
-    if (restLen > 7) {
-      CANx->sTxMailBox[0].TDTR = 8;
-    } else {
-      CANx->sTxMailBox[0].TDTR = restLen+1;
+
+    /* if this is the first transmission of this packet */
+    if (restLen == len) {
+
+      /* store the message date length code (DLC) */
+      CANx->sTxMailBox[0].TDTR = (restLen > 4) ? 8 : restLen+1+4;
+
+      /* store the device ID */
+      canData[0] = (blt_int8u)(0xFF & (deviceID >> 0));
+      canData[1] = (blt_int8u)(0xFF & (deviceID >> 8));
+      canData[2] = (blt_int8u)(0xFF & (deviceID >> 16));
+      canData[3] = (blt_int8u)(0xFF & (deviceID >> 24));
+
+      /* store the remaining packet length */
+      canData[4] = restLen;
+
+      canIdx = 5;
+    }
+    /* if this is a succeeding transmission of this packet */
+    else {
+
+      /* store the message date length code (DLC) */
+      CANx->sTxMailBox[0].TDTR = (restLen > 7) ? 8 : restLen+1;
+
+      /* store the remaining packet length */
+      canData[0] = restLen;
+
+      canIdx = 1;
     }
-    /* Load max 8 bytes into message data bytes */
-    canData[0] = restLen;
-    canIdx = 1;
+
+    /* store the packet payload */
     while (restLen > 0 && canIdx < 8) {
       canData[canIdx] = data[len-restLen];
       canIdx++;
@@ -384,6 +412,7 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
       canData[canIdx] = 0;
       canIdx++;
     }
+
     /* store the message data bytes */
     CANx->sTxMailBox[0].TDLR = (((blt_int32u)canData[3] << 24) | \
                                 ((blt_int32u)canData[2] << 16) | \
@@ -393,6 +422,7 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
                                 ((blt_int32u)canData[6] << 16) | \
                                 ((blt_int32u)canData[5] <<  8) | \
                                 ((blt_int32u)canData[4]));
+
     /* request the start of message transmission */
     CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
     /* wait for transmit completion */
@@ -402,6 +432,52 @@ void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
       CopService();
     }
 
+    /* wait for the acknowledgement transmission */
+    while ((CANx->RF0R&(blt_int32u)0x00000003) == 0) {
+      /* keep the watchdog happy */
+      CopService();
+    }
+
+    /* read out the message identifier, length and payload */
+    ackMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
+    ackMsgLen = (blt_int8u)0x0F & CANx->sFIFOMailBox[0].RDTR;
+    canData[0] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDLR;
+    canData[1] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 8);
+    canData[2] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 16);
+    canData[3] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 24);
+    canData[4] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDHR;
+    canData[5] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 8);
+    canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
+    canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
+
+#if (CAN_DEBUG > 0)
+    /* verification:
+     * - ID must be "address & BOOT_COM_CAN_MSG_ACK"
+     * - length must be 1
+     * - canData[0] must b equal to restLen
+     */
+    if (ackMsgId != (address | (blt_int32u)BOOT_COM_CAN_MSG_ACK) ||
+        ackMsgLen != 1 ||
+        canData[0] != restLen) {
+      /* some error occurred */
+      blinkSOS(1);
+      msleep(500);
+      visualizeData((blt_int8u*)&ackMsgId, 2, 1);
+      msleep(500);
+      visualizeByte(ackMsgLen, 1);
+      msleep(500);
+      visualizeByte(canData[0], 1);
+      msleep(500);
+      visualizeByte(restLen, 1);
+      blinkSOSinf();
+    }
+#endif /* CAN_DEBUG > 0 */
+
+    /* release FIFO0 */
+    CANx->RF0R |= CAN_BIT_RFOM0;
+
+    /* modify address so that receivers can filter */
+    address |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
   }
 } /*** end of CanTransmitSinglePacket ***/
 
@@ -461,30 +537,33 @@ blt_int8u CanReceivePacket(blt_int8u *data)
   blt_int8u canData[8];
   blt_int8u restLen;
   blt_int8u canLength;
+  blt_int8u idx;
 
-  /* check if a new message was received */
-  if ((CANx->RF0R&(blt_int32u)0x00000003) > 0)
-  {
-    /* read out the message identifier */
-    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
-    /* is this the packet identifier */
-
-    blt_int32u compID;
+  blt_int32u compID;
 #if (BOOT_GATE_CAN_ENABLE > 0)
-    if (commandSend == BLT_TRUE) {
-      compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
-    } else {
+  if (commandSend == BLT_TRUE) {
+    compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
+  } else {
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
-      compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)BOOT_COM_DEVICE_ID;
+    compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
 #if (BOOT_GATE_CAN_ENABLE > 0)
-    }
+  }
 #endif /* BOOT_GATE_CAN_ENABLE > 0 */
 
+  /* check if a new message was received  or is more to come */
+  while ((CANx->RF0R&(blt_int32u)0x00000003) > 0 || receivedLen < toReceive)
+  {
+    /* wait for a transmission if required */
+    while (receivedLen < toReceive && (CANx->RF0R&(blt_int32u)0x00000003) == 0) {
+      /* keep the watchdog happy */
+      CopService();
+    }
+
+    /* read out the message identifier */
+    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
+    /* is this the packet identifier */
     if (rxMsgId == compID)
     {
-#if (BOOT_GATE_CAN_ENABLE > 0)
-      commandSend = BLT_FALSE;
-#endif /* BOOT_GATE_CAN_ENABLE > 0 */
       result = BLT_TRUE;
 
       /* save length */
@@ -499,39 +578,142 @@ blt_int8u CanReceivePacket(blt_int8u *data)
       canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
       canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
 
-      /* Store rest length of package and check if possible */
+#if (CAN_DEBUG > 0)
+      if ((receivedLen == 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) != 0) ||
+          (receivedLen > 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) == 0)) {
+        blinkSOS(4);
+        msleep(500);
+        visualizeByte(toReceive, 1);
+        msleep(500);
+        visualizeByte(receivedLen, 1);
+        msleep(500);
+        visualizeData((blt_int8u*)&rxMsgId, 2, 1);
+        msleep(500);
+        blinkSOSinf();
+      }
+#endif /* CAN_DEBUG > 0 */
+
+      /* if this is the first transmission of this packet */
       if (receivedLen == 0) {
-        toReceive = canData[0];
-        lastLen = canData[0];
-      } else {
+        /* abort if the message was meant for someone else */
+        blt_int32u deviceID = (((blt_int32u)canData[3]) << 24) | \
+                              (((blt_int32u)canData[2]) << 16) | \
+                              (((blt_int32u)canData[1]) <<  8) | \
+                              (((blt_int32u)canData[0]));
+#if (BOOT_GATE_ENABLE > 0)
+        if ((commandSend == BLT_TRUE && deviceID == 0) ||
+            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) || deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID)) {
+#else
+        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) {
+#endif
+          /* store length of the packet */
+          toReceive = canData[4];
+          lastLen = canData[4];
+          idx = 5;
+
+          /* modify the listening address for filtering of subsequent transmissions */
+          compID |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
+        } else {
+          /* release FIFO0 */
+          CANx->RF0R |= CAN_BIT_RFOM0;
+          break;
+        }
+      }
+      /* if this is a subsequent transmission of a packet */
+      else {
+        /* store rest length and check if possible */
         restLen = canData[0];
-        if (lastLen-restLen != 7) {
-          // package has been lost - but nothing happens
+#if (CAN_DEBUG > 0)
+        if (restLen != toReceive-receivedLen ||
+            canLength > restLen+1 ||
+            lastLen-restLen != ((lastLen==toReceive) ? 3 : 7)) {
+          /* transmission has been lost */
+          blinkSOS(2);
+          msleep(500);
+          visualizeData((blt_int8u*)&rxMsgId, 4, 1);
+          msleep(500);
+          visualizeByte(toReceive, 1);
+          msleep(500);
+          visualizeByte(receivedLen, 1);
+          msleep(500);
+          visualizeByte(lastLen, 1);
+          msleep(500);
+          visualizeByte(restLen, 1);
+          msleep(500);
+          visualizeByte(canLength, 1);
+          msleep(500);
+          visualizeData(readData, receivedLen, 1);
+          blinkSOSinf();
         }
+#endif /* CAN_DEBUG > 0 */
         lastLen = restLen;
+        idx = 1;
       }
 
-      /* store data in data package */
-      blt_int8u idx;
-      for (idx=1; idx < canLength; idx++) {
+      /* store the payload */
+      for (; idx < canLength; idx++) {
         readData[receivedLen] = canData[idx];
         receivedLen++;
       }
 
+      /* release FIFO0 */
+      CANx->RF0R |= CAN_BIT_RFOM0;
+
+      /* send acknowledgement */
+      CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
+      CANx->sTxMailBox[0].TIR |= ((rxMsgId | (blt_int32u)BOOT_COM_CAN_MSG_ACK) << 21);
+      CANx->sTxMailBox[0].TDTR = 1;
+      CANx->sTxMailBox[0].TDLR = (((blt_int32u)0 << 24) | \
+                                  ((blt_int32u)0 << 16) | \
+                                  ((blt_int32u)0 <<  8) | \
+                                  ((blt_int32u)(toReceive-receivedLen)));
+      CANx->sTxMailBox[0].TDHR = (((blt_int32u)0 << 24) | \
+                                  ((blt_int32u)0 << 16) | \
+                                  ((blt_int32u)0 <<  8) | \
+                                  ((blt_int32u)0));
+
+      /* request the start of message transmission */
+      CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
+      /* wait for transmit completion */
+      while ((CANx->TSR&CAN_BIT_TME0) == 0)
+      {
+        /* keep the watchdog happy */
+        CopService();
+      }
+
       /* check if full package has been received */
-      if (receivedLen >= toReceive) {
-        receivedLen = 0;
+      if (receivedLen == toReceive) {
+#if (BOOT_GATE_CAN_ENABLE > 0)
+        commandSend = BLT_FALSE;
+#endif /* BOOT_GATE_CAN_ENABLE > 0 */
         for (idx = 0; idx < toReceive; idx++) {
           data[idx] = readData[idx];
         }
         length = toReceive;
+        /* reset static variables */
+        receivedLen = 0;
+        toReceive = 0;
+        break;
       } else {
+#if (CAN_DEBUG > 0)
+        if (receivedLen > toReceive) {
+          /* something strange happened */
+          blinkSOS(3);
+          msleep(500);
+          visualizeByte(toReceive, 1);
+          msleep(500);
+          visualizeByte(receivedLen, 1);
+          blinkSOSinf();
+        }
+#endif /* CAN_DEBUG > 0 */
         length = 0;
       }
+    } else {
+      /* release FIFO0 */
+      CANx->RF0R |= CAN_BIT_RFOM0;
     }
-    /* release FIFO0 */
-    CANx->RF0R |= CAN_BIT_RFOM0;
   }
+
   return length;
 } /*** end of CanReceiveSinglePacket ***/
 
@@ -581,7 +763,7 @@ blt_int8u CanReceivePacket(blt_int8u *data)
   } else {
     return 0;
   }
-  
+
 
 } /*** end of CanReceivePacket ***/
 #endif
diff --git a/Target/Source/ARMCM4_STM32/can.h b/Target/Source/ARMCM4_STM32/can.h
index ec960d2..da0a681 100644
--- a/Target/Source/ARMCM4_STM32/can.h
+++ b/Target/Source/ARMCM4_STM32/can.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef CAN_H
@@ -38,7 +38,7 @@
 * Function prototypes
 ****************************************************************************************/
 void     CanInit(void);
-void     CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID);
+void     CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID);
 blt_bool CanReceivePacket(blt_int8u *data);
 #endif /* BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0 */
 
diff --git a/Target/Source/gateway.c b/Target/Source/gateway.c
index 50e8edf..d74308e 100644
--- a/Target/Source/gateway.c
+++ b/Target/Source/gateway.c
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 
@@ -135,7 +135,7 @@ static void InitDebugData(void) {
 
 
 /************************************************************************************//**
-** \brief     Updates the gateway module by checking if new data was received 
+** \brief     Updates the gateway module by checking if new data was received
 **            and submitting the request to process newly received data.
 ** \return    none
 **
@@ -145,7 +145,7 @@ void GateTask(void)
   blt_int16s messageLength;
   /* make xcpCtoReqPacket static for runtime efficiency */
   static unsigned char xcpCtoReqPacket[BOOT_COM_RX_MAX_DATA];
- 
+
 #if (BOOT_GATE_CAN_ENABLE > 0)
   messageLength = (blt_int16s)CanReceivePacket(&xcpCtoReqPacket[0]);
   if (messageLength > 0)
@@ -265,7 +265,7 @@ void GateTransmitPacket(blt_int8u *data, blt_int16u len)
 blt_int16u GateGetActiveInterfaceMaxRxLen(void)
 {
   blt_int16u result;
-  
+
   /* filter on gateway interface identifier */
   switch (gateActiveInterface)
   {
@@ -284,18 +284,18 @@ blt_int16u GateGetActiveInterfaceMaxRxLen(void)
     case GATE_IF_NET:
       result = BOOT_COM_NET_RX_MAX_DATA;
       break;
-      
+
     default:
       result = BOOT_COM_RX_MAX_DATA;
       break;
   }
-  
+
   return result;
 } /*** end of GateGetActiveInterfaceMaxRxLen ***/
 
 
 /************************************************************************************//**
-** \brief     Obtains the maximum number of bytes that can be transmitted on the 
+** \brief     Obtains the maximum number of bytes that can be transmitted on the
 **            specified gateway interface.
 ** \return    Maximum number of bytes that can be received.
 **
@@ -303,7 +303,7 @@ blt_int16u GateGetActiveInterfaceMaxRxLen(void)
 blt_int16u GateGetActiveInterfaceMaxTxLen(void)
 {
   blt_int16u result;
-  
+
   /* filter on gateway interface identifier */
   switch (gateActiveInterface)
   {
@@ -322,12 +322,12 @@ blt_int16u GateGetActiveInterfaceMaxTxLen(void)
     case GATE_IF_NET:
       result = BOOT_COM_NET_TX_MAX_DATA;
       break;
-      
+
     default:
       result = BOOT_COM_TX_MAX_DATA;
       break;
   }
-  
+
   return result;
 } /*** end of GateGetActiveInterfaceMaxTxLen ***/
 
@@ -358,7 +358,7 @@ blt_bool GateIsConnected(void)
 ** \return    none.
 **
 ****************************************************************************************/
-void GateTransmitPacketDirect(blt_int8u *data, blt_int8u len, blt_int8u deviceID) {
+void GateTransmitPacketDirect(blt_int8u *data, blt_int8u len, blt_int32u deviceID) {
   forwarded = BLT_TRUE;
   CanTransmitPacket(data, len, deviceID);
   XcpPacketTransmitted();
diff --git a/Target/Source/gateway.h b/Target/Source/gateway.h
index 9a7e07b..ec183d8 100644
--- a/Target/Source/gateway.h
+++ b/Target/Source/gateway.h
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 #ifndef GATE_H
@@ -138,7 +138,7 @@ blt_int16u      GateGetActiveInterfaceMaxRxLen(void);
 blt_int16u      GateGetActiveInterfaceMaxTxLen(void);
 void            GateTransmitPacket(blt_int8u *data, blt_int16u len);
 #if (BOOT_GATE_CAN_ENABLE > 0)
-void            GateTransmitPacketDirect(blt_int8u *data, blt_int8u len, blt_int8u deviceID);
+void            GateTransmitPacketDirect(blt_int8u *data, blt_int8u len, blt_int32u deviceID);
 #endif
 blt_bool        GateIsConnected(void);
 #if (BOOT_DEBUGGING_UART2_ENABLE > 0)
diff --git a/Target/Source/xcp.c b/Target/Source/xcp.c
index 9d5e714..a6190d9 100644
--- a/Target/Source/xcp.c
+++ b/Target/Source/xcp.c
@@ -23,11 +23,11 @@
 * You should have received a copy of the GNU General Public License along with OpenBLT.
 * If not, see <http://www.gnu.org/licenses/>.
 *
-* A special exception to the GPL is included to allow you to distribute a combined work 
-* that includes OpenBLT without being obliged to provide the source code for any 
+* A special exception to the GPL is included to allow you to distribute a combined work
+* that includes OpenBLT without being obliged to provide the source code for any
 * proprietary components. The exception text is included at the bottom of the license
 * file <license.html>.
-* 
+*
 * \endinternal
 ****************************************************************************************/
 
@@ -36,6 +36,7 @@
 ****************************************************************************************/
 #include "boot.h"                                /* bootloader generic header          */
 
+#include <helper.h>
 
 /****************************************************************************************
 * Defines
@@ -49,7 +50,7 @@
 /* XCP packet identifiers */
 /** \brief Command response packet identifier. */
 #define XCP_PID_RES                 (0xff)
-/** \brief Error packet identifier. */            
+/** \brief Error packet identifier. */
 #define XCP_PID_ERR                 (0xfe)
 
 /* XCP error codes */
@@ -123,7 +124,7 @@ typedef struct
 {
   blt_int8u  connected;                             /**< connection established                      */
 #if (BOOT_GATE_ENABLE > 0)
-  blt_int8u  other_connection;                      /**< connection to other device established      */
+  blt_int32u  other_connection;                      /**< connection to other device established      */
 #endif
 #if (BOOTLOADER_OF_MAIN_DEVICE > 0)
   blt_bool   wasMainConnection;                     /**< connection to serialboot (0x00) established */
@@ -149,7 +150,7 @@ static void      XcpTransmitPacket(blt_int8u *data, blt_int16s len);
 #endif /* BOOT_GATE_ENABLE > 0 */
 
 /* application specific functions */
-static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length, 
+static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length,
                                     blt_int32u *checksum);
 
 #if (XCP_SEED_KEY_PROTECTION_EN == 1)
@@ -217,7 +218,7 @@ extern blt_int8u XcpVerifyKeyHook(blt_int8u resource, blt_int8u *key, blt_int8u
 * External functions
 ****************************************************************************************/
 #if (BOOT_COM_ENABLE == 0)
-/* in case no internally supported communication interface is used, a custom 
+/* in case no internally supported communication interface is used, a custom
  * communication module can be added. In order to use the XCP protocol in the custom
  * communication module, this hook function needs to be implemented. In the XCP protocol
  * is not needed, then simply remove the xcp.c source from the project.
@@ -296,7 +297,7 @@ blt_bool XcpWasConnectedToMain(void)
 
 
 /************************************************************************************//**
-** \brief     Informs the core that a pending packet transmission was completed by 
+** \brief     Informs the core that a pending packet transmission was completed by
 **            the transport layer.
 ** \return    none
 **
@@ -454,7 +455,7 @@ void XcpPacketReceived(blt_int8u *data, blt_int16s dataLength)
 ****************************************************************************************/
 void XcpPacketReceivedForwarding(blt_int8u *data, blt_int16s dataLength) {
   /* save id of connected device */
-  blt_int8u connectionTo = xcpInfo.other_connection;
+  blt_int32u connectionTo = xcpInfo.other_connection;
 
   /* proof commands */
   switch (data[0]) {
@@ -464,6 +465,7 @@ void XcpPacketReceivedForwarding(blt_int8u *data, blt_int16s dataLength) {
     case XCP_CMD_DISCONNECT:
       xcpInfo.other_connection = 0;
       xcpInfo.connected = 0;
+      setLed(0);
       break;
     /* if there is a reset command, it has to be handled like a disconnection
      * (above) because other devices shouldn't get the ability to reset
@@ -472,6 +474,7 @@ void XcpPacketReceivedForwarding(blt_int8u *data, blt_int16s dataLength) {
     case XCP_CMD_PROGRAM_RESET:
       xcpInfo.other_connection = 0;
       xcpInfo.connected = 0;
+      setLed(0);
       data[0] = XCP_CMD_DISCONNECT;
       break;
     default:
@@ -535,7 +538,7 @@ static void XcpTransmitPacket(blt_int8u *data, blt_int16s len)
 #else
   ComTransmitPacket(data, len);
 #endif
-  
+
 } /*** end of XcpTransmitPacket ***/
 
 
@@ -568,8 +571,8 @@ static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length,
 
 #if (XCP_SEED_KEY_PROTECTION_EN == 1)
 /************************************************************************************//**
-** \brief     Provides a seed to the XCP master that will be used for the key 
-**            generation when the master attempts to unlock the specified resource. 
+** \brief     Provides a seed to the XCP master that will be used for the key
+**            generation when the master attempts to unlock the specified resource.
 **            Called by the GET_SEED command.
 ** \param     resource  Resource that the seed if requested for (XCP_RES_XXX).
 ** \param     seed      Pointer to byte buffer wher the seed will be stored.
@@ -584,8 +587,8 @@ static blt_int8u XcpGetSeed(blt_int8u resource, blt_int8u *seed)
 
 
 /************************************************************************************//**
-** \brief     Called by the UNLOCK command and checks if the key to unlock the 
-**            specified resource was correct. If so, then the resource protection 
+** \brief     Called by the UNLOCK command and checks if the key to unlock the
+**            specified resource was correct. If so, then the resource protection
 **            will be removed.
 ** \param     resource  resource to unlock (XCP_RES_XXX).
 ** \param     key       pointer to the byte buffer holding the key.
@@ -671,8 +674,8 @@ static void XcpCmdConnect(blt_int8u *data, blt_int16s dataLength)
     XcpSetCtoError(XCP_ERR_CMD_BUSY);
     return;
   }
-  #endif  
-  
+  #endif
+
 //  #if (XCP_CONNECT_MODE_HOOK_EN == 1)
 //  /* pass on the mode to a application specific hook function. This function can determine
 //   * is the mode is supported or not. A return value of BLT_FALSE causes the CONNECT command
@@ -690,16 +693,38 @@ static void XcpCmdConnect(blt_int8u *data, blt_int16s dataLength)
   /* enable resource protection */
   XcpProtectResources();
 
+  /* extract the device ID.
+   * NOTE: For legacy support the following code depends on the data length.
+   *       If two bytes were received the system switches to legacy mode.
+   *       In legacy mode, the device ID was only one byte.
+   */
+  blt_int32u deviceID;
+  if (dataLength == 2) {
+    deviceID = ((blt_int32u)0 << 24) | \
+               ((blt_int32u)0 << 16) | \
+               ((blt_int32u)0 <<  8) | \
+               ((blt_int32u)data[1]);
+  } else if (dataLength == 5) {
+    deviceID = ((blt_int32u)data[4] << 24) | \
+               ((blt_int32u)data[3] << 16) | \
+               ((blt_int32u)data[2] <<  8) | \
+               ((blt_int32u)data[1]);
+  } else {
+    blinkSOSinf();
+  }
   /* indicate that the connection is established */
 #if (BOOT_GATE_ENABLE > 0)
-  if (data[1] == 0x00 || data[1] == BOOT_COM_DEVICE_ID) {
+  if (deviceID == 0 ||
+      deviceID == (blt_int32u)BOOT_COM_DEVICE_ID ||
+      deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID) {
 #endif
     xcpInfo.connected = 1;
+    setLed(1);
 #if (BOOT_GATE_ENABLE > 0)
     xcpInfo.other_connection = 0;
 #endif
 #if (BOOTLOADER_OF_MAIN_DEVICE > 0)
-    if (data[1] == 0x00) {
+    if (deviceID == 0x00) {
       xcpInfo.wasMainConnection = BLT_TRUE;
     }
 #endif
@@ -757,7 +782,8 @@ static void XcpCmdConnect(blt_int8u *data, blt_int16s dataLength)
 
 #if (BOOT_GATE_ENABLE > 0)
   } else {
-    xcpInfo.other_connection = data[1];
+    xcpInfo.other_connection = deviceID;
+    setLed(1);
     xcpInfo.connected = 0;
     XcpPacketReceivedForwarding(data, dataLength);
     xcpInfo.ctoLen = 0;
@@ -768,7 +794,7 @@ static void XcpCmdConnect(blt_int8u *data, blt_int16s dataLength)
   }
 #endif
 
-  
+
 } /*** end of XcpCmdConnect ***/
 
 
@@ -789,6 +815,7 @@ static void XcpCmdDisconnect(blt_int8u *data)
 #if (BOOT_GATE_ENABLE > 0)
   xcpInfo.other_connection = 0;
 #endif
+  setLed(0);
 
   /* enable resource protection */
   XcpProtectResources();
@@ -1456,6 +1483,7 @@ static void XcpCmdProgramReset(blt_int8u *data)
 #if (BOOT_GATE_ENABLE > 0)
   xcpInfo.other_connection = 0;
 #endif
+  setLed(0);
 
 #if (XCP_SEED_KEY_PROTECTION_EN == 1)
   /* check if PGM resource is unlocked */
