Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Source / xcp.c @ f7d2c786

History | View | Annotate | Download (52.4 KB)

1
/************************************************************************************//**
2
* \file         Source\xcp.c
3
* \brief        XCP 1.0 protocol core source file.
4
* \ingroup      Core
5
* \internal
6
*----------------------------------------------------------------------------------------
7
*                          C O P Y R I G H T
8
*----------------------------------------------------------------------------------------
9
*   Copyright (c) 2011  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
* Include files
36
****************************************************************************************/
37
#include "boot.h"                                /* bootloader generic header          */
38

    
39
#include <helper.h>
40

    
41
/****************************************************************************************
42
* Defines
43
****************************************************************************************/
44
/** \brief XCP protocol layer version number (16-bit). */
45
#define XCP_VERSION_PROTOCOL_LAYER  (0x0100)
46

    
47
/** \brief XCP transport layer version number (16-bit). */
48
#define XCP_VERSION_TRANSPORT_LAYER (0x0100)
49

    
50
/* XCP packet identifiers */
51
/** \brief Command response packet identifier. */
52
#define XCP_PID_RES                 (0xff)
53
/** \brief Error packet identifier. */
54
#define XCP_PID_ERR                 (0xfe)
55

    
56
/* XCP error codes */
57
/** \brief Cmd processor synchronization error code. */
58
#define XCP_ERR_CMD_SYNCH           (0x00)
59
/** \brief Command was not executed error code. */
60
#define XCP_ERR_CMD_BUSY            (0x10)
61
/** \brief Unknown or unsupported command error code. */
62
#define XCP_ERR_CMD_UNKNOWN         (0x20)
63
/** \brief Parameter out of range error code. */
64
#define XCP_ERR_OUT_OF_RANGE        (0x22)
65
/** \brief Protected error code. Seed/key required. */
66
#define XCP_ERR_ACCESS_LOCKED       (0x25)
67
/** \brief Cal page not valid error code. */
68
#define XCP_ERR_PAGE_NOT_VALID      (0x26)
69
/** \brief Sequence error code. */
70
#define XCP_ERR_SEQUENCE            (0x29)
71
/** \brief Generic error code. */
72
#define XCP_ERR_GENERIC             (0x31)
73

    
74
/* XCP command codes */
75
/** \brief CONNECT command code. */
76
#define XCP_CMD_CONNECT             (0xff)
77
/** \brief DISCONNECT command code. */
78
#define XCP_CMD_DISCONNECT          (0xfe)
79
/** \brief GET_STATUS command code. */
80
#define XCP_CMD_GET_STATUS          (0xfd)
81
/** \brief SYNCH command code. */
82
#define XCP_CMD_SYNCH               (0xfc)
83
/** \brief GET_ID command code. */
84
#define XCP_CMD_GET_ID              (0xfa)
85
/** \brief GET_SEED command code. */
86
#define XCP_CMD_GET_SEED            (0xf8)
87
/** \brief UNLOCK command code. */
88
#define XCP_CMD_UNLOCK              (0xf7)
89
/** \brief SET_MTA command code. */
90
#define XCP_CMD_SET_MTA             (0xf6)
91
/** \brief UPLOAD command code. */
92
#define XCP_CMD_UPLOAD              (0xf5)
93
/** \brief SHORT_UPLOAD command code. */
94
#define XCP_CMD_SHORT_UPLOAD        (0xf4)
95
/** \brief BUILD_CHECKSUM command code. */
96
#define XCP_CMD_BUILD_CHECKSUM      (0xf3)
97
/** \brief DOWNLOAD command code. */
98
#define XCP_CMD_DOWNLOAD            (0xf0)
99
/** \brief DOWNLOAD_MAX command code. */
100
#define XCP_CMD_DOWLOAD_MAX         (0xee)
101
/** \brief SET_CALPAGE command code. */
102
#define XCP_CMD_SET_CAL_PAGE        (0xeb)
103
/** \brief GET_CALPAGE command code. */
104
#define XCP_CMD_GET_CAL_PAGE        (0xea)
105
/** \brief PROGRAM_START command code. */
106
#define XCP_CMD_PROGRAM_START       (0xd2)
107
/** \brief PROGRAM_CLEAR command code. */
108
#define XCP_CMD_PROGRAM_CLEAR       (0xd1)
109
/** \brief PROGRAM command code. */
110
#define XCP_CMD_PROGRAM             (0xd0)
111
/** \brief PROGRAM_RESET command code. */
112
#define XCP_CMD_PROGRAM_RESET       (0xcf)
113
/** \brief PROGRAM_PREPARE command code. */
114
#define XCP_CMD_PROGRAM_PREPARE     (0xcc)
115
/** \brief PROGRAM_MAX command code. */
116
#define XCP_CMD_PROGRAM_MAX         (0xc9)
117

    
118

    
119
/****************************************************************************************
120
* Type definitions
121
****************************************************************************************/
122
/** \brief Struture type for grouping XCP internal module information. */
123
typedef struct
124
{
125
  blt_int8u  connected;                             /**< connection established                      */
126
#if (BOOT_GATE_ENABLE > 0)
127
  blt_int32u  other_connection;                      /**< connection to other device established      */
128
#endif
129
#if (BOOTLOADER_OF_MAIN_DEVICE > 0)
130
  blt_bool   wasMainConnection;                     /**< connection to serialboot (0x00) established */
131
#endif
132
  blt_int8u  oldData[BOOT_COM_RX_MAX_DATA];         /**< old packet data buffer                      */
133
  blt_int8u  protection;                            /**< protection state                            */
134
  blt_int8u  s_n_k_resource;                        /**< for seed/key sequence                       */
135
  blt_int8u  ctoData[BOOT_COM_RX_MAX_DATA];         /**< cto packet data buffer                      */
136
  blt_int8u  ctoPending;                            /**< cto transmission pending flag               */
137
  blt_int16s ctoLen;                                /**< cto current packet length                   */
138
  blt_int32u mta;                                   /**< memory transfer address                     */
139
} tXcpInfo;
140

    
141

    
142
/****************************************************************************************
143
* Function prototypes
144
****************************************************************************************/
145
/* transport layer specific functions */
146
#if (BOOT_GATE_ENABLE > 0)
147
static void      XcpTransmitPacket(blt_int8u *data, blt_int16s len, blt_bool fromGate);
148
#else
149
static void      XcpTransmitPacket(blt_int8u *data, blt_int16s len);
150
#endif /* BOOT_GATE_ENABLE > 0 */
151

    
152
/* application specific functions */
153
static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length,
154
                                    blt_int32u *checksum);
155

    
156
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
157
static blt_int8u XcpGetSeed(blt_int8u resource, blt_int8u *seed);
158
static blt_int8u XcpVerifyKey(blt_int8u resource, blt_int8u *key, blt_int8u len);
159
#endif
160

    
161
/* general utility functions */
162
static void XcpProtectResources(void);
163
static void XcpSetCtoError(blt_int8u error);
164

    
165
/* XCP command processors */
166
static void XcpCmdConnect(blt_int8u *data, blt_int16s dataLength);
167
static void XcpCmdDisconnect(blt_int8u *data);
168
static void XcpCmdGetStatus(blt_int8u *data);
169
static void XcpCmdSynch(blt_int8u *data);
170
static void XcpCmdGetId(blt_int8u *data);
171
static void XcpCmdSetMta(blt_int8u *data);
172
static void XcpCmdUpload(blt_int8u *data);
173
static void XcpCmdShortUpload(blt_int8u *data);
174
static void XcpCmdBuildCheckSum(blt_int8u *data);
175
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
176
static void XcpCmdGetSeed(blt_int8u *data);
177
static void XcpCmdUnlock(blt_int8u *data);
178
#endif
179
#if (XCP_RES_CALIBRATION_EN == 1)
180
static void XcpCmdDownload(blt_int8u *data);
181
static void XcpCmdDownloadMax(blt_int8u *data);
182
#endif
183
#if (XCP_RES_PAGING_EN == 1)
184
static void XcpCmdSetCalPage(blt_int8u *data);
185
static void XcpCmdGetCalPage(blt_int8u *data);
186
#endif
187
#if (XCP_RES_PROGRAMMING_EN == 1)
188
static void XcpCmdProgramMax(blt_int8u *data);
189
static void XcpCmdProgram(blt_int8u *data);
190
static void XcpCmdProgramStart(blt_int8u *data);
191
static void XcpCmdProgramClear(blt_int8u *data);
192
static void XcpCmdProgramReset(blt_int8u *data);
193
static void XcpCmdProgramPrepare(blt_int8u *data);
194
#endif
195
static void portedTransmission(blt_int8u *data);
196

    
197

    
198
/****************************************************************************************
199
* Hook functions
200
****************************************************************************************/
201
#if (XCP_RES_PAGING_EN == 1)
202
extern blt_int8u XcpCalSetPageHook(blt_int8u segment, blt_int8u page);
203
extern blt_int8u XcpCalGetPageHook(blt_int8u segment);
204
#endif
205

    
206
#if (XCP_CONNECT_MODE_HOOK_EN == 1)
207
extern blt_bool XcpConnectModeHook(blt_int8u mode);
208
#endif
209

    
210
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
211
extern blt_int8u XcpGetSeedHook(blt_int8u resource, blt_int8u *seed);
212
extern blt_int8u XcpVerifyKeyHook(blt_int8u resource, blt_int8u *key, blt_int8u len);
213
#endif
214

    
215

    
216

    
217
/****************************************************************************************
218
* External functions
219
****************************************************************************************/
220
#if (BOOT_COM_ENABLE == 0)
221
/* in case no internally supported communication interface is used, a custom
222
 * communication module can be added. In order to use the XCP protocol in the custom
223
 * communication module, this hook function needs to be implemented. In the XCP protocol
224
 * is not needed, then simply remove the xcp.c source from the project.
225
 */
226
extern void XcpTransmitPacketHook(blt_int8u *data, blt_int16u len);
227
#endif
228

    
229

    
230
/****************************************************************************************
231
* Local constants
232
****************************************************************************************/
233
/** \brief String buffer with station id. */
234
static const blt_int8s xcpStationId[] = XCP_STATION_ID_STRING;
235

    
236

    
237
/****************************************************************************************
238
* Local data definitions
239
****************************************************************************************/
240
/** \brief Local variable for storing XCP internal module info. */
241
static tXcpInfo xcpInfo;
242

    
243

    
244
/************************************************************************************//**
245
** \brief     Initializes the XCP driver. Should be called once upon system startup.
246
** \return    none
247
**
248
****************************************************************************************/
249
void XcpInit(void)
250
{
251
  /* reset xcp module info */
252
  xcpInfo.connected = 0;
253
#if (BOOT_GATE_ENABLE > 0)
254
  xcpInfo.other_connection = 0;
255
#endif
256
#if (BOOTLOADER_OF_MAIN_DEVICE > 0)
257
  xcpInfo.wasMainConnection = BLT_FALSE;
258
#endif
259
  xcpInfo.mta = 0;
260
  xcpInfo.ctoPending = 0;
261
  xcpInfo.ctoLen = 0;
262
  xcpInfo.s_n_k_resource = 0;
263
  xcpInfo.protection = 0;
264
} /*** end of XcpInit ***/
265

    
266

    
267
/************************************************************************************//**
268
** \brief     Obtains information about the XCP connection state.
269
** \return    BLT_TRUE is an XCP connection is established, BLT_FALSE otherwise.
270
**
271
****************************************************************************************/
272
blt_bool XcpIsConnected(void)
273
{
274
#if (BOOT_GATE_ENABLE > 0)
275
  if (xcpInfo.connected == 0 && xcpInfo.other_connection == 0)
276
#else
277
  if (xcpInfo.connected == 0)
278
#endif
279
  {
280
    return BLT_FALSE;
281
  }
282
  return BLT_TRUE;
283
} /*** end of XcpIsConnected ***/
284

    
285

    
286
#if (BOOTLOADER_OF_MAIN_DEVICE > 0)
287
/************************************************************************************//**
288
** \brief     Obtains information about the XCP main connection state.
289
** \return    BLT_TRUE is an XCP connection to main was established, BLT_FALSE otherwise.
290
**
291
****************************************************************************************/
292
blt_bool XcpWasConnectedToMain(void)
293
{
294
  return xcpInfo.wasMainConnection;
295
} /*** end of XcpWasConnectedToMain ***/
296
#endif
297

    
298

    
299
/************************************************************************************//**
300
** \brief     Informs the core that a pending packet transmission was completed by
301
**            the transport layer.
302
** \return    none
303
**
304
****************************************************************************************/
305
void XcpPacketTransmitted(void)
306
{
307
  /* reset packet transmission pending flag */
308
  xcpInfo.ctoPending = 0;
309
} /*** end of XcpPacketTransmitted ***/
310

    
311

    
312
/************************************************************************************//**
313
** \brief     Informs the core that a new packet was received by the transport layer.
314
** \param     data       Pointer to byte buffer with packet data.
315
** \param     dataLength Number of data bytes that need to be transmitted.
316
** \return    none
317
**
318
****************************************************************************************/
319
#if (BOOT_GATE_ENABLE > 0)
320
void XcpPacketReceived(blt_int8u *data, blt_int16s dataLength, blt_bool fromGate)
321
#else
322
void XcpPacketReceived(blt_int8u *data, blt_int16s dataLength)
323
#endif /* BOOT_GATE_ENABLE > 0 */
324
{
325
  /* was this a connect command? */
326
  if (data[0] == XCP_CMD_CONNECT)
327
  {
328
    /* process the connect command */
329
    XcpCmdConnect(data, dataLength);
330
  }
331
  /* only continue if connected */
332
  else if (xcpInfo.connected == 1)
333
  {
334
    switch (data[0])
335
    {
336
      case XCP_CMD_UPLOAD:
337
        XcpCmdUpload(data);
338
        break;
339
      case XCP_CMD_SHORT_UPLOAD:
340
        XcpCmdShortUpload(data);
341
        break;
342
      case XCP_CMD_SET_MTA:
343
        XcpCmdSetMta(data);
344
        break;
345
      case XCP_CMD_BUILD_CHECKSUM:
346
        XcpCmdBuildCheckSum(data);
347
        break;
348
      case XCP_CMD_GET_ID:
349
        XcpCmdGetId(data);
350
        break;
351
      case XCP_CMD_SYNCH:
352
        XcpCmdSynch(data);
353
        break;
354
      case XCP_CMD_GET_STATUS:
355
        XcpCmdGetStatus(data);
356
        break;
357
      case XCP_CMD_DISCONNECT:
358
        XcpCmdDisconnect(data);
359
        break;
360
#if (XCP_RES_CALIBRATION_EN == 1)
361
      case XCP_CMD_DOWNLOAD:
362
        XcpCmdDownload(data);
363
        break;
364
      case XCP_CMD_DOWLOAD_MAX:
365
        XcpCmdDownloadMax(data);
366
        break;
367
#endif
368
#if (XCP_RES_PROGRAMMING_EN == 1)
369
      case XCP_CMD_PROGRAM_MAX:
370
        XcpCmdProgramMax(data);
371
        break;
372
      case XCP_CMD_PROGRAM:
373
        XcpCmdProgram(data);
374
        break;
375
      case XCP_CMD_PROGRAM_START:
376
        XcpCmdProgramStart(data);
377
        break;
378
      case XCP_CMD_PROGRAM_CLEAR:
379
        XcpCmdProgramClear(data);
380
        break;
381
      case XCP_CMD_PROGRAM_RESET:
382
        XcpCmdProgramReset(data);
383
        break;
384
      case XCP_CMD_PROGRAM_PREPARE:
385
        XcpCmdProgramPrepare(data);
386
        break;
387
#endif
388
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
389
      case XCP_CMD_GET_SEED:
390
        XcpCmdGetSeed(data);
391
        break;
392
      case XCP_CMD_UNLOCK:
393
        XcpCmdUnlock(data);
394
        break;
395
#endif
396
#if (XCP_RES_PAGING_EN == 1)
397
      case XCP_CMD_SET_CAL_PAGE:
398
        XcpCmdSetCalPage(data);
399
        break;
400
      case XCP_CMD_GET_CAL_PAGE:
401
        XcpCmdGetCalPage(data);
402
        break;
403
#endif
404
      default:
405
        XcpSetCtoError(XCP_ERR_CMD_UNKNOWN);
406
        break;
407
    }
408
  }
409
#if (BOOT_GATE_ENABLE > 0)
410
  /* check if there is still an other connection */
411
  else if (xcpInfo.other_connection > 0) {
412
    /* Forwarding message */
413
    XcpPacketReceivedForwarding(data, dataLength);
414
    return;
415
  }
416
#endif /* (BOOT_GATE_ENABLE > 0) */
417
  else
418
  {
419
    /* return to make sure response packet is not send because we are not connected */
420
    return;
421
  }
422

    
423
  /* make sure the previous command was completed */
424
  if (xcpInfo.ctoPending == 1)
425
  {
426
    /* command overrun occurred */
427
    XcpSetCtoError(XCP_ERR_CMD_BUSY);
428
  }
429

    
430
  /* send the response if it contains something */
431
  if (xcpInfo.ctoLen > 0)
432
  {
433
    /* set cto packet transmission pending flag */
434
    xcpInfo.ctoPending = 1;
435

    
436
    /* transmit the cto response packet */
437
#if (BOOT_GATE_ENABLE > 0)
438
    XcpTransmitPacket(xcpInfo.ctoData, xcpInfo.ctoLen, fromGate);
439
#else
440
    XcpTransmitPacket(xcpInfo.ctoData, xcpInfo.ctoLen);
441
#endif /* BOOT_GATE_ENABLE > 0 */
442
  }
443

    
444
} /*** end of XcpPacketReceived ***/
445

    
446

    
447

    
448
#if (BOOT_GATE_ENABLE > 0)
449
/************************************************************************************//**
450
** \brief     Forwards the packet to other device.
451
** \param     data       Pointer to the byte buffer with packet data.
452
** \param     dataLength Number of data bytes that need to be transmitted.
453
** \return    none
454
**
455
****************************************************************************************/
456
void XcpPacketReceivedForwarding(blt_int8u *data, blt_int16s dataLength) {
457
  /* save id of connected device */
458
  blt_int32u connectionTo = xcpInfo.other_connection;
459

    
460
  /* proof commands */
461
  switch (data[0]) {
462
    /* if there is a disconnection command, everything else in xcp info
463
     * has to be set on disconnection
464
     */
465
    case XCP_CMD_DISCONNECT:
466
      xcpInfo.other_connection = 0;
467
      xcpInfo.connected = 0;
468
      setLed(0);
469
      break;
470
    /* if there is a reset command, it has to be handled like a disconnection
471
     * (above) because other devices shouldn't get the ability to reset
472
     * themselves alone without any general reset command to all devices
473
     */
474
    case XCP_CMD_PROGRAM_RESET:
475
      xcpInfo.other_connection = 0;
476
      xcpInfo.connected = 0;
477
      setLed(0);
478
      data[0] = XCP_CMD_DISCONNECT;
479
      break;
480
    default:
481
      break;
482
  }
483

    
484
  xcpInfo.ctoPending = 1;
485
#if (BOOT_DEBUGGING_UART2_ENABLE > 0)
486
  /* send debugging information */
487
  BuildData(&debugDataTCan, data, (blt_int8u)dataLength);
488
#endif
489
  /* send packet direct with CAN */
490
  GateTransmitPacketDirect(data, (blt_int8u)dataLength, connectionTo);
491
} /*** end of XcpPacketReceivedForwarding ***/
492

    
493

    
494
/************************************************************************************//**
495
** \brief     Transmits the packet from gateway to com.
496
** \param     data       Pointer to the byte buffer with packet data.
497
** \param     dataLength Number of data bytes that need to be transmitted.
498
** \return    none
499
**
500
****************************************************************************************/
501
void XcpGatewayPacketReceived(blt_int8u *data, blt_int16s dataLength) {
502
  xcpInfo.ctoPending = 1;
503
#if (BOOT_DEBUGGING_UART2_ENABLE > 0)
504
  /* send debugging information */
505
  BuildData(&debugDataRCan, data, (blt_int8u)dataLength);
506
#endif
507
  /* send packet direct with UART */
508
  ComTransmitPacketDirect(data, (blt_int8u)dataLength);
509
} /*** end of XcpGatewayPacketReceived ***/
510

    
511
#endif /* (BOOT_GATE_ENABLE > 0) */
512

    
513

    
514

    
515
/************************************************************************************//**
516
** \brief     Transmits the packet using the xcp transport layer.
517
** \param     data Pointer to the byte buffer with packet data.
518
** \param     len  Number of data bytes that need to be transmitted.
519
** \return    none
520
**
521
****************************************************************************************/
522

    
523
#if (BOOT_GATE_ENABLE > 0)
524
static void XcpTransmitPacket(blt_int8u *data, blt_int16s len, blt_bool fromGate)
525
#else
526
static void XcpTransmitPacket(blt_int8u *data, blt_int16s len)
527
#endif /* BOOT_GATE_ENABLE > 0 */
528
{
529
  /* submit packet to the communication interface for transmission */
530
#if (BOOT_GATE_ENABLE > 0)
531
  if (fromGate == BLT_TRUE) {
532
    GateTransmitPacket(data, len);
533
    return;
534
  }
535
#endif /* BOOT_GATE_ENABLE > 0 */
536
#if (BOOT_COM_ENABLE == 0)
537
  XcpTransmitPacketHook(data, len);
538
#else
539
  ComTransmitPacket(data, len);
540
#endif
541

    
542
} /*** end of XcpTransmitPacket ***/
543

    
544

    
545
/************************************************************************************//**
546
** \brief     Called by the BUILD_CHECKSUM command to perform a checksum calculation
547
**            over the specified memory region.
548
** \param     address   The start address of the memory region.
549
** \param     length    Length of the memory region in bytes.
550
** \param     checksum  Pointer to where the calculated checksum is to be stored.
551
** \return    Checksum type that was used during the checksum calculation.
552
**
553
****************************************************************************************/
554
static blt_int8u XcpComputeChecksum(blt_int32u address, blt_int32u length,
555
                                    blt_int32u *checksum)
556
{
557
  blt_int8u cs = 0;
558

    
559
  /* this example computes the checksum using the add byte to byte algorithm */
560
  while (length-- > 0)
561
  {
562
    cs += *((blt_int8u*)(blt_addr)address);
563
    address++;
564
  }
565

    
566
  *checksum = cs;
567

    
568
  return XCP_CS_ADD11;
569
} /*** end of XcpComputeChecksum ***/
570

    
571

    
572
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
573
/************************************************************************************//**
574
** \brief     Provides a seed to the XCP master that will be used for the key
575
**            generation when the master attempts to unlock the specified resource.
576
**            Called by the GET_SEED command.
577
** \param     resource  Resource that the seed if requested for (XCP_RES_XXX).
578
** \param     seed      Pointer to byte buffer wher the seed will be stored.
579
** \return    Length of the seed in bytes.
580
**
581
****************************************************************************************/
582
static blt_int8u XcpGetSeed(blt_int8u resource, blt_int8u *seed)
583
{
584
  /* pass request on to the application through a hook function */
585
  return XcpGetSeedHook(resource, seed);
586
} /*** end of XcpGetSeed ***/
587

    
588

    
589
/************************************************************************************//**
590
** \brief     Called by the UNLOCK command and checks if the key to unlock the
591
**            specified resource was correct. If so, then the resource protection
592
**            will be removed.
593
** \param     resource  resource to unlock (XCP_RES_XXX).
594
** \param     key       pointer to the byte buffer holding the key.
595
** \param     len       length of the key in bytes.
596
** \return    1 if the key was correct, 0 otherwise.
597
**
598
****************************************************************************************/
599
static blt_int8u XcpVerifyKey(blt_int8u resource, blt_int8u *key, blt_int8u len)
600
{
601
  /* pass request on to the application through a hook function */
602
  return XcpVerifyKeyHook(resource, key, len);
603
} /*** end of XcpVerifyKey ***/
604
#endif /* XCP_SEED_KEY_PROTECTION_EN == 1 */
605

    
606

    
607
/************************************************************************************//**
608
** \brief     Utility function to protects all the available resources.
609
** \return    none
610
**
611
****************************************************************************************/
612
static void XcpProtectResources(void)
613
{
614
  xcpInfo.protection = 0;
615

    
616
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
617
  #if (XCP_RES_CALIBRATION_EN == 1)
618
  xcpInfo.protection |= XCP_RES_CALPAG;
619
  #endif
620

    
621
  #if (XCP_RES_PAGING_EN == 1)
622
  xcpInfo.protection |= XCP_RES_CALPAG;
623
  #endif
624

    
625
  #if (XCP_RES_PROGRAMMING_EN == 1)
626
  xcpInfo.protection |= XCP_RES_PGM;
627
  #endif
628

    
629
  #if (XCP_RES_DATA_ACQUISITION_EN == 1)
630
  xcpInfo.protection |= XCP_RES_DAQ;
631
  #endif
632

    
633
  #if (XCP_RES_DATA_STIMULATION_EN == 1)
634
  xcpInfo.protection |= XCP_RES_STIM;
635
  #endif
636
#endif /* XCP_SEED_KEY_PROTECTION_EN == 1 */
637
} /*** end of XcpProtectResources ***/
638

    
639

    
640
/************************************************************************************//**
641
** \brief     Prepares the cto packet data for the specified error.
642
** \param     error XCP error code (XCP_ERR_XXX).
643
** \return    none
644
**
645
****************************************************************************************/
646
static void XcpSetCtoError(blt_int8u error)
647
{
648
  /* prepare the error packet */
649
  xcpInfo.ctoData[0] = XCP_PID_ERR;
650
  xcpInfo.ctoData[1] = error;
651
  xcpInfo.ctoLen = 2;
652
} /*** end of XcpSetCtoError ***/
653

    
654

    
655
/************************************************************************************//**
656
** \brief     XCP command processor function which handles the CONNECT command as
657
**            defined by the protocol.
658
** \param     data Pointer to a byte buffer with the packet data.
659
** \return    none
660
**
661
****************************************************************************************/
662
static void XcpCmdConnect(blt_int8u *data, blt_int16s dataLength)
663
{
664
  /* suppress compiler warning for unused parameter */
665
  data = data;
666

    
667
  #if (BOOT_FILE_SYS_ENABLE > 0)
668
  /* reject the connection if the file module is not idle. this means that a firmware
669
   * update from the locally attached storage is in progress
670
   */
671
  if (FileIsIdle() == BLT_FALSE)
672
  {
673
    /* command not processed because we are busy */
674
    XcpSetCtoError(XCP_ERR_CMD_BUSY);
675
    return;
676
  }
677
  #endif
678

    
679
//  #if (XCP_CONNECT_MODE_HOOK_EN == 1)
680
//  /* pass on the mode to a application specific hook function. This function can determine
681
//   * is the mode is supported or not. A return value of BLT_FALSE causes the CONNECT command
682
//   * to be ignored. Note that this mode could potentially be used to specify a node ID in a
683
//   * multi XCP slave system.
684
//   */
685
//  if (XcpConnectModeHook(data[1]) == BLT_FALSE)
686
//  {
687
//    /* set the response length to 0 to suppress it */
688
//    xcpInfo.ctoLen = 0;
689
//    return;
690
//  }
691
//  #endif
692

    
693
  /* enable resource protection */
694
  XcpProtectResources();
695

    
696
  /* extract the device ID.
697
   * NOTE: For legacy support the following code depends on the data length.
698
   *       If two bytes were received the system switches to legacy mode.
699
   *       In legacy mode, the device ID was only one byte.
700
   */
701
  blt_int32u deviceID;
702
  if (dataLength == 2) {
703
    deviceID = ((blt_int32u)0 << 24) | \
704
               ((blt_int32u)0 << 16) | \
705
               ((blt_int32u)0 <<  8) | \
706
               ((blt_int32u)data[1]);
707
  } else if (dataLength == 5) {
708
    deviceID = ((blt_int32u)data[4] << 24) | \
709
               ((blt_int32u)data[3] << 16) | \
710
               ((blt_int32u)data[2] <<  8) | \
711
               ((blt_int32u)data[1]);
712
  } else {
713
    blinkSOSinf();
714
  }
715
  /* indicate that the connection is established */
716
#if (BOOT_GATE_ENABLE > 0)
717
#if defined(BOOT_COM_DEVICE_LEGACY_ID)
718
  if (deviceID == 0 ||
719
      deviceID == (blt_int32u)BOOT_COM_DEVICE_ID ||
720
      deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID) {
721
#else
722
  if (deviceID == 0 ||
723
      deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) {
724
#endif
725
#endif
726
    xcpInfo.connected = 1;
727
    setLed(1);
728
#if (BOOT_GATE_ENABLE > 0)
729
    xcpInfo.other_connection = 0;
730
#endif
731
#if (BOOTLOADER_OF_MAIN_DEVICE > 0)
732
    if (deviceID == 0x00) {
733
      xcpInfo.wasMainConnection = BLT_TRUE;
734
    }
735
#endif
736

    
737
    /* set packet id to command response packet */
738
    xcpInfo.ctoData[0] = XCP_PID_RES;
739

    
740
    /* report available resources */
741
    xcpInfo.ctoData[1] = 0;
742
#if (XCP_RES_CALIBRATION_EN == 1)
743
    xcpInfo.ctoData[1] |= XCP_RES_CALPAG;
744
#endif
745

    
746
#if (XCP_RES_PAGING_EN == 1)
747
    xcpInfo.ctoData[1] |= XCP_RES_CALPAG;
748
#endif
749

    
750
#if (XCP_RES_PROGRAMMING_EN == 1)
751
    xcpInfo.ctoData[1] |= XCP_RES_PGM;
752
#endif
753

    
754
#if (XCP_RES_DATA_ACQUISITION_EN == 1)
755
    xcpInfo.ctoData[1] |= XCP_RES_DAQ;
756
#endif
757

    
758
#if (XCP_RES_DATA_STIMULATION_EN == 1)
759
    xcpInfo.ctoData[1] |= XCP_RES_STIM;
760
#endif
761

    
762
    /* report communication mode info. only byte granularity is supported */
763
    xcpInfo.ctoData[2] = 0;
764
    /* configure for motorola or intel byte ordering */
765
    xcpInfo.ctoData[2] |= XCP_MOTOROLA_FORMAT;
766

    
767
    /* report max cto data length */
768
    xcpInfo.ctoData[3] = (blt_int8u)XCP_CTO_PACKET_LEN;
769

    
770
    /* report max dto data length */
771
#if (XCP_MOTOROLA_FORMAT == 0)
772
    xcpInfo.ctoData[4] = (blt_int8u)XCP_DTO_PACKET_LEN;
773
    xcpInfo.ctoData[5] = (blt_int8u)(XCP_DTO_PACKET_LEN >> 8);
774
#else
775
    xcpInfo.ctoData[4] = (blt_int8u)(XCP_DTO_PACKET_LEN >> 8);
776
    xcpInfo.ctoData[5] = (blt_int8u)XCP_DTO_PACKET_LEN;
777
#endif
778

    
779
    /* report msb of protocol layer version number */
780
    xcpInfo.ctoData[6] = XCP_VERSION_PROTOCOL_LAYER >> 8;
781

    
782
    /* report msb of transport layer version number */
783
    xcpInfo.ctoData[7] = XCP_VERSION_TRANSPORT_LAYER >> 8;
784

    
785
    /* set packet length */
786
    xcpInfo.ctoLen = 8;
787

    
788
#if (BOOT_GATE_ENABLE > 0)
789
  } else {
790
    xcpInfo.other_connection = deviceID;
791
    setLed(1);
792
    xcpInfo.connected = 0;
793
    XcpPacketReceivedForwarding(data, dataLength);
794
    xcpInfo.ctoLen = 0;
795
    // TODO better cancel definition!
796
//    if (xcpInfo.ctoLen == 0) {
797
//      xcpInfo.other_connection = 0;
798
//    }
799
  }
800
#endif
801

    
802

    
803
} /*** end of XcpCmdConnect ***/
804

    
805

    
806
/************************************************************************************//**
807
** \brief     XCP command processor function which handles the DISCONNECT command as
808
**            defined by the protocol.
809
** \param     data Pointer to a byte buffer with the packet data.
810
** \return    none
811
**
812
****************************************************************************************/
813
static void XcpCmdDisconnect(blt_int8u *data)
814
{
815
  /* suppress compiler warning for unused parameter */
816
  data = data;
817

    
818
  /* indicate that the xcp connection is disconnected */
819
  xcpInfo.connected = 0;
820
#if (BOOT_GATE_ENABLE > 0)
821
  xcpInfo.other_connection = 0;
822
#endif
823
  setLed(0);
824

    
825
  /* enable resource protection */
826
  XcpProtectResources();
827

    
828
  /* set packet id to command response packet */
829
  xcpInfo.ctoData[0] = XCP_PID_RES;
830

    
831
  /* set packet length */
832
  xcpInfo.ctoLen = 1;
833

    
834
} /*** end of XcpCmdDisconnect ***/
835

    
836

    
837
/************************************************************************************//**
838
** \brief     XCP command processor function which handles the GET_STATUS command as
839
**            defined by the protocol.
840
** \param     data Pointer to a byte buffer with the packet data.
841
** \return    none
842
**
843
****************************************************************************************/
844
static void XcpCmdGetStatus(blt_int8u *data)
845
{
846
  /* suppress compiler warning for unused parameter */
847
  data = data;
848

    
849
  /* set packet id to command response packet */
850
  xcpInfo.ctoData[0] = XCP_PID_RES;
851

    
852
  /* report session status */
853
  xcpInfo.ctoData[1] = 0;
854

    
855
  /* report current resource protection status */
856
  xcpInfo.ctoData[2] = xcpInfo.protection;
857

    
858
  /* reset reserved and session configuration id values */
859
  xcpInfo.ctoData[3] = 0;
860
  xcpInfo.ctoData[4] = 0;
861
  xcpInfo.ctoData[5] = 0;
862

    
863
  /* set packet length */
864
  xcpInfo.ctoLen = 6;
865
} /*** end of XcpCmdGetStatus ***/
866

    
867

    
868
/************************************************************************************//**
869
** \brief     XCP command processor function which handles the SYNCH command as
870
**            defined by the protocol.
871
** \param     data Pointer to a byte buffer with the packet data.
872
** \return    none
873
**
874
****************************************************************************************/
875
static void XcpCmdSynch(blt_int8u *data)
876
{
877
  /* suppress compiler warning for unused parameter */
878
  data = data;
879

    
880
  /* synch requires a negative response */
881
  XcpSetCtoError(XCP_ERR_CMD_SYNCH);
882
} /*** end of XcpCmdSynch ***/
883

    
884

    
885
/************************************************************************************//**
886
** \brief     XCP command processor function which handles the GET_ID command as
887
**            defined by the protocol.
888
** \param     data Pointer to a byte buffer with the packet data.
889
** \return    none
890
**
891
****************************************************************************************/
892
static void XcpCmdGetId(blt_int8u *data)
893
{
894
  /* suppress compiler warning for unused parameter */
895
  data = data;
896

    
897
  /* set packet id to command response packet */
898
  xcpInfo.ctoData[0] = XCP_PID_RES;
899

    
900
  /* point mta to start of station id string */
901
  xcpInfo.mta = (blt_int32u)&xcpStationId[0];
902

    
903
  /* set station id mode to 0 */
904
  xcpInfo.ctoData[1] = 0;
905

    
906
  /* reset reserved values */
907
  xcpInfo.ctoData[2] = 0;
908
  xcpInfo.ctoData[3] = 0;
909

    
910
  /* store station id length (excl. null termination) for response packet */
911
  *(blt_int32u*)&xcpInfo.ctoData[4] = (sizeof(xcpStationId)/sizeof(xcpStationId[0])) - 1;
912

    
913
  /* set packet length */
914
  xcpInfo.ctoLen = 8;
915
} /*** end of XcpCmdGetId ***/
916

    
917

    
918
/************************************************************************************//**
919
** \brief     XCP command processor function which handles the SET_MTA command as
920
**            defined by the protocol.
921
** \param     data Pointer to a byte buffer with the packet data.
922
** \return    none
923
**
924
****************************************************************************************/
925
static void XcpCmdSetMta(blt_int8u *data)
926
{
927
  /* set packet id to command response packet */
928
  xcpInfo.ctoData[0] = XCP_PID_RES;
929

    
930
  /* update mta. current implementation ignores address extension */
931
  xcpInfo.mta = *(blt_int32u*)&data[4];
932

    
933
  /* set packet length */
934
  xcpInfo.ctoLen = 1;
935
} /*** end of XcpCmdSetMta ***/
936

    
937

    
938
/************************************************************************************//**
939
** \brief     XCP command processor function which handles the UPLOAD command as
940
**            defined by the protocol.
941
** \param     data Pointer to a byte buffer with the packet data.
942
** \return    none
943
**
944
****************************************************************************************/
945
static void XcpCmdUpload(blt_int8u *data)
946
{
947
  /* validate length of upload request */
948
  if (data[1] > (XCP_CTO_PACKET_LEN-1))
949
  {
950
    /* requested data length is too long */
951
    XcpSetCtoError(XCP_ERR_OUT_OF_RANGE);
952
    return;
953
  }
954

    
955
  /* copy the data from memory to the data packet */
956
  CpuMemCopy(((blt_addr)(blt_int32u)&xcpInfo.ctoData[1]),(blt_addr)xcpInfo.mta, data[1]);
957

    
958
  /* set packet id to command response packet */
959
  xcpInfo.ctoData[0] = XCP_PID_RES;
960

    
961
  /* post increment the mta */
962
  xcpInfo.mta += data[1];
963

    
964
  /* set packet length */
965
  xcpInfo.ctoLen = data[1]+1;
966
} /*** end of XcpCmdUpload ***/
967

    
968

    
969
/************************************************************************************//**
970
** \brief     XCP command processor function which handles the SHORT_UPLOAD command as
971
**            defined by the protocol.
972
** \param     data Pointer to a byte buffer with the packet data.
973
** \return    none
974
**
975
****************************************************************************************/
976
static void XcpCmdShortUpload(blt_int8u *data)
977
{
978
  /* validate length of upload request */
979
  if (data[1] > (XCP_CTO_PACKET_LEN-1))
980
  {
981
    /* requested data length is too long */
982
    XcpSetCtoError(XCP_ERR_OUT_OF_RANGE);
983
    return;
984
  }
985

    
986
  /* update mta. current implementation ignores address extension */
987
  xcpInfo.mta = *(blt_int32u*)&data[4];
988

    
989
  /* copy the data from memory to the data packet */
990
  CpuMemCopy((blt_addr)((blt_int32u)&xcpInfo.ctoData[1]),(blt_addr)xcpInfo.mta, data[1]);
991
  /* set packet id to command response packet */
992
  xcpInfo.ctoData[0] = XCP_PID_RES;
993

    
994
  /* post increment the mta */
995
  xcpInfo.mta += data[1];
996

    
997
  /* set packet length */
998
  xcpInfo.ctoLen = data[1]+1;
999
} /*** end of XcpCmdShortUpload ***/
1000

    
1001

    
1002
#if (XCP_RES_CALIBRATION_EN == 1)
1003
/************************************************************************************//**
1004
** \brief     XCP command processor function which handles the DOWNLOAD command as
1005
**            defined by the protocol.
1006
** \param     data Pointer to a byte buffer with the packet data.
1007
** \return    none
1008
**
1009
****************************************************************************************/
1010
static void XcpCmdDownload(blt_int8u *data)
1011
{
1012
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1013
  /* check if CAL_PAG resource is unlocked */
1014
  if ((xcpInfo.protection & XCP_RES_CALPAG) != 0)
1015
  {
1016
    /* resource is locked. use seed/key sequence to unlock */
1017
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1018
    return;
1019
  }
1020
#endif
1021

    
1022
  /* validate length of download request */
1023
  if (data[1] > (XCP_CTO_PACKET_LEN-2))
1024
  {
1025
    /* requested data length is too long */
1026
    XcpSetCtoError(XCP_ERR_OUT_OF_RANGE);
1027
    return;
1028
  }
1029

    
1030
  /* copy the data from the data packet to memory */
1031
  CpuMemCopy((blt_addr)xcpInfo.mta, (blt_addr)((blt_int32u)&data[2]), data[1]);
1032
  /* set packet id to command response packet */
1033
  xcpInfo.ctoData[0] = XCP_PID_RES;
1034

    
1035
  /* post increment the mta */
1036
  xcpInfo.mta += data[1];
1037

    
1038
  /* set packet length */
1039
  xcpInfo.ctoLen = 1;
1040
} /*** end of XcpCmdDownload ***/
1041

    
1042

    
1043
/************************************************************************************//**
1044
** \brief     XCP command processor function which handles the DOWNLOAD_MAX command as
1045
**            defined by the protocol.
1046
** \param     data Pointer to a byte buffer with the packet data.
1047
** \return    none
1048
**
1049
****************************************************************************************/
1050
static void XcpCmdDownloadMax(blt_int8u *data)
1051
{
1052
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1053
  /* check if CAL_PAG resource is unlocked */
1054
  if ((xcpInfo.protection & XCP_RES_CALPAG) != 0)
1055
  {
1056
    /* resource is locked. use seed/key sequence to unlock */
1057
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1058
    return;
1059
  }
1060
#endif
1061

    
1062
  /* copy the data from the data packet to memory */
1063
  CpuMemCopy((blt_addr)xcpInfo.mta, (blt_addr)((blt_int32u)&data[1]), \
1064
              XCP_CTO_PACKET_LEN-1);
1065

    
1066
  /* set packet id to command response packet */
1067
  xcpInfo.ctoData[0] = XCP_PID_RES;
1068

    
1069
  /* post increment the mta */
1070
  xcpInfo.mta += XCP_CTO_PACKET_LEN-1;
1071

    
1072
  /* set packet length */
1073
  xcpInfo.ctoLen = 1;
1074
} /*** end of XcpCmdDownloadMax ***/
1075
#endif /* XCP_RES_CALIBRATION_EN == 1 */
1076

    
1077

    
1078
/************************************************************************************//**
1079
** \brief     XCP command processor function which handles the BUILD_CHECKSUM command as
1080
**            defined by the protocol.
1081
** \param     data Pointer to a byte buffer with the packet data.
1082
** \return    none
1083
**
1084
****************************************************************************************/
1085
static void XcpCmdBuildCheckSum(blt_int8u *data)
1086
{
1087
  /* set packet id to command response packet */
1088
  xcpInfo.ctoData[0] = XCP_PID_RES;
1089

    
1090
  /* obtain checksum and checksum type */
1091
  xcpInfo.ctoData[1] = XcpComputeChecksum(xcpInfo.mta, *(blt_int32u*)&data[4],
1092
                                          (blt_int32u*)&xcpInfo.ctoData[4]);
1093

    
1094
  /* initialize reserved parameters */
1095
  xcpInfo.ctoData[2] = 0;
1096
  xcpInfo.ctoData[3] = 0;
1097

    
1098
  /* set packet length */
1099
  xcpInfo.ctoLen = 8;
1100
} /*** end of XcpCmdBuildCheckSum ***/
1101

    
1102

    
1103
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1104
/************************************************************************************//**
1105
** \brief     XCP command processor function which handles the GET_SEED command as
1106
**            defined by the protocol.
1107
** \param     data Pointer to a byte buffer with the packet data.
1108
** \return    none
1109
**
1110
****************************************************************************************/
1111
static void XcpCmdGetSeed(blt_int8u *data)
1112
{
1113
  blt_int8u resourceOK;
1114

    
1115
  /* init resource check variable as if an illegal resource is requested */
1116
  resourceOK = 0;
1117

    
1118
  /* check if calibration/paging resource is requested for seed/key and make
1119
   * sure this is the only requested resource
1120
   */
1121
  if (((data[2] & XCP_RES_CALPAG) > 0) && ((data[2] & ~XCP_RES_CALPAG) == 0))
1122
  {
1123
    resourceOK = 1;
1124
  }
1125

    
1126
  /* check if programming resource is requested for seed/key and make
1127
   * sure this is the only requested resource
1128
   */
1129
  if (((data[2] & XCP_RES_PGM) > 0) && ((data[2] & ~XCP_RES_PGM) == 0))
1130
  {
1131
    resourceOK = 1;
1132
  }
1133

    
1134
  /* check if data acquisition resource is requested for seed/key and make
1135
   * sure this is the only requested resource
1136
   */
1137
  if (((data[2] & XCP_RES_DAQ) > 0) && ((data[2] & ~XCP_RES_DAQ) == 0))
1138
  {
1139
    resourceOK = 1;
1140
  }
1141

    
1142
  /* check if data stimulation resource is requested for seed/key and make
1143
   * sure this is the only requested resource
1144
   */
1145
  if (((data[2] & XCP_RES_STIM) > 0) && ((data[2] & ~XCP_RES_STIM) == 0))
1146
  {
1147
    resourceOK = 1;
1148
  }
1149

    
1150
  /* now process the resource validation */
1151
  if (resourceOK == 0)
1152
  {
1153
    XcpSetCtoError(XCP_ERR_OUT_OF_RANGE);
1154
    return;
1155
  }
1156

    
1157
  /* store resource for which the seed/key sequence is started */
1158
  xcpInfo.s_n_k_resource = data[2];
1159

    
1160
  /* set packet id to command response packet */
1161
  xcpInfo.ctoData[0] = XCP_PID_RES;
1162

    
1163
  /* request the seed from the application */
1164
  xcpInfo.ctoData[1] = XcpGetSeed(xcpInfo.s_n_k_resource, &xcpInfo.ctoData[2]);
1165

    
1166
  /* seed cannot be longer than XCP_CTO_PACKET_LEN-2 */
1167
  if (xcpInfo.ctoData[1] > (XCP_CTO_PACKET_LEN-2))
1168
  {
1169
    /* seed length length is too long */
1170
    XcpSetCtoError(XCP_ERR_OUT_OF_RANGE);
1171
    return;
1172
  }
1173

    
1174
  /* set packet length */
1175
  xcpInfo.ctoLen = xcpInfo.ctoData[1] + 2;
1176
} /*** end of XcpCmdGetSeed ***/
1177

    
1178

    
1179
/************************************************************************************//**
1180
** \brief     XCP command processor function which handles the UNLOCK command as
1181
**            defined by the protocol.
1182
** \param     data Pointer to a byte buffer with the packet data.
1183
** \return    none
1184
**
1185
****************************************************************************************/
1186
static void XcpCmdUnlock(blt_int8u *data)
1187
{
1188
  /* key cannot be longer than XCP_CTO_PACKET_LEN-2 */
1189
  if (data[1] > (XCP_CTO_PACKET_LEN-2))
1190
  {
1191
    /* key is too long incorrect */
1192
    XcpSetCtoError(XCP_ERR_SEQUENCE);
1193
    return;
1194
  }
1195

    
1196
  /* verify the key */
1197
  if (XcpVerifyKey(xcpInfo.s_n_k_resource, &data[2], data[1]) == 0)
1198
  {
1199
    /* invalid key so inform the master and do a disconnect */
1200
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1201

    
1202
    /* indicate that the xcp connection is disconnected */
1203
    xcpInfo.connected = 0;
1204

    
1205
    /* enable resource protection */
1206
    XcpProtectResources();
1207

    
1208
    return;
1209
  }
1210

    
1211
  /* key correct so unlock the resource */
1212
  xcpInfo.protection &= ~xcpInfo.s_n_k_resource;
1213

    
1214
  /* reset seed/key resource variable for possible next unlock */
1215
  xcpInfo.s_n_k_resource = 0;
1216

    
1217
  /* set packet id to command response packet */
1218
  xcpInfo.ctoData[0] = XCP_PID_RES;
1219

    
1220
  /* report the current resource protection */
1221
  xcpInfo.ctoData[1] = xcpInfo.protection;
1222

    
1223
  /* set packet length */
1224
  xcpInfo.ctoLen = 2;
1225
} /*** end of XcpCmdUnlock ***/
1226
#endif /* XCP_SEED_KEY_PROTECTION_EN == 1 */
1227

    
1228

    
1229
#if (XCP_RES_PAGING_EN == 1)
1230
/************************************************************************************//**
1231
** \brief     XCP command processor function which handles the SET_CAL_PAGE command as
1232
**            defined by the protocol.
1233
** \param     data Pointer to a byte buffer with the packet data.
1234
** \return    none
1235
**
1236
****************************************************************************************/
1237
static void XcpCmdSetCalPage(blt_int8u *data)
1238
{
1239
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1240
  /* check if CAL_PAG resource is unlocked */
1241
  if ((xcpInfo.protection & XCP_RES_CALPAG) == XCP_RES_CALPAG)
1242
  {
1243
    /* resource is locked. use seed/key sequence to unlock */
1244
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1245
    return;
1246
  }
1247
#endif
1248

    
1249
  /* select the page. note that the mode parameter is ignored */
1250
  if (XcpCalSetPageHook(data[2], data[3]) == 0)
1251
  {
1252
    /* calibration page could not be selected */
1253
    XcpSetCtoError(XCP_ERR_PAGE_NOT_VALID);
1254
    return;
1255
  }
1256

    
1257
  /* set packet id to command response packet */
1258
  xcpInfo.ctoData[0] = XCP_PID_RES;
1259

    
1260
  /* set packet length */
1261
  xcpInfo.ctoLen = 1;
1262
} /*** end of XcpCmdSetCalPage ***/
1263

    
1264

    
1265
/************************************************************************************//**
1266
** \brief     XCP command processor function which handles the GET_CAL_PAGE command as
1267
**            defined by the protocol.
1268
** \param     data Pointer to a byte buffer with the packet data.
1269
** \return    none
1270
**
1271
****************************************************************************************/
1272
static void XcpCmdGetCalPage(blt_int8u *data)
1273
{
1274
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1275
  /* check if CAL_PAG resource is unlocked */
1276
  if ((xcpInfo.protection & XCP_RES_CALPAG) == XCP_RES_CALPAG)
1277
  {
1278
    /* resource is locked. use seed/key sequence to unlock */
1279
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1280
    return;
1281
  }
1282
#endif
1283

    
1284
  /* set packet id to command response packet */
1285
  xcpInfo.ctoData[0] = XCP_PID_RES;
1286

    
1287
  /* initialize reserved parameters */
1288
  xcpInfo.ctoData[1] = 0;
1289
  xcpInfo.ctoData[2] = 0;
1290

    
1291
  /* store the calibration page */
1292
  xcpInfo.ctoData[3] = XcpCalGetPageHook(data[2]);
1293

    
1294
  /* set packet length */
1295
  xcpInfo.ctoLen = 4;
1296
} /*** end of XcpCmdGetCalPage ***/
1297
#endif /* XCP_RES_PAGING_EN == 1 */
1298

    
1299

    
1300
#if (XCP_RES_PROGRAMMING_EN == 1)
1301
/************************************************************************************//**
1302
** \brief     XCP command processor function which handles the PROGRAM_START command as
1303
**            defined by the protocol.
1304
** \param     data Pointer to a byte buffer with the packet data.
1305
** \return    none
1306
**
1307
****************************************************************************************/
1308
static void XcpCmdProgramStart(blt_int8u *data)
1309
{
1310
  /* suppress compiler warning for unused parameter */
1311
  data = data;
1312

    
1313
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1314
  /* check if PGM resource is unlocked */
1315
  if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM)
1316
  {
1317
    /* resource is locked. use seed/key sequence to unlock */
1318
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1319
    return;
1320
  }
1321
#endif
1322

    
1323
  /* set packet id to command response packet */
1324
  xcpInfo.ctoData[0] = XCP_PID_RES;
1325

    
1326
  /* initialize reserved parameter */
1327
  xcpInfo.ctoData[1] = 0;
1328

    
1329
  /* no special communication mode supported during programming */
1330
  xcpInfo.ctoData[2] = 0;
1331

    
1332
  /* cto packet length stays the same during programming */
1333
  xcpInfo.ctoData[3] = (blt_int8u)XCP_CTO_PACKET_LEN;
1334

    
1335
  /* no block size, st-min time, or queue size supported */
1336
  xcpInfo.ctoData[4] = 0;
1337
  xcpInfo.ctoData[5] = 0;
1338
  xcpInfo.ctoData[6] = 0;
1339

    
1340
  /* set packet length */
1341
  xcpInfo.ctoLen = 7;
1342
} /*** end of XcpCmdProgramStart ***/
1343

    
1344

    
1345
/************************************************************************************//**
1346
** \brief     XCP command processor function which handles the PROGRAM_MAX command as
1347
**            defined by the protocol.
1348
** \param     data Pointer to a byte buffer with the packet data.
1349
** \return    none
1350
**
1351
****************************************************************************************/
1352
static void XcpCmdProgramMax(blt_int8u *data)
1353
{
1354
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1355
  /* check if PGM resource is unlocked */
1356
  if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM)
1357
  {
1358
    /* resource is locked. use seed/key sequence to unlock */
1359
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1360
    return;
1361
  }
1362
#endif
1363

    
1364
  /* program the data */
1365
  if (NvmWrite((blt_addr)xcpInfo.mta, XCP_CTO_PACKET_LEN-1, &data[1]) == 0)
1366
  {
1367
    /* error occurred during programming */
1368
    XcpSetCtoError(XCP_ERR_GENERIC);
1369
    return;
1370
  }
1371

    
1372
  /* set packet id to command response packet */
1373
  xcpInfo.ctoData[0] = XCP_PID_RES;
1374

    
1375
  /* post increment the mta */
1376
  xcpInfo.mta += XCP_CTO_PACKET_LEN-1;
1377

    
1378
  /* set packet length */
1379
  xcpInfo.ctoLen = 1;
1380
} /*** end of XcpCmdProgramMax ***/
1381

    
1382

    
1383
/************************************************************************************//**
1384
** \brief     XCP command processor function which handles the PROGRAM command as
1385
**            defined by the protocol.
1386
** \param     data Pointer to a byte buffer with the packet data.
1387
** \return    none
1388
**
1389
****************************************************************************************/
1390
static void XcpCmdProgram(blt_int8u *data)
1391
{
1392
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1393
  /* check if PGM resource is unlocked */
1394
  if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM)
1395
  {
1396
    /* resource is locked. use seed/key sequence to unlock */
1397
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1398
    return;
1399
  }
1400
#endif
1401

    
1402
  /* validate length of download request */
1403
  if (data[1] > (XCP_CTO_PACKET_LEN-2))
1404
  {
1405
    /* requested data length is too long */
1406
    XcpSetCtoError(XCP_ERR_OUT_OF_RANGE);
1407
    return;
1408
  }
1409

    
1410
  /* set packet id to command response packet */
1411
  xcpInfo.ctoData[0] = XCP_PID_RES;
1412

    
1413
  /* set packet length */
1414
  xcpInfo.ctoLen = 1;
1415

    
1416
  /* end of programming sequence (datasize is 0)? */
1417
  if (data[1] == 0)
1418
  {
1419
    /* call erase/programming cleanup routine */
1420
    if (NvmDone() == BLT_FALSE)
1421
    {
1422
      /* error occurred while finishing up programming */
1423
      XcpSetCtoError(XCP_ERR_GENERIC);
1424
    }
1425
    return;
1426
  }
1427
  /* program the data */
1428
  if (NvmWrite((blt_addr)xcpInfo.mta, data[1], &data[2]) == 0)
1429
  {
1430
    /* error occurred during programming */
1431
    XcpSetCtoError(XCP_ERR_GENERIC);
1432
    return;
1433
  }
1434

    
1435
  /* post increment the mta */
1436
  xcpInfo.mta += data[1];
1437
} /*** end of XcpCmdProgram ***/
1438

    
1439

    
1440
/************************************************************************************//**
1441
** \brief     XCP command processor function which handles the PROGRAM_CLEAR command as
1442
**            defined by the protocol.
1443
** \param     data Pointer to a byte buffer with the packet data.
1444
** \return    none
1445
**
1446
****************************************************************************************/
1447
static void XcpCmdProgramClear(blt_int8u *data)
1448
{
1449
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1450
  /* check if PGM resource is unlocked */
1451
  if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM)
1452
  {
1453
    /* resource is locked. use seed/key sequence to unlock */
1454
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1455
    return;
1456
  }
1457
#endif
1458

    
1459
  /* erase the memory */
1460
  if (NvmErase((blt_addr)xcpInfo.mta, *(blt_int32u*)&data[4]) == 0)
1461
  {
1462
    /* error occurred during erasure */
1463
    XcpSetCtoError(XCP_ERR_GENERIC);
1464
    return;
1465
  }
1466

    
1467
  /* set packet id to command response packet */
1468
  xcpInfo.ctoData[0] = XCP_PID_RES;
1469

    
1470
  /* set packet length */
1471
  xcpInfo.ctoLen = 1;
1472
} /*** end of XcpCmdProgramClear ***/
1473

    
1474

    
1475
/************************************************************************************//**
1476
** \brief     XCP command processor function which handles the PROGRAM_RESET command as
1477
**            defined by the protocol.
1478
** \param     data Pointer to a byte buffer with the packet data.
1479
** \return    none
1480
**
1481
****************************************************************************************/
1482
static void XcpCmdProgramReset(blt_int8u *data)
1483
{
1484
  /* suppress compiler warning for unused parameter */
1485
  data = data;
1486

    
1487
  xcpInfo.connected = 0;
1488
#if (BOOT_GATE_ENABLE > 0)
1489
  xcpInfo.other_connection = 0;
1490
#endif
1491
  setLed(0);
1492

    
1493
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1494
  /* check if PGM resource is unlocked */
1495
  if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM)
1496
  {
1497
    /* resource is locked. use seed/key sequence to unlock */
1498
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1499
    return;
1500
  }
1501
#endif
1502

    
1503
  /* reset the ecu after programming is done. so basically, just start the newly programmed
1504
   * firmware. it is okay if the code does not return here. if CpuReset() is used here, then
1505
   * the bootloader is first activated again, including the backdoor timer which is not
1506
   * desired.
1507
   */
1508
  CpuStartUserProgram();
1509

    
1510
  /* set packet id to command response packet */
1511
  xcpInfo.ctoData[0] = XCP_PID_RES;
1512

    
1513
  /* set packet length */
1514
  xcpInfo.ctoLen = 1;
1515
} /*** end of XcpCmdProgramReset ***/
1516

    
1517

    
1518
/************************************************************************************//**
1519
** \brief     XCP command processor function which handles the PROGRAM_PREPARE command as
1520
**            defined by the protocol.
1521
** \param     data Pointer to a byte buffer with the packet data.
1522
** \return    none
1523
**
1524
****************************************************************************************/
1525
static void XcpCmdProgramPrepare(blt_int8u *data)
1526
{
1527
#if (XCP_SEED_KEY_PROTECTION_EN == 1)
1528
  /* check if PGM resource is unlocked */
1529
  if ((xcpInfo.protection & XCP_RES_PGM) == XCP_RES_PGM)
1530
  {
1531
    /* resource is locked. use seed/key sequence to unlock */
1532
    XcpSetCtoError(XCP_ERR_ACCESS_LOCKED);
1533
    return;
1534
  }
1535
#endif
1536

    
1537
  /* programming with kernel currently not needed and therefore not supported */
1538
  XcpSetCtoError(XCP_ERR_GENERIC);
1539
  return;
1540
} /*** end of XcpCmdProgramPrepare ***/
1541
#endif /* XCP_RES_PROGRAMMING_EN == 1 */
1542

    
1543

    
1544

    
1545
/******************************** end of xcp.c *****************************************/