/************************************************************************************//** * \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 have received a copy of the GNU General Public License along with OpenBLT. It * should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. * * \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