From d07c3d783a48ee8ecb263b315670a568a0436b3f Mon Sep 17 00:00:00 2001 From: Frank Voorburg Date: Fri, 23 May 2014 09:32:19 +0000 Subject: [PATCH] Added SerialBoot, a command line program written in C for both Windows and Linux to perform firmware updates through the PC's serial port using the OpenBLT bootloader. git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@84 5dc33758-31d5-4daf-9ae8-b24bf3d40d73 --- Host/SerialBoot.exe | Bin 0 -> 45056 bytes Host/Source/SerialBoot/CMakeLists.txt | 70 ++ Host/Source/SerialBoot/main.c | 335 +++++++++ Host/Source/SerialBoot/port/linux/timeutil.c | 74 ++ .../SerialBoot/port/linux/xcptransport.c | 299 ++++++++ Host/Source/SerialBoot/port/timeutil.h | 44 ++ Host/Source/SerialBoot/port/win32/timeutil.c | 65 ++ .../SerialBoot/port/win32/xcptransport.c | 262 +++++++ Host/Source/SerialBoot/port/xcptransport.h | 56 ++ Host/Source/SerialBoot/sb_types.h | 70 ++ Host/Source/SerialBoot/srecord.c | 453 ++++++++++++ Host/Source/SerialBoot/srecord.h | 80 ++ Host/Source/SerialBoot/xcpmaster.c | 694 ++++++++++++++++++ Host/Source/SerialBoot/xcpmaster.h | 71 ++ 14 files changed, 2573 insertions(+) create mode 100644 Host/SerialBoot.exe create mode 100644 Host/Source/SerialBoot/CMakeLists.txt create mode 100644 Host/Source/SerialBoot/main.c create mode 100644 Host/Source/SerialBoot/port/linux/timeutil.c create mode 100644 Host/Source/SerialBoot/port/linux/xcptransport.c create mode 100644 Host/Source/SerialBoot/port/timeutil.h create mode 100644 Host/Source/SerialBoot/port/win32/timeutil.c create mode 100644 Host/Source/SerialBoot/port/win32/xcptransport.c create mode 100644 Host/Source/SerialBoot/port/xcptransport.h create mode 100644 Host/Source/SerialBoot/sb_types.h create mode 100644 Host/Source/SerialBoot/srecord.c create mode 100644 Host/Source/SerialBoot/srecord.h create mode 100644 Host/Source/SerialBoot/xcpmaster.c create mode 100644 Host/Source/SerialBoot/xcpmaster.h diff --git a/Host/SerialBoot.exe b/Host/SerialBoot.exe new file mode 100644 index 0000000000000000000000000000000000000000..013dd2476bd258d65b997378f5372f26e705f49e GIT binary patch literal 45056 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 literal 0 HcmV?d00001 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 ********************************/