diff --git a/Host/SerialBoot.exe b/Host/SerialBoot.exe
new file mode 100644
index 00000000..013dd247
Binary files /dev/null and b/Host/SerialBoot.exe differ
diff --git a/Host/Source/SerialBoot/CMakeLists.txt b/Host/Source/SerialBoot/CMakeLists.txt
new file mode 100644
index 00000000..85fc0554
--- /dev/null
+++ b/Host/Source/SerialBoot/CMakeLists.txt
@@ -0,0 +1,70 @@
+#****************************************************************************************
+# \file CMakeLists.txt
+# \brief CMake descriptor file for SerialBoot command line demonstration program.
+# \ingroup SerialBoot
+# \internal
+#----------------------------------------------------------------------------------------
+# C O P Y R I G H T
+#----------------------------------------------------------------------------------------
+# Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+#
+#----------------------------------------------------------------------------------------
+# L I C E N S E
+#----------------------------------------------------------------------------------------
+# This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with OpenBLT.
+# If not, see .
+#
+# 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 .
+#
+# \endinternal
+#****************************************************************************************
+
+# Specify the version being used aswell as the language
+cmake_minimum_required(VERSION 2.8)
+
+# Specify the project name
+project(SerialBoot)
+
+# Set the port directory, which is platform specific
+IF(WIN32)
+ set(PROJECT_PORT_DIR ${PROJECT_SOURCE_DIR}/port/win32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_WIN32 -D_CRT_SECURE_NO_WARNINGS")
+ELSEIF(UNIX)
+ set(PROJECT_PORT_DIR ${PROJECT_SOURCE_DIR}/port/linux)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_LINUX")
+ENDIF(WIN32)
+
+# Build debug version by default
+set(CMAKE_BUILD_TYPE "Debug")
+
+# Set include directories
+include_directories("${PROJECT_SOURCE_DIR}" "${PROJECT_PORT_DIR}" "${PROJECT_SOURCE_DIR}/port")
+
+# Get header files
+file(GLOB_RECURSE INCS "*.h")
+
+# Add sources
+add_executable(
+ SerialBoot
+ main.c
+ xcpmaster.c
+ srecord.c
+ ${PROJECT_PORT_DIR}/xcptransport.c
+ ${PROJECT_PORT_DIR}/timeutil.c
+ ${INCS}
+)
+
+
+#*********************************** end of CMakeLists.txt ******************************
\ No newline at end of file
diff --git a/Host/Source/SerialBoot/main.c b/Host/Source/SerialBoot/main.c
new file mode 100644
index 00000000..369619ec
--- /dev/null
+++ b/Host/Source/SerialBoot/main.c
@@ -0,0 +1,335 @@
+/************************************************************************************//**
+* \file main.c
+* \brief SerialBoot command line demonstration program for OpenBLT.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include /* standard I/O library */
+#include /* string library */
+#include "xcpmaster.h" /* XCP master protocol module */
+#include "srecord.h" /* S-record file handling */
+#include "timeutil.h" /* time utility module */
+
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+static void DisplayProgramInfo(void);
+static void DisplayProgramUsage(void);
+static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[]);
+
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+/** \brief Program return code if all went ok. */
+#define PROG_RESULT_OK (0)
+
+/** \brief Program return code if an error occurred. */
+#define PROG_RESULT_ERROR (1)
+
+
+/****************************************************************************************
+* Local data declarations
+****************************************************************************************/
+/** \brief Name of the serial device, such as COM4 or /dev/ttyUSB0. */
+static sb_char serialDeviceName[32];
+
+/** \brief Serial communication speed in bits per second. */
+static sb_uint32 serialBaudrate;
+
+/** \brief Name of the S-record file. */
+static sb_char srecordFileName[128];
+
+
+/************************************************************************************//**
+** \brief Program entry point.
+** \param argc Number of program parameters.
+** \param argv array to program parameter strings.
+** \return 0 on success, > 0 on error.
+**
+****************************************************************************************/
+sb_int32 main(sb_int32 argc, sb_char *argv[])
+{
+ sb_file hSrecord;
+ tSrecordParseResults fileParseResults;
+ tSrecordLineParseResults lineParseResults;
+
+ /* disable buffering for the standard output to make sure printf does not wait until
+ * a newline character is detected before outputting text on the console.
+ */
+ setbuf(stdout, SB_NULL);
+
+ /* inform user about the program */
+ DisplayProgramInfo();
+
+ /* start out by making sure program was started with the correct parameters */
+ if (ParseCommandLine(argc, argv) == SB_FALSE)
+ {
+ /* parameters invalid. inform user about how this program works */
+ DisplayProgramUsage();
+ return PROG_RESULT_ERROR;
+ }
+
+ /* -------------------- start the firmware update procedure ------------------------ */
+ printf("Starting firmware update for \"%s\" using %s @ %u bits/s\n", srecordFileName, serialDeviceName, serialBaudrate);
+
+ /* -------------------- validating the S-record file ------------------------------- */
+ printf("Checking formatting of S-record file \"%s\"...", srecordFileName);
+ if (SrecordIsValid(srecordFileName) == SB_FALSE)
+ {
+ printf("ERROR\n");
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- opening the S-record file ---------------------------------- */
+ printf("Opening S-record file \"%s\"...", srecordFileName);
+ if ((hSrecord = SrecordOpen(srecordFileName)) == SB_NULL)
+ {
+ printf("ERROR\n");
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- parsing the S-record file ---------------------------------- */
+ printf("Parsing S-record file \"%s\"...", srecordFileName);
+ SrecordParse(hSrecord, &fileParseResults);
+ printf("OK\n");
+ printf("-> Lowest memory address: 0x%08x\n", fileParseResults.address_low);
+ printf("-> Highest memory address: 0x%08x\n", fileParseResults.address_high);
+ printf("-> Total data bytes: %u\n", fileParseResults.data_bytes_total);
+
+ /* -------------------- Open the serial port --------------------------------------- */
+ printf("Opening serial port %s...", serialDeviceName);
+ if (XcpMasterInit(serialDeviceName, serialBaudrate) == SB_FALSE)
+ {
+ printf("ERROR\n");
+ SrecordClose(hSrecord);
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- Connect to XCP slave --------------------------------------- */
+ printf("Connecting to bootloader...");
+ if (XcpMasterConnect() == SB_FALSE)
+ {
+ /* no response. prompt the user to reset the system */
+ printf("TIMEOUT\nReset your microcontroller...");
+ }
+ /* now keep retrying until we get a response */
+ while (XcpMasterConnect() == SB_FALSE)
+ {
+ /* delay a bit to not pump up the CPU load */
+ TimeUtilDelayMs(20);
+ }
+ printf("OK\n");
+
+ /* -------------------- Prepare the programming session ---------------------------- */
+ printf("Initializing programming session...");
+ if (XcpMasterStartProgrammingSession() == SB_FALSE)
+ {
+ printf("ERROR\n");
+ XcpMasterDisconnect();
+ XcpMasterDeinit();
+ SrecordClose(hSrecord);
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- Erase memory ----------------------------------------------- */
+ printf("Erasing %u bytes starting at 0x%08x...", fileParseResults.data_bytes_total, fileParseResults.address_low);
+ if (XcpMasterClearMemory(fileParseResults.address_low, (fileParseResults.address_high - fileParseResults.address_low)) == SB_FALSE)
+ {
+ printf("ERROR\n");
+ XcpMasterDisconnect();
+ XcpMasterDeinit();
+ SrecordClose(hSrecord);
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- Program data ----------------------------------------------- */
+ printf("Programming data. Please wait...");
+ /* loop through all S-records with program data */
+ while (SrecordParseNextDataLine(hSrecord, &lineParseResults) == SB_TRUE)
+ {
+ if (XcpMasterProgramData(lineParseResults.address, lineParseResults.length, lineParseResults.data) == SB_FALSE)
+ {
+ printf("ERROR\n");
+ XcpMasterDisconnect();
+ XcpMasterDeinit();
+ SrecordClose(hSrecord);
+ return PROG_RESULT_ERROR;
+ }
+ }
+ printf("OK\n");
+
+ /* -------------------- Stop the programming session ------------------------------- */
+ printf("Finishing programming session...");
+ if (XcpMasterStopProgrammingSession() == SB_FALSE)
+ {
+ printf("ERROR\n");
+ XcpMasterDisconnect();
+ XcpMasterDeinit();
+ SrecordClose(hSrecord);
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- Disconnect from XCP slave and perform software reset ------- */
+ printf("Performing software reset...");
+ if (XcpMasterDisconnect() == SB_FALSE)
+ {
+ printf("ERROR\n");
+ XcpMasterDeinit();
+ SrecordClose(hSrecord);
+ return PROG_RESULT_ERROR;
+ }
+ printf("OK\n");
+
+ /* -------------------- close the serial port -------------------------------------- */
+ XcpMasterDeinit();
+ printf("Closed serial port %s\n", serialDeviceName);
+
+ /* -------------------- close the S-record file ------------------------------------ */
+ SrecordClose(hSrecord);
+ printf("Closed S-record file \"%s\"\n", srecordFileName);
+
+ /* all done */
+ printf("Firmware successfully updated!\n");
+ return PROG_RESULT_OK;
+} /*** end of main ***/
+
+
+/************************************************************************************//**
+** \brief Outputs information to the user about this program.
+** \return none.
+**
+****************************************************************************************/
+static void DisplayProgramInfo(void)
+{
+ printf("-------------------------------------------------------------------------\n");
+ printf("SerialBoot version 1.00. Performs firmware updates via the serial port\n");
+ printf("for a microcontroller based system that runs the OpenBLT bootloader.\n\n");
+ printf("Copyright (c) by Feaser http://www.feaser.com\n");
+ printf("-------------------------------------------------------------------------\n");
+} /*** end of DisplayProgramInfo ***/
+
+
+/************************************************************************************//**
+** \brief Outputs information to the user about how to use this program.
+** \return none.
+**
+****************************************************************************************/
+static void DisplayProgramUsage(void)
+{
+ printf("Usage: SerialBoot -d[device] -b[baudrate] [s-record file]\n\n");
+#ifdef PLATFORM_WIN32
+ printf("Example: SerialBoot -dCOM4 -b57600 myfirmware.s19\n");
+ printf(" -> Connects to COM4, configures a communication speed of 57600\n");
+#else
+ printf("Example: SerialBoot -d/dev/ttyS0 -b57600 myfirmware.s19\n");
+ printf(" -> Connects to ttyS0, configures a communication speed of 57600\n");
+#endif
+ printf(" bits/second and programs the myfirmware.s19 file in non-\n");
+ printf(" volatile memory of the microcontroller using OpenBLT.\n");
+ printf("-------------------------------------------------------------------------\n");
+} /*** end of DisplayProgramUsage ***/
+
+
+/************************************************************************************//**
+** \brief Parses the command line arguments. A fixed amount of arguments is expected.
+** 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.
+** \return SB_TRUE on success, SB_FALSE otherwise.
+**
+****************************************************************************************/
+static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[])
+{
+ sb_uint8 paramIdx;
+ sb_uint8 paramDfound = SB_FALSE;
+ sb_uint8 paramBfound = SB_FALSE;
+ sb_uint8 srecordfound = SB_FALSE;
+
+ /* make sure the right amount of arguments are given */
+ if (argc != 4)
+ {
+ return SB_FALSE;
+ }
+
+ /* loop through all the command lina parameters, just skip the 1st one because this
+ * is the name of the program, which we are not interested in.
+ */
+ for (paramIdx=1; paramIdx.
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include /* UNIX standard functions */
+#include /* file control definitions */
+#include /* time definitions */
+
+
+/************************************************************************************//**
+** \brief Get the system time in milliseconds.
+** \return Time in milliseconds.
+**
+****************************************************************************************/
+sb_uint32 TimeUtilGetSystemTimeMs(void)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, SB_NULL) != 0)
+ {
+ return 0;
+ }
+
+ return (sb_uint32)((tv.tv_sec * 1000ul) + (tv.tv_usec / 1000ul));
+} /*** end of XcpTransportClose ***/
+
+
+/************************************************************************************//**
+** \brief Performs a delay of the specified amount of milliseconds.
+** \param delay Delay time in milliseconds.
+** \return none.
+**
+****************************************************************************************/
+void TimeUtilDelayMs(sb_uint16 delay)
+{
+ usleep(1000 * delay);
+} /*** end of TimeUtilDelayMs **/
+
+
+/*********************************** end of xcptransport.c *****************************/
diff --git a/Host/Source/SerialBoot/port/linux/xcptransport.c b/Host/Source/SerialBoot/port/linux/xcptransport.c
new file mode 100644
index 00000000..18e429dd
--- /dev/null
+++ b/Host/Source/SerialBoot/port/linux/xcptransport.c
@@ -0,0 +1,299 @@
+/************************************************************************************//**
+* \file port\linux\xcptransport.c
+* \brief XCP transport layer interface source file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include /* standard I/O library */
+#include /* string function definitions */
+#include /* UNIX standard functions */
+#include /* file control definitions */
+#include /* error number definitions */
+#include /* POSIX terminal control */
+#include "xcpmaster.h" /* XCP master protocol module */
+#include "timeutil.h" /* time utility module */
+
+
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+/** \brief Invalid UART device/file handle. */
+#define UART_INVALID_HANDLE (-1)
+
+/** \brief maximum number of bytes in a transmit/receive XCP packet in UART. */
+#define XCP_MASTER_UART_MAX_DATA ((XCP_MASTER_TX_MAX_DATA>XCP_MASTER_RX_MAX_DATA) ? \
+ (XCP_MASTER_TX_MAX_DATA+1) : (XCP_MASTER_RX_MAX_DATA+1))
+
+/** \brief The smallest time in millisecond that the UART is configured for. */
+#define UART_RX_TIMEOUT_MIN_MS (100)
+
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+static speed_t XcpTransportGetBaudrateMask(sb_uint32 baudrate);
+
+
+/****************************************************************************************
+* Local data declarations
+****************************************************************************************/
+static tXcpTransportResponsePacket responsePacket;
+static sb_int32 hUart = UART_INVALID_HANDLE;
+
+
+/************************************************************************************//**
+** \brief Initializes the communication interface used by this transport layer.
+** \param device Serial communication device name. For example "COM4".
+** \param baudrate Communication speed in bits/sec.
+** \return SB_TRUE if successful, SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpTransportInit(sb_char *device, sb_uint32 baudrate)
+{
+ struct termios options;
+
+ /* open the port */
+ hUart = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
+ /* verify the result */
+ if (hUart == UART_INVALID_HANDLE)
+ {
+ return SB_FALSE;
+ }
+ /* configure the device to block during read operations */
+ if (fcntl(hUart, F_SETFL, 0) == -1)
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+ /* get the current options for the port */
+ if (tcgetattr(hUart, &options) == -1)
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+ /* configure the baudrate */
+ if (cfsetispeed(&options, XcpTransportGetBaudrateMask(baudrate)) == -1)
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+ if (cfsetospeed(&options, XcpTransportGetBaudrateMask(baudrate)) == -1)
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+ /* enable the receiver and set local mode */
+ options.c_cflag |= (CLOCAL | CREAD);
+ /* configure 8-n-1 */
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag |= CS8;
+ /* disable hardware flow control */
+ options.c_cflag &= ~CRTSCTS;
+ /* configure raw input */
+ options.c_lflag &= ~(ICANON | ISIG);
+ /* configure raw output */
+ options.c_oflag &= ~OPOST;
+ /* configure timeouts */
+ options.c_cc[VMIN] = 0;
+ options.c_cc[VTIME] = UART_RX_TIMEOUT_MIN_MS/100; /* 1/10th of a second */
+ /* set the new options for the port */
+ if (tcsetattr(hUart, TCSAFLUSH, &options) == -1)
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+ /* success */
+ return SB_TRUE;
+} /*** end of XcpTransportInit ***/
+
+
+/************************************************************************************//**
+** \brief Transmits an XCP packet on the transport layer and attemps to receive the
+** response within the given timeout. The data in the response packet is
+** stored in an internal data buffer that can be obtained through function
+** XcpTransportReadResponsePacket().
+** \return SB_TRUE is the response packet was successfully received and stored,
+** SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpTransportSendPacket(sb_uint8 *data, sb_uint8 len, sb_uint16 timeOutMs)
+{
+ sb_uint16 cnt;
+ static sb_uint8 xcpUartBuffer[XCP_MASTER_UART_MAX_DATA]; /* static to lower stack load */
+ sb_uint16 xcpUartLen;
+ sb_int32 bytesSent;
+ sb_int32 bytesToRead;
+ sb_int32 bytesRead;
+ sb_uint8 *uartReadDataPtr;
+ sb_uint32 timeoutTime;
+ sb_uint32 nowTime;
+ ssize_t result;
+
+ /* ------------------------ XCP packet transmission -------------------------------- */
+ /* prepare the XCP packet for transmission on UART. this is basically the same as the
+ * xcp packet data but just the length of the packet is added to the first byte.
+ */
+ xcpUartLen = len+1;
+ xcpUartBuffer[0] = len;
+ for (cnt=0; cnt 0)
+ {
+ result = read(hUart, uartReadDataPtr, bytesToRead);
+ if (result != -1)
+ {
+ bytesRead = result;
+ /* update the bytes that were already read */
+ uartReadDataPtr += bytesRead;
+ bytesToRead -= bytesRead;
+ }
+ /* check for timeout if not yet done */
+ if ( (bytesToRead > 0) && (TimeUtilGetSystemTimeMs() >= timeoutTime) )
+ {
+ /* timeout occurred */
+ return SB_FALSE;
+ }
+ }
+
+ /* read the rest of the packet */
+ bytesToRead = responsePacket.len;
+ uartReadDataPtr = &responsePacket.data[0];
+ while(bytesToRead > 0)
+ {
+ result = read(hUart, uartReadDataPtr, bytesToRead);
+ if (result != -1)
+ {
+ bytesRead = result;
+ /* update the bytes that were already read */
+ uartReadDataPtr += bytesRead;
+ bytesToRead -= bytesRead;
+ }
+ /* check for timeout if not yet done */
+ if ( (bytesToRead > 0) && (TimeUtilGetSystemTimeMs() >= timeoutTime) )
+ {
+ /* timeout occurred */
+ return SB_FALSE;
+ }
+ }
+ /* still here so the complete packet was received */
+ return SB_TRUE;
+} /*** end of XcpMasterTpSendPacket ***/
+
+
+/************************************************************************************//**
+** \brief Reads the data from the response packet. Make sure to not call this
+** function while XcpTransportSendPacket() is active, because the data won't be
+** valid then.
+** \return Pointer to the response packet data.
+**
+****************************************************************************************/
+tXcpTransportResponsePacket *XcpTransportReadResponsePacket(void)
+{
+ return &responsePacket;
+} /*** end of XcpTransportReadResponsePacket ***/
+
+
+/************************************************************************************//**
+** \brief Closes the communication channel.
+** \return none.
+**
+****************************************************************************************/
+void XcpTransportClose(void)
+{
+ /* close the COM port handle if valid */
+ if (hUart != UART_INVALID_HANDLE)
+ {
+ close(hUart);
+ }
+
+ /* set handles to invalid */
+ hUart = UART_INVALID_HANDLE;
+} /*** end of XcpTransportClose ***/
+
+
+/************************************************************************************//**
+** \brief Converts the baudrate value to a bitmask value used by termios. Currently
+** supports the most commonly used baudrates.
+** \return none.
+**
+****************************************************************************************/
+static speed_t XcpTransportGetBaudrateMask(sb_uint32 baudrate)
+{
+ speed_t result;
+
+ switch (baudrate)
+ {
+ case 115200:
+ result = B115200;
+ break;
+ case 57600:
+ result = B57600;
+ break;
+ case 38400:
+ result = B38400;
+ break;
+ case 19200:
+ result = B19200;
+ break;
+ case 9600:
+ default:
+ result = B9600;
+ break;
+ }
+ return result;
+} /*** end of XcpTransportGetBaudrateMask ***/
+
+
+/*********************************** end of xcptransport.c *****************************/
diff --git a/Host/Source/SerialBoot/port/timeutil.h b/Host/Source/SerialBoot/port/timeutil.h
new file mode 100644
index 00000000..86840b2e
--- /dev/null
+++ b/Host/Source/SerialBoot/port/timeutil.h
@@ -0,0 +1,44 @@
+/************************************************************************************//**
+* \file port\timeutil.h
+* \brief Time utility header file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+#ifndef TIMEUTIL_H
+#define TIMEUTIL_H
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+sb_uint32 TimeUtilGetSystemTimeMs(void);
+void TimeUtilDelayMs(sb_uint16 delay);
+
+
+#endif /* TIMEUTIL_H */
+/*********************************** end of timeutil.h *********************************/
diff --git a/Host/Source/SerialBoot/port/win32/timeutil.c b/Host/Source/SerialBoot/port/win32/timeutil.c
new file mode 100644
index 00000000..97411d53
--- /dev/null
+++ b/Host/Source/SerialBoot/port/win32/timeutil.c
@@ -0,0 +1,65 @@
+/************************************************************************************//**
+* \file port\win32\timeutil.c
+* \brief Time utility source file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include /* for WIN32 library */
+
+
+/************************************************************************************//**
+** \brief Get the system time in milliseconds.
+** \return Time in milliseconds.
+**
+****************************************************************************************/
+sb_uint32 TimeUtilGetSystemTimeMs(void)
+{
+ return GetTickCount();
+} /*** end of XcpTransportClose ***/
+
+
+/************************************************************************************//**
+** \brief Performs a delay of the specified amount of milliseconds.
+** \param delay Delay time in milliseconds.
+** \return none.
+**
+****************************************************************************************/
+void TimeUtilDelayMs(sb_uint16 delay)
+{
+ Sleep(delay);
+} /*** end of TimeUtilDelayMs **/
+
+
+/*********************************** end of timeutil.c *********************************/
diff --git a/Host/Source/SerialBoot/port/win32/xcptransport.c b/Host/Source/SerialBoot/port/win32/xcptransport.c
new file mode 100644
index 00000000..c9fc979d
--- /dev/null
+++ b/Host/Source/SerialBoot/port/win32/xcptransport.c
@@ -0,0 +1,262 @@
+/************************************************************************************//**
+* \file port\win32\xcptransport.c
+* \brief XCP transport layer interface source file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include /* for WIN32 library */
+#include /* string library */
+#include "xcpmaster.h" /* XCP master protocol module */
+#include "timeutil.h" /* time utility module */
+
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+#define UART_TX_BUFFER_SIZE (1024) /**< transmission buffer size */
+#define UART_RX_BUFFER_SIZE (1024) /**< reception buffer size */
+
+/** \brief maximum number of bytes in a transmit/receive XCP packet in UART. */
+#define XCP_MASTER_UART_MAX_DATA ((XCP_MASTER_TX_MAX_DATA>XCP_MASTER_RX_MAX_DATA) ? \
+ (XCP_MASTER_TX_MAX_DATA+1) : (XCP_MASTER_RX_MAX_DATA+1))
+
+/** \brief The smallest time in millisecond that the UART is configured for. */
+#define UART_RX_TIMEOUT_MIN_MS (5)
+
+
+/****************************************************************************************
+* Local data declarations
+****************************************************************************************/
+static tXcpTransportResponsePacket responsePacket;
+static HANDLE hUart = INVALID_HANDLE_VALUE;
+
+
+/************************************************************************************//**
+** \brief Initializes the communication interface used by this transport layer.
+** \param device Serial communication device name. For example "COM4".
+** \param baudrate Communication speed in bits/sec.
+** \return SB_TRUE if successful, SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpTransportInit(sb_char *device, sb_uint32 baudrate)
+{
+ COMMTIMEOUTS timeouts = { 0 };
+ DCB dcbSerialParams = { 0 };
+ char portStr[64] = "\\\\.\\\0";
+
+ /* construct the COM port name as a string */
+ strcat_s(portStr, 59, device);
+
+ /* obtain access to the COM port */
+ hUart = CreateFile(portStr, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, 0);
+
+ /* validate COM port handle */
+ if (hUart == INVALID_HANDLE_VALUE)
+ {
+ return SB_FALSE;
+ }
+
+ /* get current COM port configuration */
+ dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
+ if (!GetCommState(hUart, &dcbSerialParams))
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+
+ /* configure the baudrate and 8,n,1 */
+ dcbSerialParams.BaudRate = baudrate;
+ dcbSerialParams.ByteSize = 8;
+ dcbSerialParams.StopBits = ONESTOPBIT;
+ dcbSerialParams.Parity = NOPARITY;
+ if (!SetCommState(hUart, &dcbSerialParams))
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+
+ /* set communication timeout parameters */
+ timeouts.ReadIntervalTimeout = UART_RX_TIMEOUT_MIN_MS;
+ timeouts.ReadTotalTimeoutConstant = UART_RX_TIMEOUT_MIN_MS;
+ timeouts.ReadTotalTimeoutMultiplier = 1;
+ timeouts.WriteTotalTimeoutConstant = UART_RX_TIMEOUT_MIN_MS;
+ timeouts.WriteTotalTimeoutMultiplier = 1;
+ if (!SetCommTimeouts(hUart, &timeouts))
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+
+ /* set transmit and receive buffer sizes */
+ if(!SetupComm(hUart, UART_RX_BUFFER_SIZE, UART_TX_BUFFER_SIZE))
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+
+ /* empty the transmit and receive buffers */
+ if (!FlushFileBuffers(hUart))
+ {
+ XcpTransportClose();
+ return SB_FALSE;
+ }
+ /* successfully connected to the serial device */
+ return SB_TRUE;
+} /*** end of XcpTransportInit ***/
+
+
+/************************************************************************************//**
+** \brief Transmits an XCP packet on the transport layer and attemps to receive the
+** response within the given timeout. The data in the response packet is
+** stored in an internal data buffer that can be obtained through function
+** XcpTransportReadResponsePacket().
+** \return SB_TRUE is the response packet was successfully received and stored,
+** SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpTransportSendPacket(sb_uint8 *data, sb_uint8 len, sb_uint16 timeOutMs)
+{
+ sb_uint32 dwWritten = 0;
+ sb_uint32 dwRead = 0;
+ sb_uint32 dwToRead;
+ sb_uint16 cnt;
+ static sb_uint8 xcpUartBuffer[XCP_MASTER_UART_MAX_DATA]; /* static to lower stack load */
+ sb_uint16 xcpUartLen;
+ sb_uint8 *uartReadDataPtr;
+ sb_uint32 timeoutTime;
+
+ /* ------------------------ XCP packet transmission -------------------------------- */
+ /* prepare the XCP packet for transmission on UART. this is basically the same as the
+ * xcp packet data but just the length of the packet is added to the first byte.
+ */
+ xcpUartLen = len+1;
+ xcpUartBuffer[0] = len;
+ for (cnt=0; cnt 0)
+ {
+ dwRead = 0;
+ if (ReadFile(hUart, uartReadDataPtr, dwToRead, &dwRead, NULL))
+ {
+ /* update the bytes that were already read */
+ uartReadDataPtr += dwRead;
+ dwToRead -= dwRead;
+ }
+ /* check for timeout if not yet done */
+ if ( (dwToRead > 0) && (TimeUtilGetSystemTimeMs() >= timeoutTime) )
+ {
+ /* timeout occurred */
+ return SB_FALSE;
+ }
+ }
+
+ /* read the rest of the packet */
+ dwToRead = responsePacket.len;
+ uartReadDataPtr = &responsePacket.data[0];
+ while(dwToRead > 0)
+ {
+ dwRead = 0;
+ if (ReadFile(hUart, uartReadDataPtr, dwToRead, &dwRead, NULL))
+ {
+ /* update the bytes that were already read */
+ uartReadDataPtr += dwRead;
+ dwToRead -= dwRead;
+ }
+ /* check for timeout if not yet done */
+ if ( (dwToRead > 0) && (TimeUtilGetSystemTimeMs() >= timeoutTime) )
+ {
+ /* timeout occurred */
+ return SB_FALSE;
+ }
+ }
+ /* still here so the complete packet was received */
+ return SB_TRUE;
+} /*** end of XcpMasterTpSendPacket ***/
+
+
+/************************************************************************************//**
+** \brief Reads the data from the response packet. Make sure to not call this
+** function while XcpTransportSendPacket() is active, because the data won't be
+** valid then.
+** \return Pointer to the response packet data.
+**
+****************************************************************************************/
+tXcpTransportResponsePacket *XcpTransportReadResponsePacket(void)
+{
+ return &responsePacket;
+} /*** end of XcpTransportReadResponsePacket ***/
+
+
+/************************************************************************************//**
+** \brief Closes the communication channel.
+** \return none.
+**
+****************************************************************************************/
+void XcpTransportClose(void)
+{
+ /* close the COM port handle if valid */
+ if (hUart != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hUart);
+ }
+
+ /* set handles to invalid */
+ hUart = INVALID_HANDLE_VALUE;
+} /*** end of XcpTransportClose ***/
+
+
+/*********************************** end of xcptransport.c *****************************/
diff --git a/Host/Source/SerialBoot/port/xcptransport.h b/Host/Source/SerialBoot/port/xcptransport.h
new file mode 100644
index 00000000..795ecdea
--- /dev/null
+++ b/Host/Source/SerialBoot/port/xcptransport.h
@@ -0,0 +1,56 @@
+/************************************************************************************//**
+* \file port\xcptransport.h
+* \brief XCP transport layer interface header file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+#ifndef XCPTRANSPORT_H
+#define XCPTRANSPORT_H
+
+/****************************************************************************************
+* Type definitions
+****************************************************************************************/
+typedef struct
+{
+ sb_uint8 data[XCP_MASTER_RX_MAX_DATA];
+ sb_uint8 len;
+} tXcpTransportResponsePacket;
+
+
+/****************************************************************************************
+* EFunction prototypes
+****************************************************************************************/
+sb_uint8 XcpTransportInit(sb_char *device, sb_uint32 baudrate);
+sb_uint8 XcpTransportSendPacket(sb_uint8 *data, sb_uint8 len, sb_uint16 timeOutMs);
+tXcpTransportResponsePacket *XcpTransportReadResponsePacket(void);
+void XcpTransportClose(void);
+
+
+#endif /* XCPTRANSPORT_H */
+/*********************************** end of xcptransport.h *****************************/
diff --git a/Host/Source/SerialBoot/sb_types.h b/Host/Source/SerialBoot/sb_types.h
new file mode 100644
index 00000000..de019cd5
--- /dev/null
+++ b/Host/Source/SerialBoot/sb_types.h
@@ -0,0 +1,70 @@
+/************************************************************************************//**
+* \file sb_types.h
+* \brief Serial Boot type definitions header file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+#ifndef SB_TYPES_H
+#define SB_TYPES_H
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* standard I/O library */
+
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+/** \brief Generic boolean true value. */
+#define SB_TRUE (1u)
+
+/** \brief Ceneric boolean false value. */
+#define SB_FALSE (0u)
+
+/** \brief NULL pointer value. */
+#define SB_NULL ((void *)0)
+
+
+/****************************************************************************************
+* Type definitions
+****************************************************************************************/
+typedef signed char sb_char;
+typedef signed char sb_int8;
+typedef signed short sb_int16;
+typedef signed int sb_int32;
+typedef unsigned char sb_uint8;
+typedef unsigned short sb_uint16;
+typedef unsigned int sb_uint32;
+typedef FILE * sb_file;
+
+
+
+#endif /* SB_TYPES_H */
+/*********************************** end of sb_types.h *********************************/
diff --git a/Host/Source/SerialBoot/srecord.c b/Host/Source/SerialBoot/srecord.c
new file mode 100644
index 00000000..75bbf88f
--- /dev/null
+++ b/Host/Source/SerialBoot/srecord.c
@@ -0,0 +1,453 @@
+/************************************************************************************//**
+* \file srecord.c
+* \brief Motorola S-record library header file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include /* for strcpy etc. */
+#include /* for toupper() etc. */
+#include "srecord.h" /* S-record library */
+
+
+/****************************************************************************************
+* Type definitions
+****************************************************************************************/
+/** \brief Enumeration for the different S-record line types. */
+typedef enum
+{
+ LINE_TYPE_S1, /**< 16-bit address line */
+ LINE_TYPE_S2, /**< 24-bit address line */
+ LINE_TYPE_S3, /**< 32-bit address line */
+ LINE_TYPE_UNSUPPORTED /**< unsupported line */
+} tSrecordLineType;
+
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+static tSrecordLineType SrecordGetLineType(const sb_char *line);
+static sb_uint8 SrecordVerifyChecksum(const sb_char *line);
+static sb_uint8 SrecordHexStringToByte(const sb_char *hexstring);
+static sb_uint8 SrecordReadLine(sb_file srecordHandle, sb_char *line);
+
+
+/************************************************************************************//**
+** \brief Checks if the specified srecordFile exists and contains s-records.
+** \param srecordFile The S-record file with full path if applicable.
+** \return SB_TRUE on the S-record is valid, SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 SrecordIsValid(const sb_char *srecordFile)
+{
+ sb_file tempHandle;
+ sb_char line[SRECORD_MAX_CHARS_PER_LINE];
+
+ /* attempt to open the file */
+ tempHandle = SrecordOpen(srecordFile);
+ /* is the file available? */
+ if (tempHandle == SB_NULL)
+ {
+ /* cannot open the file */
+ return SB_FALSE;
+ }
+ /* all lines should be formatted as S-records. read the first one to check this */
+ if (SrecordReadLine(tempHandle, line) == SB_FALSE)
+ {
+ /* could not read a line. file must be empty */
+ SrecordClose(tempHandle);
+ return SB_FALSE;
+ }
+ /* check if the line starts with the 'S' character, followed by a digit */
+ if ( (toupper(line[0]) != 'S') || (isdigit(line[1]) == 0) )
+ {
+ SrecordClose(tempHandle);
+ return SB_FALSE;
+ }
+
+ /* still here so it is a valid s-record */
+ SrecordClose(tempHandle);
+ return SB_TRUE;
+} /*** end of SrecordIsValid ***/
+
+
+/************************************************************************************//**
+** \brief Opens the S-record file for reading.
+** \param srecordFile The S-record file with full path if applicable.
+** \return The filehandle if successful, SB_NULL otherwise.
+**
+****************************************************************************************/
+sb_file SrecordOpen(const sb_char *srecordFile)
+{
+ /* open the file for reading */
+ return fopen(srecordFile, "r");
+} /*** end of SrecordOpen ***/
+
+
+/************************************************************************************//**
+** \brief Parse the S-record file to obtain information about its contents.
+** \param srecordHandle The S-record file handle. It is returned by SrecordOpen.
+** \param parseResults Pointer to where the parse results should be stored.
+** \return none.
+**
+****************************************************************************************/
+void SrecordParse(sb_file srecordHandle, tSrecordParseResults *parseResults)
+{
+ tSrecordLineParseResults lineResults;
+
+ /* start at the beginning of the file */
+ rewind(srecordHandle);
+
+ /* init data structure */
+ parseResults->address_high = 0;
+ parseResults->address_low = 0xffffffff;
+ parseResults->data_bytes_total = 0;
+
+ /* loop through all S-records with program data */
+ while (SrecordParseNextDataLine(srecordHandle, &lineResults) == SB_TRUE)
+ {
+ /* update byte total */
+ parseResults->data_bytes_total += lineResults.length;
+ /* is this a new lowest address? */
+ if (lineResults.address < parseResults->address_low)
+ {
+ parseResults->address_low = lineResults.address;
+ }
+ /* is this a new highest address? */
+ if ((lineResults.address + lineResults.length - 1) > parseResults->address_high)
+ {
+ parseResults->address_high = (lineResults.address + lineResults.length - 1);
+ }
+ }
+ /* reset to the beginning of the file again */
+ rewind(srecordHandle);
+} /*** end of SrecordParse ***/
+
+
+/************************************************************************************//**
+** \brief Closes the S-record file.
+** \param srecordHandle The S-record file handle. It is returned by SrecordOpen.
+** \return none.
+**
+****************************************************************************************/
+void SrecordClose(sb_file srecordHandle)
+{
+ /* close the file handle if valid */
+ if (srecordHandle != SB_NULL)
+ {
+ fclose(srecordHandle);
+ }
+} /*** end of SrecordClose ***/
+
+
+/************************************************************************************//**
+** \brief Reads the next S-record with program data, parses it and returns the
+** results.
+** \param srecordHandle The S-record file handle. It is returned by SrecordOpen.
+** \param parseResults Pointer to where the parse results should be stored.
+** \return SB_TRUE is valid parse results were stored. SB_FALSE in case of end-of-
+** file.
+**
+****************************************************************************************/
+sb_uint8 SrecordParseNextDataLine(sb_file srecordHandle, tSrecordLineParseResults *parseResults)
+{
+ sb_char line[SRECORD_MAX_CHARS_PER_LINE];
+ sb_uint8 data_line_found = SB_FALSE;
+ tSrecordLineType lineType;
+ sb_uint16 bytes_on_line;
+ sb_uint16 i;
+ sb_char *linePtr;
+
+ /* first set the length paramter to 0 */
+ parseResults->length = 0;
+
+ while (data_line_found == SB_FALSE)
+ {
+ /* read the next line from the file */
+ if (SrecordReadLine(srecordHandle, line) == SB_FALSE)
+ {
+ /* end-of-file encountered */
+ return SB_FALSE;
+ }
+ /* we now have a line. check if it is a S-record data line */
+ lineType = SrecordGetLineType(line);
+ if (lineType != LINE_TYPE_UNSUPPORTED)
+ {
+ /* check if the checksum on the line is correct */
+ if (SrecordVerifyChecksum(line) == SB_TRUE)
+ {
+ /* found a valid line that can be parsed. loop will stop */
+ data_line_found = SB_TRUE;
+ break;
+ }
+ }
+ }
+
+ /* still here so we have a valid S-record data line. start parsing */
+ linePtr = &line[0];
+ /* all good so far, now read out the address and databytes for the line */
+ switch (lineType)
+ {
+ /* ---------------------------- S1 line type ------------------------------------- */
+ case LINE_TYPE_S1:
+ /* adjust pointer to point to byte count value */
+ linePtr += 2;
+ /* read out the number of byte values that follow on the line */
+ bytes_on_line = SrecordHexStringToByte(linePtr);
+ /* read out the 16-bit address */
+ linePtr += 2;
+ parseResults->address = SrecordHexStringToByte(linePtr) << 8;
+ linePtr += 2;
+ parseResults->address += SrecordHexStringToByte(linePtr);
+ /* adjust pointer to point to the first data byte after the address */
+ linePtr += 2;
+ /* determine how many data bytes are on the line */
+ parseResults->length = bytes_on_line - 3; /* -2 bytes address, -1 byte checksum */
+ /* read and store data bytes if requested */
+ for (i=0; ilength; i++)
+ {
+ parseResults->data[i] = SrecordHexStringToByte(linePtr);
+ linePtr += 2;
+ }
+ break;
+
+ /* ---------------------------- S2 line type ------------------------------------- */
+ case LINE_TYPE_S2:
+ /* adjust pointer to point to byte count value */
+ linePtr += 2;
+ /* read out the number of byte values that follow on the line */
+ bytes_on_line = SrecordHexStringToByte(linePtr);
+ /* read out the 32-bit address */
+ linePtr += 2;
+ parseResults->address = SrecordHexStringToByte(linePtr) << 16;
+ linePtr += 2;
+ parseResults->address += SrecordHexStringToByte(linePtr) << 8;
+ linePtr += 2;
+ parseResults->address += SrecordHexStringToByte(linePtr);
+ /* adjust pointer to point to the first data byte after the address */
+ linePtr += 2;
+ /* determine how many data bytes are on the line */
+ parseResults->length = bytes_on_line - 4; /* -3 bytes address, -1 byte checksum */
+ /* read and store data bytes if requested */
+ for (i=0; ilength; i++)
+ {
+ parseResults->data[i] = SrecordHexStringToByte(linePtr);
+ linePtr += 2;
+ }
+ break;
+
+ /* ---------------------------- S3 line type ------------------------------------- */
+ case LINE_TYPE_S3:
+ /* adjust pointer to point to byte count value */
+ linePtr += 2;
+ /* read out the number of byte values that follow on the line */
+ bytes_on_line = SrecordHexStringToByte(linePtr);
+ /* read out the 32-bit address */
+ linePtr += 2;
+ parseResults->address = SrecordHexStringToByte(linePtr) << 24;
+ linePtr += 2;
+ parseResults->address += SrecordHexStringToByte(linePtr) << 16;
+ linePtr += 2;
+ parseResults->address += SrecordHexStringToByte(linePtr) << 8;
+ linePtr += 2;
+ parseResults->address += SrecordHexStringToByte(linePtr);
+ /* adjust pointer to point to the first data byte after the address */
+ linePtr += 2;
+ /* determine how many data bytes are on the line */
+ parseResults->length = bytes_on_line - 5; /* -4 bytes address, -1 byte checksum */
+ /* read and store data bytes if requested */
+ for (i=0; ilength; i++)
+ {
+ parseResults->data[i] = SrecordHexStringToByte(linePtr);
+ linePtr += 2;
+ }
+ break;
+
+ default:
+ /* will not happen */
+ break;
+ }
+
+ /* parsing all done */
+ return SB_TRUE;
+} /*** end of SrecordParseNextDataLine ***/
+
+
+/************************************************************************************//**
+** \brief Inspects a line from a Motorola S-Record file to determine its type.
+** \param line A line from the S-Record.
+** \return the S-Record line type.
+**
+****************************************************************************************/
+static tSrecordLineType SrecordGetLineType(const sb_char *line)
+{
+ /* check if the line starts with the 'S' character, followed by a digit */
+ if ( (toupper(line[0]) != 'S') || (isdigit(line[1]) == 0) )
+ {
+ /* not a valid S-Record line type */
+ return LINE_TYPE_UNSUPPORTED;
+ }
+ /* determine the line type */
+ if (line[1] == '1')
+ {
+ return LINE_TYPE_S1;
+ }
+ if (line[1] == '2')
+ {
+ return LINE_TYPE_S2;
+ }
+ if (line[1] == '3')
+ {
+ return LINE_TYPE_S3;
+ }
+ /* still here so not a supported line type found */
+ return LINE_TYPE_UNSUPPORTED;
+} /*** end of SrecordGetLineType ***/
+
+
+/************************************************************************************//**
+** \brief Inspects an S1, S2 or S3 line from a Motorola S-Record file to
+** determine if the checksum at the end is corrrect.
+** \param line An S1, S2 or S3 line from the S-Record.
+** \return SB_TRUE if the checksum is correct, SB_FALSE otherwise.
+**
+****************************************************************************************/
+static sb_uint8 SrecordVerifyChecksum(const sb_char *line)
+{
+ sb_uint16 bytes_on_line;
+ sb_uint8 checksum = 0;
+
+ /* adjust pointer to point to byte count value */
+ line += 2;
+ /* read out the number of byte values that follow on the line */
+ bytes_on_line = SrecordHexStringToByte(line);
+ /* byte count is part of checksum */
+ checksum += bytes_on_line;
+ /* adjust pointer to the first byte of the address */
+ line += 2;
+ /* add byte values of address and data, but not the final checksum */
+ do
+ {
+ /* add the next byte value to the checksum */
+ checksum += SrecordHexStringToByte(line);
+ /* update counter */
+ bytes_on_line--;
+ /* point to next hex string in the line */
+ line += 2;
+ }
+ while (bytes_on_line > 1);
+ /* the checksum is calculated by summing up the values of the byte count, address and
+ * databytes and then taking the 1-complement of the sum's least signigicant byte */
+ checksum = ~checksum;
+ /* finally verify the calculated checksum with the one at the end of the line */
+ if (checksum != SrecordHexStringToByte(line))
+ {
+ /* checksum incorrect */
+ return SB_FALSE;
+ }
+ /* still here so the checksum was correct */
+ return SB_TRUE;
+} /*** end of SrecordVerifyChecksum ***/
+
+
+/************************************************************************************//**
+** \brief Helper function to convert a sequence of 2 characters that represent
+** a hexadecimal value to the actual byte value.
+** Example: SrecordHexStringToByte("2f") --> returns 47.
+** \param hexstring String beginning with 2 characters that represent a hexa-
+** decimal value.
+** \return The resulting byte value.
+**
+****************************************************************************************/
+static sb_uint8 SrecordHexStringToByte(const sb_char *hexstring)
+{
+ sb_uint8 result = 0;
+ sb_char c;
+ sb_uint8 counter;
+
+ /* a hexadecimal character is 2 characters long (i.e 0x4F minus the 0x part) */
+ for (counter=0; counter < 2; counter++)
+ {
+ /* read out the character */
+ c = toupper(hexstring[counter]);
+ /* check that the character is 0..9 or A..F */
+ if ( (c < '0') || (c > 'F') || ( (c > '9') && (c < 'A') ) )
+ {
+ /* character not valid */
+ return 0;
+ }
+ /* convert character to 4-bit value (check ASCII table for more info) */
+ c -= '0';
+ if (c > 9)
+ {
+ c -= 7;
+ }
+ /* add it to the result */
+ result = (result << 4) + c;
+ }
+ /* return the results */
+ return result;
+} /*** end of SrecordHexStringToByte ***/
+
+
+/************************************************************************************//**
+** \brief Reads the next line from the S-record file handle.
+** \param srecordHandle The S-record file handle. It is returned by SrecordOpen.
+** \param line Destination buffer for the line characters. Should be of size
+** SRECORD_MAX_CHARS_PER_LINE.
+** \return SB_TRUE if successful, SB_FALSE otherwise.
+**
+****************************************************************************************/
+static sb_uint8 SrecordReadLine(sb_file srecordHandle, sb_char *line)
+{
+ /* init the line as an empty line */
+ line[0] = '\0';
+
+ /* loop as long as we find a non-empty line or end-of-file */
+ while (line[0] == '\0')
+ {
+ if (fgets(line, SRECORD_MAX_CHARS_PER_LINE, srecordHandle) == SB_NULL)
+ {
+ /* no more lines available */
+ return SB_FALSE;
+ }
+ /* replace the line termination with a string termination */
+ line[strcspn(line, "\n")] = '\0';
+ }
+ /* still here so not EOF and not and empty line, so success */
+ return SB_TRUE;
+} /*** end of SrecordReadLine ***/
+
+
+/*********************************** end of srecord.c **********************************/
diff --git a/Host/Source/SerialBoot/srecord.h b/Host/Source/SerialBoot/srecord.h
new file mode 100644
index 00000000..1caf6d0a
--- /dev/null
+++ b/Host/Source/SerialBoot/srecord.h
@@ -0,0 +1,80 @@
+/************************************************************************************//**
+* \file srecord.h
+* \brief Motorola S-record library header file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+#ifndef SRECORD_H
+#define SRECORD_H
+
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+/** \brief Maximum number of characters that can be on a line in the firmware file. */
+#define SRECORD_MAX_CHARS_PER_LINE (512)
+
+/** \brief Maximum number of data bytes that can be on a line in the firmware file
+ * (S-record).
+ */
+#define SRECORD_MAX_DATA_BYTES_PER_LINE (SRECORD_MAX_CHARS_PER_LINE/2)
+
+
+/****************************************************************************************
+* Type definitions
+****************************************************************************************/
+/** \brief Structure type for grouping the parsing results of an S-record file. */
+typedef struct
+{
+ sb_uint32 address_low; /**< lowest memory address */
+ sb_uint32 address_high; /**< lowest memory address */
+ sb_uint32 data_bytes_total; /**< total number of data bytes */
+} tSrecordParseResults;
+
+/** \brief Structure type for grouping the parsing results of an S-record line. */
+typedef struct
+{
+ sb_uint8 data[SRECORD_MAX_DATA_BYTES_PER_LINE]; /**< array for S1,S2 or S3 data bytes*/
+ sb_uint32 address; /**< address on S1,S2 or S3 line */
+ sb_uint16 length; /**< number of bytes written to array */
+} tSrecordLineParseResults;
+
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+sb_uint8 SrecordIsValid(const sb_char *srecordFile);
+sb_file SrecordOpen(const sb_char *srecordFile);
+void SrecordParse(sb_file srecordHandle, tSrecordParseResults *parseResults);
+void SrecordClose(sb_file srecordHandle);
+sb_uint8 SrecordParseNextDataLine(sb_file srecordHandle, tSrecordLineParseResults *parseResults);
+
+
+#endif /* SRECORD_H */
+/*********************************** end of srecord.h **********************************/
diff --git a/Host/Source/SerialBoot/xcpmaster.c b/Host/Source/SerialBoot/xcpmaster.c
new file mode 100644
index 00000000..c05e4b78
--- /dev/null
+++ b/Host/Source/SerialBoot/xcpmaster.c
@@ -0,0 +1,694 @@
+/************************************************************************************//**
+* \file xcpmaster.c
+* \brief XCP Master source file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include /* assertion module */
+#include /* C types */
+#include "xcpmaster.h" /* XCP master protocol module */
+
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+/* XCP command codes as defined by the protocol currently supported by this module */
+#define XCP_MASTER_CMD_CONNECT (0xFF)
+#define XCP_MASTER_CMD_DISCONNECT (0xFE)
+#define XCP_MASTER_CMD_SET_MTA (0xF6)
+#define XCP_MASTER_CMD_UPLOAD (0xF5)
+#define XCP_MASTER_CMD_PROGRAM_START (0xD2)
+#define XCP_MASTER_CMD_PROGRAM_CLEAR (0xD1)
+#define XCP_MASTER_CMD_PROGRAM (0xD0)
+#define XCP_MASTER_CMD_PROGRAM_RESET (0xCF)
+#define XCP_MASTER_CMD_PROGRAM_MAX (0xC9)
+
+/* XCP response packet IDs as defined by the protocol */
+#define XCP_MASTER_CMD_PID_RES (0xFF) /* positive response */
+
+/* timeout values */
+#define XCP_MASTER_CONNECT_TIMEOUT_MS (20)
+#define XCP_MASTER_TIMEOUT_T1_MS (1000) /* standard command timeout */
+#define XCP_MASTER_TIMEOUT_T2_MS (2000) /* build checksum timeout */
+#define XCP_MASTER_TIMEOUT_T3_MS (2000) /* program start timeout */
+#define XCP_MASTER_TIMEOUT_T4_MS (10000) /* erase timeout */
+#define XCP_MASTER_TIMEOUT_T5_MS (1000) /* write and reset timeout */
+#define XCP_MASTER_TIMEOUT_T6_MS (1000) /* user specific connect connect timeout */
+#define XCP_MASTER_TIMEOUT_T7_MS (2000) /* wait timer timeout */
+
+/** \brief Number of retries to connect to the XCP slave. */
+#define XCP_MASTER_CONNECT_RETRIES (5)
+
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+static sb_uint8 XcpMasterSendCmdConnect(void);
+static sb_uint8 XcpMasterSendCmdSetMta(sb_uint32 address);
+static sb_uint8 XcpMasterSendCmdUpload(sb_uint8 data[], sb_uint8 length);
+static sb_uint8 XcpMasterSendCmdProgramStart(void);
+static sb_uint8 XcpMasterSendCmdProgramReset(void);
+static sb_uint8 XcpMasterSendCmdProgram(sb_uint8 length, sb_uint8 data[]);
+static sb_uint8 XcpMasterSendCmdProgramMax(sb_uint8 data[]);
+static sb_uint8 XcpMasterSendCmdProgramClear(sb_uint32 length);
+static void XcpMasterSetOrderedLong(sb_uint32 value, sb_uint8 data[]);
+
+
+/****************************************************************************************
+* Local data declarations
+****************************************************************************************/
+/** \brief Store the byte ordering of the XCP slave. */
+static sb_uint8 xcpSlaveIsIntel = SB_FALSE;
+
+/** \brief The max number of bytes in the command transmit object (master->slave). */
+static sb_uint8 xcpMaxCto;
+
+/** \brief The max number of bytes in the command transmit object (master->slave) during
+ * a programming session.
+ */
+static sb_uint8 xcpMaxProgCto = 0;
+
+/** \brief The max number of bytes in the data transmit object (slave->master). */
+static sb_uint8 xcpMaxDto;
+
+/** \brief Internal data buffer for storing the data of the XCP response packet. */
+static tXcpTransportResponsePacket responsePacket;
+
+
+/************************************************************************************//**
+** \brief Initializes the XCP master protocol layer.
+** \param device Serial communication device name. For example "COM4".
+** \param baudrate Communication speed in bits/sec.
+** \return SB_TRUE is successful, SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpMasterInit(sb_char *device, sb_uint32 baudrate)
+{
+ /* initialize the underlying transport layer that is used for the communication */
+ return XcpTransportInit(device, baudrate);
+} /*** end of XcpMasterInit ***/
+
+
+/************************************************************************************//**
+** \brief Uninitializes the XCP master protocol layer.
+** \return none.
+**
+****************************************************************************************/
+void XcpMasterDeinit(void)
+{
+ XcpTransportClose();
+} /*** end of XcpMasterDeinit ***/
+
+
+/************************************************************************************//**
+** \brief Connect to the XCP slave.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpMasterConnect(void)
+{
+ sb_uint8 cnt;
+
+ /* try to connect with a finite amount of retries */
+ for (cnt=0; cnt 0)
+ {
+ /* set the current read length to make optimal use of the available packet data. */
+ currentReadCnt = len % (xcpMaxDto - 1);
+ if (currentReadCnt == 0)
+ {
+ currentReadCnt = (xcpMaxDto - 1);
+ }
+ /* upload some data */
+ if (XcpMasterSendCmdUpload(&data[bufferOffset], currentReadCnt) == SB_FALSE)
+ {
+ return SB_FALSE;
+ }
+ /* update loop variables */
+ len -= currentReadCnt;
+ bufferOffset += currentReadCnt;
+ }
+ /* still here so all data successfully read from the slave */
+ return SB_TRUE;
+} /*** end of XcpMasterReadData ***/
+
+
+/************************************************************************************//**
+** \brief Programs data to the slave's non volatile memory. Note that it must be
+** erased first.
+** \param addr Base memory address for the program operation
+** \param len Number of bytes to program.
+** \param data Source buffer with the to be programmed bytes.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+sb_uint8 XcpMasterProgramData(sb_uint32 addr, sb_uint32 len, sb_uint8 data[])
+{
+ sb_uint8 currentWriteCnt;
+ sb_uint32 bufferOffset = 0;
+
+ /* first set the MTA pointer */
+ if (XcpMasterSendCmdSetMta(addr) == SB_FALSE)
+ {
+ return SB_FALSE;
+ }
+ /* perform segmented programming of the data */
+ while (len > 0)
+ {
+ /* set the current read length to make optimal use of the available packet data. */
+ currentWriteCnt = len % (xcpMaxProgCto - 1);
+ if (currentWriteCnt == 0)
+ {
+ currentWriteCnt = (xcpMaxProgCto - 1);
+ }
+ /* prepare the packed data for the program command */
+ if (currentWriteCnt < (xcpMaxProgCto - 1))
+ {
+ /* program data */
+ if (XcpMasterSendCmdProgram(currentWriteCnt, &data[bufferOffset]) == SB_FALSE)
+ {
+ return SB_FALSE;
+ }
+ }
+ else
+ {
+ /* program max data */
+ if (XcpMasterSendCmdProgramMax(&data[bufferOffset]) == SB_FALSE)
+ {
+ return SB_FALSE;
+ }
+ }
+ /* update loop variables */
+ len -= currentWriteCnt;
+ bufferOffset += currentWriteCnt;
+ }
+ /* still here so all data successfully programmed */
+ return SB_TRUE;
+} /*** end of XcpMasterProgramData ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP Connect command.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+static sb_uint8 XcpMasterSendCmdConnect(void)
+{
+ sb_uint8 packetData[2];
+ tXcpTransportResponsePacket *responsePacketPtr;
+
+ /* prepare the command packet */
+ packetData[0] = XCP_MASTER_CMD_CONNECT;
+ packetData[1] = 0; /* normal mode */
+
+ /* send the packet */
+ if (XcpTransportSendPacket(packetData, 2, 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)
+ {
+ /* store slave's byte ordering information */
+ xcpSlaveIsIntel = SB_TRUE;
+ }
+ /* store max number of bytes the slave allows for master->slave packets. */
+ xcpMaxCto = responsePacketPtr->data[3];
+ xcpMaxProgCto = xcpMaxCto;
+ /* store max number of bytes the slave allows for slave->master packets. */
+ if (xcpSlaveIsIntel == SB_TRUE)
+ {
+ xcpMaxDto = responsePacketPtr->data[4] + (responsePacketPtr->data[5] << 8);
+ }
+ else
+ {
+ 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 */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdConnect ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP Set MTA command.
+** \param address New MTA address for the slave.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+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_T1_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;
+ }
+
+ /* still here so all went well */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdSetMta ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP UPLOAD command.
+** \param data Destination data buffer.
+** \param length Number of bytes to upload.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+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;
+
+ /* send the packet */
+ if (XcpTransportSendPacket(packetData, 2, XCP_MASTER_TIMEOUT_T1_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;
+ }
+
+ /* now store the uploaded data */
+ for (data_index=0; data_indexdata[data_index+1];
+ }
+
+ /* still here so all went well */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdUpload ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP PROGRAM START command.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+static sb_uint8 XcpMasterSendCmdProgramStart(void)
+{
+ sb_uint8 packetData[1];
+ tXcpTransportResponsePacket *responsePacketPtr;
+
+ /* prepare the command packet */
+ packetData[0] = XCP_MASTER_CMD_PROGRAM_START;
+
+ /* send the packet */
+ if (XcpTransportSendPacket(packetData, 1, XCP_MASTER_TIMEOUT_T3_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;
+ }
+
+ /* 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 */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdProgramStart ***/
+
+
+/************************************************************************************//**
+** \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.
+**
+****************************************************************************************/
+static sb_uint8 XcpMasterSendCmdProgramReset(void)
+{
+ sb_uint8 packetData[1];
+ tXcpTransportResponsePacket *responsePacketPtr;
+
+ /* prepare the command packet */
+ packetData[0] = XCP_MASTER_CMD_PROGRAM_RESET;
+
+ /* send the packet, assume the sending itself is ok and check if a response was
+ * received.
+ */
+ if (XcpTransportSendPacket(packetData, 1, XCP_MASTER_TIMEOUT_T5_MS) == SB_FALSE)
+ {
+ /* probably no response received within the specified timeout, but that is allowed
+ * for the reset command.
+ */
+ return SB_TRUE;
+ }
+ /* 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 */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdProgramReset ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP PROGRAM command.
+** \param length Number of bytes in the data array to program.
+** \param data Array with data bytes to program.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+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;
+ for (cnt=0; cntlen == 0) || (responsePacketPtr->data[0] != XCP_MASTER_CMD_PID_RES) )
+ {
+ /* not a valid or positive response */
+ return SB_FALSE;
+ }
+
+ /* still here so all went well */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdProgram ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP PROGRAM MAX command.
+** \param data Array with data bytes to program.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+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++)
+ {
+ packetData[cnt+1] = data[cnt];
+ }
+
+ /* send the packet */
+ if (XcpTransportSendPacket(packetData, xcpMaxProgCto, XCP_MASTER_TIMEOUT_T5_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;
+ }
+
+ /* still here so all went well */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdProgramMax ***/
+
+
+/************************************************************************************//**
+** \brief Sends the XCP PROGRAM CLEAR command.
+** \return SB_TRUE is successfull, SB_FALSE otherwise.
+**
+****************************************************************************************/
+static sb_uint8 XcpMasterSendCmdProgramClear(sb_uint32 length)
+{
+ sb_uint8 packetData[8];
+ tXcpTransportResponsePacket *responsePacketPtr;
+
+ /* prepare the command packet */
+ packetData[0] = XCP_MASTER_CMD_PROGRAM_CLEAR;
+ packetData[1] = 0; /* use absolute mode */
+ packetData[2] = 0; /* reserved */
+ packetData[3] = 0; /* reserved */
+
+ /* set the erase length taking into account byte ordering */
+ XcpMasterSetOrderedLong(length, &packetData[4]);
+
+
+ /* send the packet */
+ if (XcpTransportSendPacket(packetData, 8, XCP_MASTER_TIMEOUT_T4_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;
+ }
+
+ /* still here so all went well */
+ return SB_TRUE;
+} /*** end of XcpMasterSendCmdProgramClear ***/
+
+
+/************************************************************************************//**
+** \brief Stores a 32-bit value into a byte buffer taking into account Intel
+** or Motorola byte ordering.
+** \param value The 32-bit value to store in the buffer.
+** \param data Array to the buffer for storage.
+** \return none.
+**
+****************************************************************************************/
+static void XcpMasterSetOrderedLong(sb_uint32 value, sb_uint8 data[])
+{
+ if (xcpSlaveIsIntel == SB_TRUE)
+ {
+ data[3] = (sb_uint8)(value >> 24);
+ data[2] = (sb_uint8)(value >> 16);
+ data[1] = (sb_uint8)(value >> 8);
+ data[0] = (sb_uint8)value;
+ }
+ else
+ {
+ data[0] = (sb_uint8)(value >> 24);
+ data[1] = (sb_uint8)(value >> 16);
+ data[2] = (sb_uint8)(value >> 8);
+ data[3] = (sb_uint8)value;
+ }
+} /*** end of XcpMasterSetOrderedLong ***/
+
+
+/*********************************** end of xcpmaster.c ********************************/
diff --git a/Host/Source/SerialBoot/xcpmaster.h b/Host/Source/SerialBoot/xcpmaster.h
new file mode 100644
index 00000000..9447b540
--- /dev/null
+++ b/Host/Source/SerialBoot/xcpmaster.h
@@ -0,0 +1,71 @@
+/************************************************************************************//**
+* \file xcpmaster.h
+* \brief XCP Master header file.
+* \ingroup SerialBoot
+* \internal
+*----------------------------------------------------------------------------------------
+* C O P Y R I G H T
+*----------------------------------------------------------------------------------------
+* Copyright (c) 2014 by Feaser http://www.feaser.com All rights reserved
+*
+*----------------------------------------------------------------------------------------
+* L I C E N S E
+*----------------------------------------------------------------------------------------
+* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as published by the Free
+* Software Foundation, either version 3 of the License, or (at your option) any later
+* version.
+*
+* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+* PURPOSE. See the GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along with OpenBLT.
+* If not, see .
+*
+* 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 .
+*
+* \endinternal
+****************************************************************************************/
+#ifndef XCPMASTER_H
+#define XCPMASTER_H
+
+/****************************************************************************************
+* Macro definitions
+****************************************************************************************/
+/** \brief Configure number of bytes in the master->slave data packet. Should be at least
+ * equal or larger than that configured on the slave.
+ */
+#define XCP_MASTER_TX_MAX_DATA (255)
+
+/** \brief Configure number of bytes in the slave->master data packet. Should be at least
+ * equal or larger than that configured on the slave.
+ */
+#define XCP_MASTER_RX_MAX_DATA (255)
+
+
+/****************************************************************************************
+* Include files
+****************************************************************************************/
+#include "xcptransport.h" /* XCP transport layer */
+
+
+/****************************************************************************************
+* Function prototypes
+****************************************************************************************/
+sb_uint8 XcpMasterInit(sb_char *device, sb_uint32 baudrate);
+void XcpMasterDeinit(void);
+sb_uint8 XcpMasterConnect(void);
+sb_uint8 XcpMasterDisconnect(void);
+sb_uint8 XcpMasterStartProgrammingSession(void);
+sb_uint8 XcpMasterStopProgrammingSession(void);
+sb_uint8 XcpMasterClearMemory(sb_uint32 addr, sb_uint32 len);
+sb_uint8 XcpMasterReadData(sb_uint32 addr, sb_uint32 len, sb_uint8 data[]);
+sb_uint8 XcpMasterProgramData(sb_uint32 addr, sb_uint32 len, sb_uint8 data[]);
+
+
+#endif /* XCPMASTER_H */
+/*********************************** end of xcpmaster.h ********************************/