Statistics
| Branch: | Tag: | Revision:

amiro-blt / Host / Source / SerialBoot / main.c @ 2b9a14a2

History | View | Annotate | Download (32.8 KB)

1
/************************************************************************************//**
2
* \file         main.c
3
* \brief        SerialBoot command line demonstration program for OpenBLT.
4
* \ingroup      SerialBoot
5
* \internal
6
*----------------------------------------------------------------------------------------
7
*                          C O P Y R I G H T
8
*----------------------------------------------------------------------------------------
9
*   Copyright (c) 2014  by Feaser    http://www.feaser.com    All rights reserved
10
*
11
*----------------------------------------------------------------------------------------
12
*                            L I C E N S E
13
*----------------------------------------------------------------------------------------
14
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
15
* modify it under the terms of the GNU General Public License as published by the Free
16
* Software Foundation, either version 3 of the License, or (at your option) any later
17
* version.
18
*
19
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
20
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
21
* PURPOSE. See the GNU General Public License for more details.
22
*
23
* You should have received a copy of the GNU General Public License along with OpenBLT.
24
* If not, see <http://www.gnu.org/licenses/>.
25
*
26
* A special exception to the GPL is included to allow you to distribute a combined work
27
* that includes OpenBLT without being obliged to provide the source code for any
28
* proprietary components. The exception text is included at the bottom of the license
29
* file <license.html>.
30
*
31
* \endinternal
32
****************************************************************************************/
33

    
34

    
35
/****************************************************************************************
36
* Include files
37
****************************************************************************************/
38
#include <assert.h>                                   /* assertion module              */
39
#include <sb_types.h>                                 /* C types                       */
40
#include <stdio.h>                                    /* standard I/O library          */
41
#include <string.h>                                   /* string library                */
42
#include "xcpmaster.h"                                /* XCP master protocol module    */
43
#include "srecord.h"                                  /* S-record file handling        */
44
#include "timeutil.h"                                 /* time utility module           */
45
#include "stdlib.h"                                   /* ascii to integral conversion  */
46

    
47

    
48
/****************************************************************************************
49
* Function prototypes
50
****************************************************************************************/
51
static void     DisplayProgramInfo(void);
52
static void     DisplayProgramUsage(void);
53
static void     DisplayProgramInput(void);
54
static void     printErrors(void);
55
static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[]);
56
static sb_int32 startFlashMode(void);
57
static sb_int32 flashProgram(void);
58
static sb_int32 startUserProgram(void);
59
static sb_int32 originalMainPart(void);
60
static sb_int32 openSerialPort(void);
61
static sb_int32 openSerialPortConnect(sb_uint8 start);
62
static sb_int32 closeSerialPort(void);
63
static sb_int32 buildConnection(sb_uint8 start);
64
static sb_int32 closeConnection(sb_file *hSrecord);
65
static sb_int32 closeConnectionWithReset(sb_file *hSrecord);
66
static sb_int32 prepareProgrammingSession(sb_file *hSrecord, tSrecordParseResults *fileParseResults);
67
static sb_int32 programCode(sb_file *hSrecord, tSrecordParseResults *fileParseResults, tSrecordLineParseResults *lineParseResults);
68

    
69
/****************************************************************************************
70
* Macro definitions
71
****************************************************************************************/
72
/** \brief Program return code if all went ok. */
73
#define PROG_RESULT_OK    (0)
74

    
75
/** \brief Program return code if an error occurred. */
76
#define PROG_RESULT_ERROR (1)
77

    
78
/* mode definitions of the program status */
79
#define PROGSTATE_ORIGIN           0
80
#define PROGSTATE_STARTFLASHMODE   1
81
#define PROGSTATE_RESET            2
82
#define PROGSTATE_FLASHPROGRAM     3
83
#define PROGSTATE_SETFLAGS         4
84

    
85
/* error definitions */
86
#define ERROR_NO                   0
87
#define ERROR_FILE                 1
88
#define ERROR_DEVICE               2
89
#define ERROR_UNKNOWN              255
90

    
91
/* maximal space for flashing programs */
92
#define MAX_COUNT_FLASHING_PROGRAMS 5
93

    
94

    
95
/****************************************************************************************
96
* Local data declarations
97
****************************************************************************************/
98
/** \brief Name of the serial device, such as COM4, /dev/ttyUSB0 or /dev/ttyAMiRo0. */
99
static sb_char serialDeviceName[32];
100

    
101
/** \brief Id of the bluetooth device, such as 01:23:45:67:89:AB. */
102
static sb_char bluetoothID[18];
103

    
104
/** \brief Serial communication speed in bits per second. */
105
static sb_uint32 serialBaudrate;
106

    
107
/** \brief Name of the S-record file. */
108
static sb_char *srecordFileName;
109

    
110
/* program status */
111
static sb_uint8 prog_state = 1;
112

    
113
/* id of flashing target */
114
static sb_uint32 flashingTargetID = 0;
115

    
116
/* list of program names */
117
static sb_char *srecordFileNames[MAX_COUNT_FLASHING_PROGRAMS];
118

    
119
/* list of target ids */
120
static sb_uint32 flashingTargetIDs[MAX_COUNT_FLASHING_PROGRAMS];
121

    
122
/* list of errors */
123
static sb_uint8 errors[MAX_COUNT_FLASHING_PROGRAMS];
124

    
125
/* last error */
126
static sb_uint8 errorDetected = ERROR_NO;
127

    
128
/* program counter */
129
static sb_uint8 countFlashingPrograms = 0;
130

    
131
/* RTS register value */
132
static sb_uint8 registerRTSvalue = 0;
133

    
134
/* Type of communication is about UART, not Bluetooth */
135
static sb_uint8 comIsUart = SB_TRUE;
136

    
137

    
138
/************************************************************************************//**
139
** \brief     Program entry point.
140
** \param     argc Number of program parameters.
141
** \param     argv array to program parameter strings.
142
** \return    0 on success, > 0 on error.
143
**
144
****************************************************************************************/
145
sb_int32 main(sb_int32 argc, sb_char *argv[])
146
{
147
  /* disable buffering for the standard output to make sure printf does not wait until
148
   * a newline character is detected before outputting text on the console.
149
   */
150
  setbuf(stdout, SB_NULL);
151

    
152
  /* inform user about the program */
153
  DisplayProgramInfo();
154

    
155
  /* start out by making sure program was started with the correct parameters */
156
  if (ParseCommandLine(argc, argv) == SB_FALSE)
157
  {
158
    /* parameters invalid. inform user about how this program works */
159
    DisplayProgramUsage();
160
    return PROG_RESULT_ERROR;
161
  }
162

    
163
  DisplayProgramInput();
164

    
165
  if (openSerialPortConnect(0) == PROG_RESULT_ERROR) {
166
    return PROG_RESULT_ERROR;
167
  }
168

    
169
  /* initialize errors */
170
  sb_uint8 errorIdx;
171
  for (errorIdx=0; errorIdx<MAX_COUNT_FLASHING_PROGRAMS; errorIdx++) {
172
    errors[errorIdx] = ERROR_NO;
173
  }
174

    
175
  flashingTargetID = 0;
176
  if (startFlashMode() == PROG_RESULT_ERROR) {
177
    return PROG_RESULT_ERROR;
178
  }
179

    
180
  sb_uint8 flashIdx;
181
  for (flashIdx=0; flashIdx<countFlashingPrograms; flashIdx++) {
182
    errorDetected = ERROR_NO;
183
    flashingTargetID = flashingTargetIDs[flashIdx];
184
    srecordFileName = srecordFileNames[flashIdx];
185
    printf("\nFlash %i: Flashing %s on device 0x%08X\n\n", flashIdx+1, srecordFileName, flashingTargetID);
186

    
187
    if (flashProgram() == PROG_RESULT_ERROR) {
188
      closeSerialPort();
189
      openSerialPortConnect(0);
190
    }
191
    errors[flashIdx] = errorDetected;
192
  }
193

    
194
  flashingTargetID = 0;
195
  if (startUserProgram() == PROG_RESULT_ERROR) {
196
    return PROG_RESULT_ERROR;
197
  }
198

    
199
  printErrors();
200

    
201

    
202
  return PROG_RESULT_OK;
203
} /*** end of main ***/
204

    
205

    
206
/************************************************************************************//**
207
** \brief     Outputs information to the user about this program.
208
** \return    none.
209
**
210
****************************************************************************************/
211
static void DisplayProgramInfo(void)
212
{
213
  printf("---------------------------------------------------------------------------\n");
214
  printf("SerialBoot version 1.01. Performs firmware updates via the serial port     \n");
215
  printf("for a microcontroller based system that runs the OpenBLT bootloader.       \n");
216
  printf("                                                                           \n");
217
  printf("Copyright (c) by Feaser  http://www.feaser.com                             \n");
218
  printf("---------------------------------------------------------------------------\n");
219
  printf("This tool was modified for the 'Autonomous Mini Robot' - AMiRo.            \n");
220
  printf("Copyright (c) 2016..2019  Marvin Barther, Thomas Schoepping, and Stefan    \n");
221
  printf("                          Herbrechtsmeier                                  \n");
222
  printf("This is free software; see the source for copying conditions. There is NO  \n");
223
  printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
224
  printf("The development of this software was supported by the Excellence Cluster   \n");
225
  printf("EXC 227 Cognitive Interaction Technology. The Excellence Cluster EXC 227 is\n");
226
  printf("a grant of the Deutsche Forschungsgemeinschaft (DFG) in the context of the \n");
227
  printf("German Excellence Initiative.                                              \n");
228
  printf("---------------------------------------------------------------------------\n");
229
} /*** end of DisplayProgramInfo ***/
230

    
231

    
232
/************************************************************************************//**
233
** \brief     Outputs information to the user about how to use this program.
234
** \return    none.
235
**
236
****************************************************************************************/
237
static void DisplayProgramUsage(void)
238
{
239
  printf("Usage: SerialBoot -d<device> -b<baudrate> <s-record file>/(-T<flash-id> <s-record file>)\n\n");
240
  printf("Example 1:  SerialBoot -h\n");
241
#ifdef PLATFORM_WIN32
242
  printf("Example 2:  SerialBoot -dCOM4 -b57600 -T3 firmware.srec\n");
243
  printf("Example 3:  SerialBoot -dCOM4 -b57600 -T0 firm1.srec -T3 firm2.srec\n");
244
  printf("Example 4:  SerialBoot -dCOM4 -b57600 firmware.srec\n\n");
245
  printf("WARNING: SerialBoot is not really functional with windows! Please use\n");
246
  printf("         the Linux version.\n\n");
247
  printf("  -> In all four cases it connects to COM4.\n");
248
#else
249
  printf("Example 2:  SerialBoot -d/dev/ttyAMiRo0 -b57600 -T3 firmware.srec\n");
250
  printf("Example 3:  SerialBoot -d/dev/ttyAMiRo0 -b57600 -T0 firm1.srec -T3 firm2.srec\n");
251
  printf("Example 4:  SerialBoot -d/dev/ttyAMiRo0 -b57600 firmware.srec\n\n");
252
  printf("  -> In all four cases it connects to '/dev/ttyAMiRo0' alias '/dev/ttyUSB0'.\n");
253
#endif
254
  printf("  -> In all four cases a communication speed of 57600 bits/second is configured.\n");
255
  printf("     The bootloaders will be set into flashing mode and will be reset after\n");
256
  printf("     flashing the last binary file.\n");
257
  printf("  -> In the first example this help will be opened\n");
258
  printf("  -> In the second example the binary file 'firmware.srec' will be flashed on\n");
259
  printf("     device 0x03.\n");
260
  printf("  -> In the third example the binary file 'firm1.srec' will be flashed on\n");
261
  printf("     device 0x00 and the other binary file 'firm2.srec' on device 0x03.\n");
262
  printf("  -> In the last example the standard configuration is shown. The binary file\n");
263
  printf("     'firmware.srec' will be flashed on device 0x00. It equals the\n");
264
  printf("     configuration '-T0 firmware.srec'.\n");
265
  printf("  -> Don't forget that you always have to give the parameters -d and -b.\n");
266
  printf("  -> There is also the parameter -a for giving an address for bluetooth\n");
267
  printf("     communication, but this part is not functional yet.\n");
268
  printf("--------------------------------------------------------------------------------\n");
269
} /*** end of DisplayProgramUsage ***/
270

    
271

    
272

    
273
static void DisplayProgramInput(void) {
274
#ifdef PLATFORM_WIN32
275
  printf("WARNING: SerialBoot is designed for Linux. While using Windows the correct\n");
276
  printf("         functionality can not be guaranteed! Please use Linux for using best\n");
277
  printf("         performance and savety.\n");
278
  printf("\n--------------------------------------------------------------------------------\n\n");
279
#endif
280
  printf("\nOpen device at %s @ %u bits/s and RTS=%i\n\n", serialDeviceName, serialBaudrate, registerRTSvalue);
281
  printf("Programming will start immediately in following order:\n");
282
  sb_uint8 idx;
283
  for (idx=0; idx<countFlashingPrograms; idx++) {
284
    printf("  %i) device 0x%08X: %s\n", idx+1, flashingTargetIDs[idx], srecordFileNames[idx]);
285
  }
286
}
287

    
288

    
289
/************************************************************************************//**
290
** \brief     Parses the command line arguments. A fixed amount of arguments is expected.
291
**            The program should be called as:
292
**              SerialBoot -d[device] -b[baudrate] [s-record file]
293
** \param     argc Number of program parameters.
294
** \param     argv array to program parameter strings.
295
** \return    SB_TRUE on success, SB_FALSE otherwise.
296
**
297
****************************************************************************************/
298
static sb_uint8 ParseCommandLine(sb_int32 argc, sb_char *argv[])
299
{
300
  sb_uint8 paramIdx;
301
  sb_uint8 paramAfound = SB_FALSE;
302
  sb_uint8 paramDfound = SB_FALSE;
303
  sb_uint8 paramBfound = SB_FALSE;
304
  sb_uint8 paramTfound = SB_FALSE;
305
  sb_uint8 paramRTSfound = SB_FALSE;
306
  sb_uint8 paramXfound = SB_FALSE;
307
  sb_uint8 srecordfound = SB_FALSE;
308

    
309
  /* make sure the right amount of arguments are given */
310
  if (argc < 4 || argc > 14)
311
  {
312
    return SB_FALSE;
313
  }
314

    
315
  /* loop through all the command lina parameters, just skip the 1st one because this
316
   * is the name of the program, which we are not interested in.
317
   */
318
  for (paramIdx=1; paramIdx<argc; paramIdx++)
319
  {
320
    /* is this the device name? */
321
    if ( (argv[paramIdx][0] == '-') && (argv[paramIdx][1] == 'd') && (paramDfound == SB_FALSE) && (paramTfound == SB_FALSE) && (paramAfound == SB_FALSE))
322
    {
323
      /* copy the device name and set flag that this parameter was found */
324
      strcpy(serialDeviceName, &argv[paramIdx][2]);
325
      paramDfound = SB_TRUE;
326
      comIsUart = SB_TRUE;
327
    }
328
    /* is this the bluetooth id? */
329
/*
330
    else if ( (argv[paramIdx][0] == '-') && (argv[paramIdx][1] == 'a') && (paramDfound == SB_FALSE) && (paramTfound == SB_FALSE) && (paramAfound == SB_FALSE))
331
    {
332
      if ((argv[paramIdx][4] != ':') || (argv[paramIdx][7] != ':') || (argv[paramIdx][10] != ':') || (argv[paramIdx][13] != ':') || (argv[paramIdx][16] != ':')) {
333
        printf("The bluetooth ID %s has not the format xx:xx:xx:xx:xx:xx\n", &argv[paramIdx][2]);
334
        return SB_FALSE;
335
      }
336
      // copy the bluetooth id and set flag that this parameter was found
337
      strcpy(serialDeviceName, &argv[paramIdx][2]);
338
      paramAfound = SB_TRUE;
339
      comIsUart = SB_FALSE;
340
      // TODO accept bluetooth communication
341
      printf("Bluetooth communication is not available yet!");
342
      return SB_FALSE;
343
    }
344
*/
345
    /* is this the baudrate? */
346
    else if ( (argv[paramIdx][0] == '-') && (argv[paramIdx][1] == 'b') && (paramBfound == SB_FALSE) && (paramTfound == SB_FALSE) )
347
    {
348
      /* extract the baudrate and set flag that this parameter was found */
349
      sscanf(&argv[paramIdx][2], "%u", &serialBaudrate);
350
      paramBfound = SB_TRUE;
351
    }
352
    /* is this the RTS flag? */
353
    else if ( (argv[paramIdx][0] == '-') && (argv[paramIdx][1] == 'R') && (argv[paramIdx][2] == 'T') && (argv[paramIdx][3] == 'S') && (paramRTSfound == SB_FALSE) && (paramTfound == SB_FALSE) )
354
    {
355
      /* extract RTS flag [0,1] and set that this parameter was found */
356
      sb_char setValue[2];
357
      strcpy(setValue, &argv[paramIdx][4]);
358
      if (setValue[0] == 0x0) {
359
        registerRTSvalue = 0;
360
      } else {
361
        registerRTSvalue = ((int)setValue[0])-48;
362
      }
363
      if (registerRTSvalue > 1 || registerRTSvalue < 0 || setValue[1] != 0x0) {
364
        registerRTSvalue = 0;
365
        printf("Not allowed value for RTS register. RTS=[0,1]\n");
366
        return SB_FALSE;
367
      }
368
      paramRTSfound = SB_TRUE;
369
    }
370
    /* is this the target number? */
371
    else if ( (argv[paramIdx][0] == '-') && (argv[paramIdx][1] == 'T') && (paramTfound == SB_FALSE) && (paramXfound == SB_FALSE) && (paramDfound == SB_TRUE) && (paramBfound == SB_TRUE) )
372
    {
373
      if (countFlashingPrograms >= MAX_COUNT_FLASHING_PROGRAMS) {
374
        printf("too many programs to flash (-T)\n");
375
        return SB_FALSE;
376
      }
377
      /* prog status has to be set in flashing mode */
378
      paramTfound = SB_TRUE;
379
      prog_state = PROGSTATE_FLASHPROGRAM;
380
      sb_char choosenID[128];
381
      strcpy(choosenID, &argv[paramIdx][2]);
382
      /* Transform ascii numbers in string to an integer */
383
      flashingTargetID = 0;
384
      if (choosenID[0] == '0' && (choosenID[1] < '0' || choosenID[1] > '9')) {  // if the ID is something like "0x..." or "0o..."
385
        switch (choosenID[1]) {
386
          case 'x':
387
          case 'X':
388
            flashingTargetID = strtoul(&choosenID[2], NULL, 16);
389
            break;
390
          case 'o':
391
          case 'O':
392
            flashingTargetID = strtoul(&choosenID[2], NULL, 8);
393
            break;
394
          case 'b':
395
          case 'B':
396
            flashingTargetID = strtoul(&choosenID[2], NULL, 2);
397
            break;
398
          case 'd':
399
          case 'D':
400
            flashingTargetID = strtoul(&choosenID[2], NULL, 10);
401
            break;
402
          default:
403
            printf("could not interprete target ID\n");
404
            return SB_FALSE;
405
            break;
406
        }
407
      } else {
408
        flashingTargetID = strtoul(choosenID, NULL, 10);
409
      }
410
      if (flashingTargetID == 0) {
411
        printf("target ID invalid (0x%08X)\n", flashingTargetID);
412
        return SB_FALSE;
413
      }
414
      flashingTargetIDs[countFlashingPrograms] = flashingTargetID;
415
    }
416
    /* is this a srec file (a parameter without "-" in the beginning) */
417
    else if (argv[paramIdx][0] != '-')
418
    {
419
      if (countFlashingPrograms >= MAX_COUNT_FLASHING_PROGRAMS) {
420
        printf("too many programs to flash (without -T)\n");
421
        return SB_FALSE;
422
      }
423
      /* srecord file has been found */
424
      if (paramTfound == SB_FALSE) {
425
        paramTfound = SB_TRUE;
426
        flashingTargetIDs[countFlashingPrograms] = 0;
427
        prog_state = PROGSTATE_ORIGIN;
428
      }
429
      srecordFileNames[countFlashingPrograms] = &(argv[paramIdx][0]);
430
      countFlashingPrograms++;
431
      paramTfound = SB_FALSE;
432
      srecordfound = SB_TRUE;
433
    }
434
  }
435

    
436
  /* verify if all parameters were found */
437
  if ( ( ((paramDfound == SB_FALSE) || (paramBfound == SB_FALSE)) && (paramAfound == SB_FALSE)) || (srecordfound == SB_FALSE) )
438
  {
439
    printf("-a, -d, -b or srecord file missing, remember that you can only choose -a or -d\n");
440
    return SB_FALSE;
441
  }
442

    
443
  /* still here so the parsing was successful */
444
  return SB_TRUE;
445
} /*** end of ParseCommandLine ***/
446

    
447

    
448

    
449

    
450

    
451
static void printErrors(void) {
452
  sb_uint8 detected = 0;
453
  sb_uint8 errorIdx;
454
  for (errorIdx=0; errorIdx<MAX_COUNT_FLASHING_PROGRAMS; errorIdx++) {
455
    if (errors[errorIdx] != ERROR_NO) {
456
      detected++;
457
    }
458
  }
459
  if (detected == 0) {
460
    printf("\nEvery firmware successfully updated.\nSerialBoot finished without any errors.\n\n");
461
  } else {
462
    if (detected < countFlashingPrograms) {
463
      printf("\n%i ERRORs detected!\nOnly in the following %i cases SerialBoot updated the firmware:\n", detected, countFlashingPrograms-detected);
464
      for (errorIdx=0; errorIdx<countFlashingPrograms; errorIdx++) {
465
        if (errors[errorIdx] == ERROR_NO) {
466
          printf(" * Flash %i: %s on device 0x%08X\n", errorIdx+1, srecordFileNames[errorIdx], flashingTargetIDs[errorIdx]);
467
        }
468
      }
469
      printf("In the following %i cases SerialBoot could not update the firmware:\n", detected);
470
    } else {
471
      printf("\nERRORs detected!\nEvery firmware update by SerialBoot failed:\n");
472
    }
473
    for (errorIdx=0; errorIdx<countFlashingPrograms; errorIdx++) {
474
      if (errors[errorIdx] != ERROR_NO) {
475
        printf(" * ERROR in Flash %i: ", errorIdx+1);
476
        switch (errors[errorIdx]) {
477
          case ERROR_FILE:
478
            printf("The file %s couldn't be read!\n", srecordFileNames[errorIdx]); break;
479
          case ERROR_DEVICE:
480
            printf("No connection to device 0x%08X!\n", flashingTargetIDs[errorIdx]); break;
481
          default:
482
            printf("Couldn't specify the error. Please check output above!\n"); break;
483
        }
484
      }
485
    }
486
    printf("Please check the errors before trying to update again.\n\n");
487
  }
488
}
489

    
490

    
491

    
492

    
493

    
494
static sb_int32 startFlashMode(void) {
495

    
496
  /* -------------------- start flashing mode ---------------------------------------- */
497
  printf("Set main device on flashing mode\n");
498

    
499
  /* -------------------- open connection -------------------------------------------- */
500
  if (buildConnection(1) == PROG_RESULT_ERROR) {
501
    return PROG_RESULT_ERROR;
502
  }
503

    
504
  //printf("close...");
505

    
506
  /* -------------------- close connection ------------------------------------------- */
507
  if(closeConnection(NULL) == PROG_RESULT_ERROR) {
508
    return PROG_RESULT_ERROR;
509
  }
510

    
511
  /* all done */
512
  printf("Main device is now in flashing mode!\n\n");
513

    
514
  return PROG_RESULT_OK;
515
}
516

    
517

    
518

    
519
static sb_int32 flashProgram(void) {
520
  sb_file hSrecord;
521
  tSrecordParseResults fileParseResults;
522
  tSrecordLineParseResults lineParseResults;
523

    
524
  /* -------------------- start the firmware update procedure ------------------------ */
525
  printf("Starting firmware update for \"%s\" on device 0x%08X\n", srecordFileName, flashingTargetID);
526
  printf("Using %s @ %u bits/s\n", serialDeviceName, serialBaudrate);
527

    
528
  /* -------------------- prepare programming session -------------------------------- */
529
  if (prepareProgrammingSession(&hSrecord, &fileParseResults) == PROG_RESULT_ERROR) {
530
    errorDetected = ERROR_FILE;
531
    return PROG_RESULT_ERROR;
532
  }
533

    
534
  /* -------------------- open connection -------------------------------------------- */
535
  if (buildConnection(0) == PROG_RESULT_ERROR) {
536
    errorDetected = ERROR_DEVICE;
537
    return PROG_RESULT_ERROR;
538
  }
539

    
540
  /* -------------------- programming code ------------------------------------------- */
541
  if (programCode(&hSrecord, &fileParseResults, &lineParseResults) == PROG_RESULT_ERROR) {
542
    errorDetected = ERROR_UNKNOWN;
543
    return PROG_RESULT_ERROR;
544
  }
545

    
546
  /* -------------------- close connection ------------------------------------------- */
547
  if (closeConnection(&hSrecord) == PROG_RESULT_ERROR) {
548
    errorDetected = ERROR_UNKNOWN;
549
    return PROG_RESULT_ERROR;
550
  }
551

    
552
  /* -------------------- close the S-record file ------------------------------------ */
553
  SrecordClose(hSrecord);
554
  printf("Closed S-record file \"%s\"\n", srecordFileName);
555

    
556
  /* all done */
557
  printf("Firmware successfully updated!\n\n");
558

    
559
  return PROG_RESULT_OK;
560
}
561

    
562

    
563

    
564

    
565

    
566

    
567
static sb_int32 startUserProgram(void) {
568
  /* -------------------- start the user program ------------------------------------- */
569
  printf("Resetting all using %s @ %u bits/s\n", serialDeviceName, serialBaudrate);
570

    
571
  /* -------------------- open connection -------------------------------------------- */
572
  if (buildConnection(0) == PROG_RESULT_ERROR) {
573
    return PROG_RESULT_ERROR;
574
  }
575

    
576
  /* -------------------- close connection and reset --------------------------------- */
577
  if (closeConnectionWithReset(NULL) == PROG_RESULT_ERROR) {
578
    return PROG_RESULT_ERROR;
579
  }
580

    
581
  /* all done */
582
  printf("User programs have been started!\n\n");
583

    
584
  return PROG_RESULT_OK;
585
}
586

    
587

    
588

    
589

    
590
static sb_int32 originalMainPart(void) {
591
  sb_file hSrecord;
592
  tSrecordParseResults fileParseResults;
593
  tSrecordLineParseResults lineParseResults;
594

    
595
  /* -------------------- start the firmware update procedure ------------------------ */
596
  printf("Starting firmware update for \"%s\" using %s @ %u bits/s\n", srecordFileName, serialDeviceName, serialBaudrate);
597

    
598
  /* -------------------- prepare programming session -------------------------------- */
599
  if (prepareProgrammingSession(&hSrecord, &fileParseResults) == PROG_RESULT_ERROR) {
600
    return PROG_RESULT_ERROR;
601
  }
602

    
603
  /* -------------------- open serial port and open connection ----------------------- */
604
  if (openSerialPortConnect(0) == PROG_RESULT_ERROR) {
605
    return PROG_RESULT_ERROR;
606
  }
607

    
608
  /* -------------------- open connection -------------------------------------------- */
609
//  if (buildConnection(0) == PROG_RESULT_ERROR) {
610
//    return PROG_RESULT_ERROR;
611
//  }
612

    
613
  /* -------------------- programming code ------------------------------------------- */
614
  if (programCode(&hSrecord, &fileParseResults, &lineParseResults) == PROG_RESULT_ERROR) {
615
    return PROG_RESULT_ERROR;
616
  }
617

    
618
  /* -------------------- close connection and reset --------------------------------- */
619
  if (closeConnectionWithReset(&hSrecord) == PROG_RESULT_ERROR) {
620
    return PROG_RESULT_ERROR;
621
  }
622

    
623
  /* -------------------- close the S-record file ------------------------------------ */
624
  SrecordClose(hSrecord);
625
  printf("Closed S-record file \"%s\"\n", srecordFileName);
626

    
627
  /* all done */
628
  printf("Firmware successfully updated!\n\n");
629

    
630
  return PROG_RESULT_OK;
631
}
632

    
633

    
634

    
635

    
636

    
637
static sb_int32 openSerialPort(void) {
638
  /* -------------------- Open the serial port --------------------------------------- */
639
//  printf("Opening serial port %s...", serialDeviceName);
640
  if (XcpMasterInit(serialDeviceName, serialBaudrate, comIsUart) == SB_FALSE)
641
  {
642
    printf("ERROR\n");
643
    return PROG_RESULT_ERROR;
644
  }
645
//  printf("OK\n");
646
  return PROG_RESULT_OK;
647
}
648

    
649

    
650

    
651

    
652

    
653
static sb_int32 closeSerialPort(void) {
654
  /* -------------------- close the serial port -------------------------------------- */
655
  XcpMasterDeinit();
656
  return PROG_RESULT_OK;
657
}
658

    
659

    
660

    
661

    
662

    
663
static sb_int32 openSerialPortConnect(sb_uint8 start) {
664
  /* -------------------- Connect to XCP slave --------------------------------------- */
665
//  printf("Connecting to bootloader...");
666
  sb_uint8 connections = 0;
667
  if (XcpMasterInit(serialDeviceName, serialBaudrate, comIsUart) == SB_FALSE) {
668
    printf("Could not open serial port\n");
669
  } else {
670
    if (XcpMasterConnect(0) == SB_FALSE) {
671
      connections++;
672
      /* no response. prompt the user to reset the system */
673
      if (flashingTargetID == 0 && start > 0) {
674
        printf("Please connect main device to serial port %s...", serialDeviceName);
675
      } else  {
676
        printf("Try to connect to device...");
677
      }
678
    }
679
  }
680
  /* now keep retrying until we get a response */
681
  sb_uint16 timeoutIdx = 0;
682
  sb_uint16 timeoutEnd = 60;
683
  sb_uint8 noConnectionYet = SB_TRUE;
684
  while (noConnectionYet == SB_TRUE) {
685
    if (XcpMasterInit(serialDeviceName, serialBaudrate, comIsUart) == SB_FALSE) {
686
      if (timeoutIdx == timeoutEnd) {
687
        printf("\nTIMEOUT in building connection. Please start serial port of the main device ...");
688
      }
689
    } else {
690
      if (XcpMasterConnect(0) == SB_FALSE) {
691
        if (timeoutIdx == timeoutEnd) {
692
          printf("\nTIMEOUT in reset. Please reset the main device ...");
693
        }
694
      } else {
695
        noConnectionYet = SB_FALSE;
696
      }
697
    }
698
    /* delay a bit to not pump up the CPU load */
699
    TimeUtilDelayMs(20);
700
    timeoutIdx++;
701
  }
702
  if (connections > 0) {
703
    printf("OK\n");
704
  }
705

    
706
  return PROG_RESULT_OK;
707
}
708

    
709

    
710

    
711

    
712
static sb_int32 buildConnection(sb_uint8 start) {
713
  /* -------------------- Connect to XCP slave --------------------------------------- */
714
//  printf("Connecting to bootloader...");
715
  sb_uint8 connections = 0;
716
  if (XcpMasterConnect(flashingTargetID) == SB_FALSE) {
717
    connections++;
718
    /* no response. prompt the user to reset the system */
719
    if (flashingTargetID == 0 && start > 0) {
720
      printf("Please connect main device to serial port %s...", serialDeviceName);
721
    } else if (flashingTargetID == 0) {
722
      printf("Try to connect to device...");
723
    } else {
724
      printf("Try to connect to device 0x%08X...", flashingTargetID);
725
    }
726
  }
727
  /* now keep retrying until we get a response */
728
  sb_uint16 timeoutIdx = 0;
729
  sb_uint16 timeoutEnd = 50;
730
  while (XcpMasterConnect(flashingTargetID) == SB_FALSE) {
731
    if (timeoutIdx == timeoutEnd) {
732
      printf("\nTIMEOUT: No connection possible.\n\n");
733
      return PROG_RESULT_ERROR;
734
    }
735
    /* delay a bit to not pump up the CPU load */
736
    TimeUtilDelayMs(20);
737
    timeoutIdx++;
738
  }
739
  if (connections > 0) {
740
    printf("OK\n");
741
  }
742

    
743
  return PROG_RESULT_OK;
744
}
745

    
746

    
747

    
748

    
749
static sb_int32 closeConnection(sb_file *hSrecord) {
750
  /* -------------------- Disconnect from XCP slave and perform software reset ------- */
751
//  printf("Performing software reset...");
752
  if (XcpMasterDisconnect() == SB_FALSE)
753
  {
754
    printf("ERROR\n");
755
    if (hSrecord != NULL) {
756
      SrecordClose(*hSrecord);
757
    }
758
    return PROG_RESULT_ERROR;
759
  }
760
//  printf("OK\n");
761

    
762
  return PROG_RESULT_OK;
763
}
764

    
765

    
766

    
767

    
768
static sb_int32 closeConnectionWithReset(sb_file *hSrecord) {
769
  /* -------------------- Disconnect from XCP slave ---------------------------------- */
770
  printf("Resetting...");
771
  if (XcpMasterProgramReset() == SB_FALSE)
772
  {
773
    printf("ERROR\n");
774
    XcpMasterDisconnect();
775
    if (hSrecord != NULL) {
776
      SrecordClose(*hSrecord);
777
    }
778
    return PROG_RESULT_ERROR;
779
  }
780
  printf("OK\n");
781

    
782
  closeSerialPort();
783
  printf("Closed serial port %s\n", serialDeviceName);
784

    
785
  return PROG_RESULT_OK;
786
}
787

    
788

    
789

    
790

    
791
static sb_int32 prepareProgrammingSession(sb_file *hSrecord, tSrecordParseResults *fileParseResults) {
792
  /* -------------------- validating the S-record file ------------------------------- */
793
  printf("Checking formatting of S-record file \"%s\"...", srecordFileName);
794
  if (SrecordIsValid(srecordFileName) == SB_FALSE)
795
  {
796
    printf("ERROR\n\n");
797
    return PROG_RESULT_ERROR;
798
  }
799
  printf("OK\n");
800

    
801
  /* -------------------- opening the S-record file ---------------------------------- */
802
  printf("Opening S-record file \"%s\"...", srecordFileName);
803
  if ((*hSrecord = SrecordOpen(srecordFileName)) == SB_NULL)
804
  {
805
    printf("ERROR\n\n");
806
    return PROG_RESULT_ERROR;
807
  }
808
  printf("OK\n");
809

    
810
  /* -------------------- parsing the S-record file ---------------------------------- */
811
  printf("Parsing S-record file \"%s\"...", srecordFileName);
812
  SrecordParse(*hSrecord, fileParseResults);
813
  printf("OK\n");
814
  printf("-> Lowest memory address:  0x%08x\n", fileParseResults->address_low);
815
  printf("-> Highest memory address: 0x%08x\n", fileParseResults->address_high);
816
  printf("-> Total data bytes: %u\n", fileParseResults->data_bytes_total);
817

    
818
  return PROG_RESULT_OK;
819
}
820

    
821

    
822

    
823

    
824
static sb_int32 programCode(sb_file *hSrecord, tSrecordParseResults *fileParseResults, tSrecordLineParseResults *lineParseResults) {
825
  /* -------------------- Prepare the programming session ---------------------------- */
826
  printf("Initializing programming session...");
827
  if (XcpMasterStartProgrammingSession() == SB_FALSE)
828
  {
829
    printf("ERROR\n");
830
    XcpMasterDisconnect();
831
    SrecordClose(*hSrecord);
832
    return PROG_RESULT_ERROR;
833
  }
834
  printf("OK\n");
835

    
836
  /* -------------------- Erase memory ----------------------------------------------- */
837
  printf("Erasing %u bytes starting at 0x%08x...", fileParseResults->data_bytes_total, fileParseResults->address_low);
838
  if (XcpMasterClearMemory(fileParseResults->address_low, (fileParseResults->address_high - fileParseResults->address_low)) == SB_FALSE)
839
  {
840
    printf("ERROR\n");
841
    XcpMasterDisconnect();
842
    SrecordClose(*hSrecord);
843
    return PROG_RESULT_ERROR;
844
  }
845
  printf("OK\n");
846

    
847
  /* -------------------- Program data ----------------------------------------------- */
848
  printf("Programming data. Please wait...");
849
  /* loop through all S-records with program data */
850
  while (SrecordParseNextDataLine(*hSrecord, lineParseResults) == SB_TRUE)
851
  {
852
    if (XcpMasterProgramData(lineParseResults->address, lineParseResults->length, lineParseResults->data) == SB_FALSE)
853
    {
854
      printf("ERROR\n");
855
      XcpMasterDisconnect();
856
      SrecordClose(*hSrecord);
857
      return PROG_RESULT_ERROR;
858
    }
859
  }
860
  printf("OK\n");
861

    
862
  /* -------------------- Stop the programming session ------------------------------- */
863
  printf("Finishing programming session...");
864
  if (XcpMasterStopProgrammingSession() == SB_FALSE)
865
  {
866
    printf("ERROR\n");
867
    XcpMasterDisconnect();
868
    SrecordClose(*hSrecord);
869
    return PROG_RESULT_ERROR;
870
  }
871
  printf("OK\n");
872

    
873
  return PROG_RESULT_OK;
874
}
875

    
876

    
877

    
878
/*********************************** end of main.c *************************************/