Statistics
| Branch: | Tag: | Revision:

amiro-blt / Host / Source / SerialBoot / main.c @ 2654b32c

History | View | Annotate | Download (32.075 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

    
46

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

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

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

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

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

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

    
93

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

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

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

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

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

    
112
/* id of flashing target */
113
static sb_uint8 flashingTargetID = 0;
114

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

    
118
/* list of target ids */
119
static sb_uint8 flashingTargetIDs[MAX_COUNT_FLASHING_PROGRAMS];
120

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

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

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

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

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

    
136

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

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

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

    
162
  DisplayProgramInput();
163

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

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

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

    
179
  sb_uint8 flashIdx;
180
  for (flashIdx=0; flashIdx<countFlashingPrograms; flashIdx++) {
181
    errorDetected = ERROR_NO;
182
    flashingTargetID = flashingTargetIDs[flashIdx];
183
    srecordFileName = srecordFileNames[flashIdx];
184
    printf("\nFlash %i: Flashing %s on device %i\n\n", flashIdx+1, srecordFileName, flashingTargetID);
185
    if (flashProgram() == PROG_RESULT_ERROR) {
186
      closeSerialPort();
187
      openSerialPortConnect(0);
188
    }
189
    errors[flashIdx] = errorDetected;
190
  }
191

    
192
  flashingTargetID = 0;
193
  if (startUserProgram() == PROG_RESULT_ERROR) {
194
    return PROG_RESULT_ERROR;
195
  }
196

    
197
  printErrors();
198

    
199

    
200
  return PROG_RESULT_OK;
201
} /*** end of main ***/
202

    
203

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

    
228

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

    
267

    
268

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

    
284

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

    
305
  /* make sure the right amount of arguments are given */
306
  if (argc < 4 || argc > 14)
307
  {
308
    return SB_FALSE;
309
  }
310

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

    
424
  /* still here so the parsing was successful */
425
  return SB_TRUE;
426
} /*** end of ParseCommandLine ***/
427

    
428

    
429

    
430

    
431

    
432
static void printErrors(void) {
433
  sb_uint8 detected = 0;
434
  sb_uint8 errorIdx;
435
  for (errorIdx=0; errorIdx<MAX_COUNT_FLASHING_PROGRAMS; errorIdx++) {
436
    if (errors[errorIdx] != ERROR_NO) {
437
      detected++;
438
    }
439
  }
440
  if (detected == 0) {
441
    printf("\nEvery firmware successfully updated.\nSerialBoot finished without any errors.\n\n");
442
  } else {
443
    if (detected < countFlashingPrograms) {
444
      printf("\n%i ERRORs detected!\nOnly in the following %i cases SerialBoot updated the firmware:\n", detected, countFlashingPrograms-detected);
445
      for (errorIdx=0; errorIdx<countFlashingPrograms; errorIdx++) {
446
        if (errors[errorIdx] == ERROR_NO) {
447
          printf(" * Flash %i: %s on device %i\n", errorIdx+1, srecordFileNames[errorIdx], flashingTargetIDs[errorIdx]);
448
        }
449
      }
450
      printf("In the following %i cases SerialBoot could not update the firmware:\n", detected);
451
    } else {
452
      printf("\nERRORs detected!\nEvery firmware update by SerialBoot failed:\n");
453
    }
454
    for (errorIdx=0; errorIdx<countFlashingPrograms; errorIdx++) {
455
      if (errors[errorIdx] != ERROR_NO) {
456
        printf(" * ERROR in Flash %i: ", errorIdx+1);
457
        switch (errors[errorIdx]) {
458
          case ERROR_FILE:
459
            printf("The file %s couldn't be read!\n", srecordFileNames[errorIdx]); break;
460
          case ERROR_DEVICE:
461
            printf("No connection to device %i!\n", flashingTargetIDs[errorIdx]); break;
462
          default:
463
            printf("Couldn't specify the error. Please check output above!\n"); break;
464
        }
465
      }
466
    }
467
    printf("Please check the errors before trying to update again.\n\n");
468
  }
469
}
470

    
471

    
472

    
473

    
474

    
475
static sb_int32 startFlashMode(void) {
476

    
477
  /* -------------------- start flashing mode ---------------------------------------- */
478
  printf("Set main device on flashing mode\n");
479

    
480
  /* -------------------- open connection -------------------------------------------- */
481
  if (buildConnection(1) == PROG_RESULT_ERROR) {
482
    return PROG_RESULT_ERROR;
483
  }
484

    
485
  //printf("close...");
486

    
487
  /* -------------------- close connection ------------------------------------------- */
488
  if(closeConnection(NULL) == PROG_RESULT_ERROR) {
489
    return PROG_RESULT_ERROR;
490
  }
491

    
492
  /* all done */
493
  printf("Main device is now in flashing mode!\n\n");
494

    
495
  return PROG_RESULT_OK;
496
}
497

    
498

    
499

    
500
static sb_int32 flashProgram(void) {
501
  sb_file hSrecord;
502
  tSrecordParseResults fileParseResults;
503
  tSrecordLineParseResults lineParseResults;
504

    
505
  /* -------------------- start the firmware update procedure ------------------------ */
506
  printf("Starting firmware update for \"%s\" on device %i (0x", srecordFileName, flashingTargetID);
507
  if (flashingTargetID < 16)
508
  {
509
    printf("0");
510
  }
511
  printf("%X)\nUsing %s @ %u bits/s\n", flashingTargetID, serialDeviceName, serialBaudrate);
512

    
513
  /* -------------------- prepare programming session -------------------------------- */
514
  if (prepareProgrammingSession(&hSrecord, &fileParseResults) == PROG_RESULT_ERROR) {
515
    errorDetected = ERROR_FILE;
516
    return PROG_RESULT_ERROR;
517
  }
518

    
519
  /* -------------------- open connection -------------------------------------------- */
520
  if (buildConnection(0) == PROG_RESULT_ERROR) {
521
    errorDetected = ERROR_DEVICE;
522
    return PROG_RESULT_ERROR;
523
  }
524

    
525
  /* -------------------- programming code ------------------------------------------- */
526
  if (programCode(&hSrecord, &fileParseResults, &lineParseResults) == PROG_RESULT_ERROR) {
527
    errorDetected = ERROR_UNKNOWN;
528
    return PROG_RESULT_ERROR;
529
  }
530

    
531
  /* -------------------- close connection ------------------------------------------- */
532
  if (closeConnection(&hSrecord) == PROG_RESULT_ERROR) {
533
    errorDetected = ERROR_UNKNOWN;
534
    return PROG_RESULT_ERROR;
535
  }
536

    
537
  /* -------------------- close the S-record file ------------------------------------ */
538
  SrecordClose(hSrecord);
539
  printf("Closed S-record file \"%s\"\n", srecordFileName);
540

    
541
  /* all done */
542
  printf("Firmware successfully updated!\n\n");
543

    
544
  return PROG_RESULT_OK;
545
}
546

    
547

    
548

    
549

    
550

    
551

    
552
static sb_int32 startUserProgram(void) {
553
  /* -------------------- start the user program ------------------------------------- */
554
  printf("Resetting all using %s @ %u bits/s\n", serialDeviceName, serialBaudrate);
555

    
556
  /* -------------------- open connection -------------------------------------------- */
557
  if (buildConnection(0) == PROG_RESULT_ERROR) {
558
    return PROG_RESULT_ERROR;
559
  }
560

    
561
  /* -------------------- close connection and reset --------------------------------- */
562
  if (closeConnectionWithReset(NULL) == PROG_RESULT_ERROR) {
563
    return PROG_RESULT_ERROR;
564
  }
565

    
566
  /* all done */
567
  printf("User programs have been started!\n\n");
568

    
569
  return PROG_RESULT_OK;
570
}
571

    
572

    
573

    
574

    
575
static sb_int32 originalMainPart(void) {
576
  sb_file hSrecord;
577
  tSrecordParseResults fileParseResults;
578
  tSrecordLineParseResults lineParseResults;
579

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

    
583
  /* -------------------- prepare programming session -------------------------------- */
584
  if (prepareProgrammingSession(&hSrecord, &fileParseResults) == PROG_RESULT_ERROR) {
585
    return PROG_RESULT_ERROR;
586
  }
587

    
588
  /* -------------------- open serial port and open connection ----------------------- */
589
  if (openSerialPortConnect(0) == PROG_RESULT_ERROR) {
590
    return PROG_RESULT_ERROR;
591
  }
592

    
593
  /* -------------------- open connection -------------------------------------------- */
594
//  if (buildConnection(0) == PROG_RESULT_ERROR) {
595
//    return PROG_RESULT_ERROR;
596
//  }
597

    
598
  /* -------------------- programming code ------------------------------------------- */
599
  if (programCode(&hSrecord, &fileParseResults, &lineParseResults) == PROG_RESULT_ERROR) {
600
    return PROG_RESULT_ERROR;
601
  }
602

    
603
  /* -------------------- close connection and reset --------------------------------- */
604
  if (closeConnectionWithReset(&hSrecord) == PROG_RESULT_ERROR) {
605
    return PROG_RESULT_ERROR;
606
  }
607

    
608
  /* -------------------- close the S-record file ------------------------------------ */
609
  SrecordClose(hSrecord);
610
  printf("Closed S-record file \"%s\"\n", srecordFileName);
611

    
612
  /* all done */
613
  printf("Firmware successfully updated!\n\n");
614

    
615
  return PROG_RESULT_OK;
616
}
617

    
618

    
619

    
620

    
621

    
622
static sb_int32 openSerialPort(void) {
623
  /* -------------------- Open the serial port --------------------------------------- */
624
//  printf("Opening serial port %s...", serialDeviceName);
625
  if (XcpMasterInit(serialDeviceName, serialBaudrate, comIsUart) == SB_FALSE)
626
  {
627
    printf("ERROR\n");
628
    return PROG_RESULT_ERROR;
629
  }
630
//  printf("OK\n");
631
  return PROG_RESULT_OK;
632
}
633

    
634

    
635

    
636

    
637

    
638
static sb_int32 closeSerialPort(void) {
639
  /* -------------------- close the serial port -------------------------------------- */
640
  XcpMasterDeinit();
641
  return PROG_RESULT_OK;
642
}
643

    
644

    
645

    
646

    
647

    
648
static sb_int32 openSerialPortConnect(sb_uint8 start) {
649
  /* -------------------- Connect to XCP slave --------------------------------------- */
650
//  printf("Connecting to bootloader...");
651
  sb_uint8 connections = 0;
652
  if (XcpMasterInit(serialDeviceName, serialBaudrate, comIsUart) == SB_FALSE) {
653
    printf("Could not open serial port\n");
654
  } else {
655
    if (XcpMasterConnect(0) == SB_FALSE) {
656
      connections++;
657
      /* no response. prompt the user to reset the system */
658
      if (flashingTargetID == 0 && start > 0) {
659
        printf("Please connect main device to serial port %s...", serialDeviceName);
660
      } else  {
661
        printf("Try to connect to device...");
662
      }
663
    }
664
  }
665
  /* now keep retrying until we get a response */
666
  sb_uint16 timeoutIdx = 0;
667
  sb_uint16 timeoutEnd = 60;
668
  sb_uint8 noConnectionYet = SB_TRUE;
669
  while (noConnectionYet == SB_TRUE) {
670
    if (XcpMasterInit(serialDeviceName, serialBaudrate, comIsUart) == SB_FALSE) {
671
      if (timeoutIdx == timeoutEnd) {
672
        printf("\nTIMEOUT in building connection. Please start serial port of the main device ...");
673
      }
674
    } else {
675
      if (XcpMasterConnect(0) == SB_FALSE) {
676
        if (timeoutIdx == timeoutEnd) {
677
          printf("\nTIMEOUT in reset. Please reset the main device ...");
678
        }
679
      } else {
680
        noConnectionYet = SB_FALSE;
681
      }
682
    }
683
    /* delay a bit to not pump up the CPU load */
684
    TimeUtilDelayMs(20);
685
    timeoutIdx++;
686
  }
687
  if (connections > 0) {
688
    printf("OK\n");
689
  }
690

    
691
  return PROG_RESULT_OK;
692
}
693

    
694

    
695

    
696

    
697
static sb_int32 buildConnection(sb_uint8 start) {
698
  /* -------------------- Connect to XCP slave --------------------------------------- */
699
//  printf("Connecting to bootloader...");
700
  sb_uint8 connections = 0;
701
  if (XcpMasterConnect(flashingTargetID) == SB_FALSE) {
702
    connections++;
703
    /* no response. prompt the user to reset the system */
704
    if (flashingTargetID == 0 && start > 0) {
705
      printf("Please connect main device to serial port %s...", serialDeviceName);
706
    } else if (flashingTargetID == 0) {
707
      printf("Try to connect to device...");
708
    } else {
709
      printf("Try to connect to device 0x");
710
      if (flashingTargetID < 16) {
711
        printf("0");
712
      }
713
      printf("%X...", flashingTargetID);
714
    }
715
  }
716
  /* now keep retrying until we get a response */
717
  sb_uint16 timeoutIdx = 0;
718
  sb_uint16 timeoutEnd = 50;
719
  while (XcpMasterConnect(flashingTargetID) == SB_FALSE) {
720
    if (timeoutIdx == timeoutEnd) {
721
      printf("\nTIMEOUT: No connection possible.\n\n");
722
      return PROG_RESULT_ERROR;
723
    }
724
    /* delay a bit to not pump up the CPU load */
725
    TimeUtilDelayMs(20);
726
    timeoutIdx++;
727
  }
728
  if (connections > 0) {
729
    printf("OK\n");
730
  }
731

    
732
  return PROG_RESULT_OK;
733
}
734

    
735

    
736

    
737

    
738
static sb_int32 closeConnection(sb_file *hSrecord) {
739
  /* -------------------- Disconnect from XCP slave and perform software reset ------- */
740
//  printf("Performing software reset...");
741
  if (XcpMasterDisconnect() == SB_FALSE)
742
  {
743
    printf("ERROR\n");
744
    if (hSrecord != NULL) {
745
      SrecordClose(*hSrecord);
746
    }
747
    return PROG_RESULT_ERROR;
748
  }
749
//  printf("OK\n");
750

    
751
  return PROG_RESULT_OK;
752
}
753

    
754

    
755

    
756

    
757
static sb_int32 closeConnectionWithReset(sb_file *hSrecord) {
758
  /* -------------------- Disconnect from XCP slave ---------------------------------- */
759
  printf("Resetting...");
760
  if (XcpMasterProgramReset() == SB_FALSE)
761
  {
762
    printf("ERROR\n");
763
    XcpMasterDisconnect();
764
    if (hSrecord != NULL) {
765
      SrecordClose(*hSrecord);
766
    }
767
    return PROG_RESULT_ERROR;
768
  }
769
  printf("OK\n");
770

    
771
  closeSerialPort();
772
  printf("Closed serial port %s\n", serialDeviceName);
773

    
774
  return PROG_RESULT_OK;
775
}
776

    
777

    
778

    
779

    
780
static sb_int32 prepareProgrammingSession(sb_file *hSrecord, tSrecordParseResults *fileParseResults) {
781
  /* -------------------- validating the S-record file ------------------------------- */
782
  printf("Checking formatting of S-record file \"%s\"...", srecordFileName);
783
  if (SrecordIsValid(srecordFileName) == SB_FALSE)
784
  {
785
    printf("ERROR\n\n");
786
    return PROG_RESULT_ERROR;
787
  }
788
  printf("OK\n");
789

    
790
  /* -------------------- opening the S-record file ---------------------------------- */
791
  printf("Opening S-record file \"%s\"...", srecordFileName);
792
  if ((*hSrecord = SrecordOpen(srecordFileName)) == SB_NULL)
793
  {
794
    printf("ERROR\n\n");
795
    return PROG_RESULT_ERROR;
796
  }
797
  printf("OK\n");
798

    
799
  /* -------------------- parsing the S-record file ---------------------------------- */
800
  printf("Parsing S-record file \"%s\"...", srecordFileName);
801
  SrecordParse(*hSrecord, fileParseResults);
802
  printf("OK\n");
803
  printf("-> Lowest memory address:  0x%08x\n", fileParseResults->address_low);
804
  printf("-> Highest memory address: 0x%08x\n", fileParseResults->address_high);
805
  printf("-> Total data bytes: %u\n", fileParseResults->data_bytes_total);
806

    
807
  return PROG_RESULT_OK;
808
}
809

    
810

    
811

    
812

    
813
static sb_int32 programCode(sb_file *hSrecord, tSrecordParseResults *fileParseResults, tSrecordLineParseResults *lineParseResults) {
814
  /* -------------------- Prepare the programming session ---------------------------- */
815
  printf("Initializing programming session...");
816
  if (XcpMasterStartProgrammingSession() == SB_FALSE)
817
  {
818
    printf("ERROR\n");
819
    XcpMasterDisconnect();
820
    SrecordClose(*hSrecord);
821
    return PROG_RESULT_ERROR;
822
  }
823
  printf("OK\n");
824

    
825
  /* -------------------- Erase memory ----------------------------------------------- */
826
  printf("Erasing %u bytes starting at 0x%08x...", fileParseResults->data_bytes_total, fileParseResults->address_low);
827
  if (XcpMasterClearMemory(fileParseResults->address_low, (fileParseResults->address_high - fileParseResults->address_low)) == SB_FALSE)
828
  {
829
    printf("ERROR\n");
830
    XcpMasterDisconnect();
831
    SrecordClose(*hSrecord);
832
    return PROG_RESULT_ERROR;
833
  }
834
  printf("OK\n");
835

    
836
  /* -------------------- Program data ----------------------------------------------- */
837
  printf("Programming data. Please wait...");
838
  /* loop through all S-records with program data */
839
  while (SrecordParseNextDataLine(*hSrecord, lineParseResults) == SB_TRUE)
840
  {
841
    if (XcpMasterProgramData(lineParseResults->address, lineParseResults->length, lineParseResults->data) == SB_FALSE)
842
    {
843
      printf("ERROR\n");
844
      XcpMasterDisconnect();
845
      SrecordClose(*hSrecord);
846
      return PROG_RESULT_ERROR;
847
    }
848
  }
849
  printf("OK\n");
850

    
851
  /* -------------------- Stop the programming session ------------------------------- */
852
  printf("Finishing programming session...");
853
  if (XcpMasterStopProgrammingSession() == SB_FALSE)
854
  {
855
    printf("ERROR\n");
856
    XcpMasterDisconnect();
857
    SrecordClose(*hSrecord);
858
    return PROG_RESULT_ERROR;
859
  }
860
  printf("OK\n");
861

    
862
  return PROG_RESULT_OK;
863
}
864

    
865

    
866

    
867
/*********************************** end of main.c *************************************/