Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Source / ARMCM3_STM32 / can.c @ 93933a75

History | View | Annotate | Download (24.573 KB)

1
/************************************************************************************//**
2
* \file         Source\ARMCM3_STM32\can.c
3
* \brief        Bootloader CAN communication interface source file.
4
* \ingroup      Target_ARMCM3_STM32
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
#define CAN_DEBUG       (0)
35

    
36
/****************************************************************************************
37
* Include files
38
****************************************************************************************/
39
#include "boot.h"                                /* bootloader generic header          */
40

    
41
#if (CAN_DEBUG > 0)
42
#include <helper.h>
43
#endif
44

    
45

    
46
#if (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
47
/****************************************************************************************
48
* Type definitions
49
****************************************************************************************/
50
/** \brief CAN transmission mailbox layout. */
51
typedef struct
52
{
53
  volatile blt_int32u TIR;
54
  volatile blt_int32u TDTR;
55
  volatile blt_int32u TDLR;
56
  volatile blt_int32u TDHR;
57
} tCanTxMailBox;
58

    
59
/** \brief CAN reception FIFO mailbox layout. */
60
typedef struct
61
{
62
  volatile blt_int32u RIR;
63
  volatile blt_int32u RDTR;
64
  volatile blt_int32u RDLR;
65
  volatile blt_int32u RDHR;
66
} tCanRxFIFOMailBox;
67

    
68
/** \brief CAN filter register layout. */
69
typedef struct
70
{
71
  volatile blt_int32u FR1;
72
  volatile blt_int32u FR2;
73
} tCanFilter;
74

    
75
/** \brief CAN controller register layout. */
76
typedef struct
77
{
78
  volatile blt_int32u MCR;
79
  volatile blt_int32u MSR;
80
  volatile blt_int32u TSR;
81
  volatile blt_int32u RF0R;
82
  volatile blt_int32u RF1R;
83
  volatile blt_int32u IER;
84
  volatile blt_int32u ESR;
85
  volatile blt_int32u BTR;
86
  blt_int32u          RESERVED0[88];
87
  tCanTxMailBox       sTxMailBox[3];
88
  tCanRxFIFOMailBox   sFIFOMailBox[2];
89
  blt_int32u          RESERVED1[12];
90
  volatile blt_int32u FMR;
91
  volatile blt_int32u FM1R;
92
  blt_int32u          RESERVED2;
93
  volatile blt_int32u FS1R;
94
  blt_int32u          RESERVED3;
95
  volatile blt_int32u FFA1R;
96
  blt_int32u          RESERVED4;
97
  volatile blt_int32u FA1R;
98
  blt_int32u          RESERVED5[8];
99
  tCanFilter          sFilterRegister[14];
100
} tCanRegs;
101

    
102

    
103
/****************************************************************************************
104
* Macro definitions
105
****************************************************************************************/
106
/** \brief Reset request bit. */
107
#define CAN_BIT_RESET    ((blt_int32u)0x00008000)
108
/** \brief Initialization request bit. */
109
#define CAN_BIT_INRQ     ((blt_int32u)0x00000001)
110
/** \brief Initialization acknowledge bit. */
111
#define CAN_BIT_INAK     ((blt_int32u)0x00000001)
112
/** \brief Sleep mode request bit. */
113
#define CAN_BIT_SLEEP    ((blt_int32u)0x00000002)
114
/** \brief Filter 0 selection bit. */
115
#define CAN_BIT_FILTER0  ((blt_int32u)0x00000001)
116
/** \brief Filter init mode bit. */
117
#define CAN_BIT_FINIT    ((blt_int32u)0x00000001)
118
/** \brief Transmit mailbox 0 empty bit. */
119
#define CAN_BIT_TME0     ((blt_int32u)0x04000000)
120
/** \brief Transmit mailbox request bit. */
121
#define CAN_BIT_TXRQ     ((blt_int32u)0x00000001)
122
/** \brief Release FIFO 0 mailbox bit. */
123
#define CAN_BIT_RFOM0    ((blt_int32u)0x00000020)
124

    
125
#if (BOOT_GATE_CAN_ENABLE > 0)
126
blt_bool commandSend;
127
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
128

    
129

    
130
/****************************************************************************************
131
* Register definitions
132
****************************************************************************************/
133
/** \brief Macro for accessing CAN controller registers. */
134
#define CANx             ((tCanRegs *) (blt_int32u)0x40006400)
135

    
136

    
137
/****************************************************************************************
138
* Type definitions
139
****************************************************************************************/
140
/** \brief Structure type for grouping CAN bus timing related information. */
141
typedef struct t_can_bus_timing
142
{
143
  blt_int8u tseg1;                                    /**< CAN time segment 1          */
144
  blt_int8u tseg2;                                    /**< CAN time segment 2          */
145
} tCanBusTiming;
146

    
147

    
148
/****************************************************************************************
149
* Local constant declarations
150
****************************************************************************************/
151
/** \brief CAN bittiming table for dynamically calculating the bittiming settings.
152
 *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25
153
 *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC
154
 *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) *
155
 *           100%. This array contains possible and valid time quanta configurations with
156
 *           a sample point between 68..78%.
157
 */
158
static const tCanBusTiming canTiming[] =
159
{                       /*  TQ | TSEG1 | TSEG2 | SP  */
160
                        /* ------------------------- */
161
    {  5, 2 },          /*   8 |   5   |   2   | 75% */
162
    {  6, 2 },          /*   9 |   6   |   2   | 78% */
163
    {  6, 3 },          /*  10 |   6   |   3   | 70% */
164
    {  7, 3 },          /*  11 |   7   |   3   | 73% */
165
    {  8, 3 },          /*  12 |   8   |   3   | 75% */
166
    {  9, 3 },          /*  13 |   9   |   3   | 77% */
167
    {  9, 4 },          /*  14 |   9   |   4   | 71% */
168
    { 10, 4 },          /*  15 |  10   |   4   | 73% */
169
    { 11, 4 },          /*  16 |  11   |   4   | 75% */
170
    { 12, 4 },          /*  17 |  12   |   4   | 76% */
171
    { 12, 5 },          /*  18 |  12   |   5   | 72% */
172
    { 13, 5 },          /*  19 |  13   |   5   | 74% */
173
    { 14, 5 },          /*  20 |  14   |   5   | 75% */
174
    { 15, 5 },          /*  21 |  15   |   5   | 76% */
175
    { 15, 6 },          /*  22 |  15   |   6   | 73% */
176
    { 16, 6 },          /*  23 |  16   |   6   | 74% */
177
    { 16, 7 },          /*  24 |  16   |   7   | 71% */
178
    { 16, 8 }           /*  25 |  16   |   8   | 68% */
179
};
180

    
181

    
182
/************************************************************************************//**
183
** \brief     Search algorithm to match the desired baudrate to a possible bus
184
**            timing configuration.
185
** \param     baud The desired baudrate in kbps. Valid values are 10..1000.
186
** \param     prescaler Pointer to where the value for the prescaler will be stored.
187
** \param     tseg1 Pointer to where the value for TSEG2 will be stored.
188
** \param     tseg2 Pointer to where the value for TSEG2 will be stored.
189
** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE
190
**            otherwise.
191
**
192
****************************************************************************************/
193
static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler,
194
                                  blt_int8u *tseg1, blt_int8u *tseg2)
195
{
196
  blt_int8u  cnt;
197

    
198
  /* loop through all possible time quanta configurations to find a match */
199
  for (cnt=0; cnt < sizeof(canTiming)/sizeof(canTiming[0]); cnt++)
200
  {
201
    if (((BOOT_CPU_SYSTEM_SPEED_KHZ/2) % (baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1))) == 0)
202
    {
203
      /* compute the prescaler that goes with this TQ configuration */
204
      *prescaler = (BOOT_CPU_SYSTEM_SPEED_KHZ/2)/(baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1));
205

    
206
      /* make sure the prescaler is valid */
207
      if ( (*prescaler > 0) && (*prescaler <= 1024) )
208
      {
209
        /* store the bustiming configuration */
210
        *tseg1 = canTiming[cnt].tseg1;
211
        *tseg2 = canTiming[cnt].tseg2;
212
        /* found a good bus timing configuration */
213
        return BLT_TRUE;
214
      }
215
    }
216
  }
217
  /* could not find a good bus timing configuration */
218
  return BLT_FALSE;
219
} /*** end of CanGetSpeedConfig ***/
220

    
221

    
222
/************************************************************************************//**
223
** \brief     Initializes the CAN controller and synchronizes it to the CAN bus.
224
** \return    none.
225
**
226
****************************************************************************************/
227
void CanInit(void)
228
{
229
  blt_int16u prescaler;
230
  blt_int8u  tseg1, tseg2;
231
  blt_bool   result;
232

    
233
#if (BOOT_GATE_CAN_ENABLE > 0)
234
  commandSend = BLT_FALSE;
235
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
236

    
237
  /* the current implementation supports CAN1. throw an assertion error in case a
238
   * different CAN channel is configured.
239
   */
240
  ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0);
241
  /* obtain bittiming configuration information */
242
  result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2);
243
  ASSERT_RT(result == BLT_TRUE);
244
  /* disable all can interrupt. this driver works in polling mode */
245
  CANx->IER = (blt_int32u)0;
246
  /* set request to reset the can controller */
247
  CANx->MCR |= CAN_BIT_RESET ;
248
  /* wait for acknowledge that the can controller was reset */
249
  while ((CANx->MCR & CAN_BIT_RESET) != 0)
250
  {
251
    /* keep the watchdog happy */
252
    CopService();
253
  }
254
  /* exit from sleep mode, which is the default mode after reset */
255
  CANx->MCR &= ~CAN_BIT_SLEEP;
256
  /* set request to enter initialisation mode */
257
  CANx->MCR |= CAN_BIT_INRQ ;
258
  /* wait for acknowledge that initialization mode was entered */
259
  while ((CANx->MSR & CAN_BIT_INAK) == 0)
260
  {
261
    /* keep the watchdog happy */
262
    CopService();
263
  }
264
  /* configure the bittming */
265
  CANx->BTR = (blt_int32u)((blt_int32u)(tseg1 - 1) << 16) | \
266
              (blt_int32u)((blt_int32u)(tseg2 - 1) << 20) | \
267
              (blt_int32u)(prescaler - 1);
268
  /* set request to leave initialisation mode */
269
  CANx->MCR &= ~CAN_BIT_INRQ;
270
  /* wait for acknowledge that initialization mode was exited */
271
  while ((CANx->MSR & CAN_BIT_INAK) != 0)
272
  {
273
    /* keep the watchdog happy */
274
    CopService();
275
  }
276
  /* enter initialisation mode for the acceptance filter */
277
  CANx->FMR |= CAN_BIT_FINIT;
278
  /* deactivate filter 0 */
279
  CANx->FA1R &= ~CAN_BIT_FILTER0;
280
  /* 32-bit scale for the filter */
281
  CANx->FS1R |= CAN_BIT_FILTER0;
282
  /* open up the acceptance filter to receive all messages */
283
  CANx->sFilterRegister[0].FR1 = 0;
284
  CANx->sFilterRegister[0].FR2 = 0;
285
  /* select id/mask mode for the filter */
286
  CANx->FM1R &= ~CAN_BIT_FILTER0;
287
  /* FIFO 0 assignation for the filter */
288
  CANx->FFA1R &= ~CAN_BIT_FILTER0;
289
  /* filter activation */
290
  CANx->FA1R |= CAN_BIT_FILTER0;
291
  /* leave initialisation mode for the acceptance filter */
292
  CANx->FMR &= ~CAN_BIT_FINIT;
293
} /*** end of CanInit ***/
294

    
295

    
296
/************************************************************************************//**
297
** \brief     Transmits a packet formatted for the communication interface.
298
** \param     data     Pointer to byte array with data that it to be transmitted.
299
** \param     len      Number of bytes that are to be transmitted.
300
** \param     deviceID ID of the device the data has to be sent to.
301
** \return    none.
302
**
303
****************************************************************************************/
304
void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID)
305
{
306
  /* make sure that transmit mailbox 0 is available */
307
  ASSERT_RT((CANx->TSR&CAN_BIT_TME0) == CAN_BIT_TME0);
308

    
309
  blt_int32u address;
310
#if (BOOT_GATE_CAN_ENABLE > 0)
311
  if (deviceID == 0) {
312
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
313
    address = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
314
#if (BOOT_GATE_CAN_ENABLE > 0)
315
    commandSend = BLT_FALSE;
316
  } else {
317
    address = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
318
    commandSend = BLT_TRUE;
319
  }
320
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
321

    
322
  /* init variables */
323
  blt_int8u canData[8];
324
  blt_int8u restLen = len;
325
  blt_int8u canIdx = 0;
326
  blt_int32u ackMsgId;
327
  blt_int8u ackMsgLen;
328

    
329
  /* send the given package in 8 byte packages */
330
  while (restLen > 0) {
331
    /* build the message identifier */
332
    CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
333
    CANx->sTxMailBox[0].TIR |= (address << 21);
334

    
335
    /* if this is the first transmission of this packet */
336
    if (restLen == len) {
337

    
338
      /* store the message date length code (DLC) */
339
      CANx->sTxMailBox[0].TDTR = (restLen > 4) ? 8 : restLen+1+4;
340

    
341
      /* store the device ID */
342
      canData[0] = (blt_int8u)(0xFF & (deviceID >> 0));
343
      canData[1] = (blt_int8u)(0xFF & (deviceID >> 8));
344
      canData[2] = (blt_int8u)(0xFF & (deviceID >> 16));
345
      canData[3] = (blt_int8u)(0xFF & (deviceID >> 24));
346

    
347
      /* store the remaining packet length */
348
      canData[4] = restLen;
349

    
350
      canIdx = 5;
351
    }
352
    /* if this is a succeeding transmission of this packet */
353
    else {
354

    
355
      /* store the message date length code (DLC) */
356
      CANx->sTxMailBox[0].TDTR = (restLen > 7) ? 8 : restLen+1;
357

    
358
      /* store the remaining packet length */
359
      canData[0] = restLen;
360

    
361
      canIdx = 1;
362
    }
363

    
364
    /* store the packet payload */
365
    while (restLen > 0 && canIdx < 8) {
366
      canData[canIdx] = data[len-restLen];
367
      canIdx++;
368
      restLen--;
369
    }
370
    /* fill rest with nulls */
371
    while (canIdx < 8) {
372
      canData[canIdx] = 0;
373
      canIdx++;
374
    }
375

    
376
    /* store the message data bytes */
377
    CANx->sTxMailBox[0].TDLR = (((blt_int32u)canData[3] << 24) | \
378
                                ((blt_int32u)canData[2] << 16) | \
379
                                ((blt_int32u)canData[1] <<  8) | \
380
                                ((blt_int32u)canData[0]));
381
    CANx->sTxMailBox[0].TDHR = (((blt_int32u)canData[7] << 24) | \
382
                                ((blt_int32u)canData[6] << 16) | \
383
                                ((blt_int32u)canData[5] <<  8) | \
384
                                ((blt_int32u)canData[4]));
385

    
386
    /* request the start of message transmission */
387
    CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
388
    /* wait for transmit completion */
389
    while ((CANx->TSR&CAN_BIT_TME0) == 0)
390
    {
391
      /* keep the watchdog happy */
392
      CopService();
393
    }
394

    
395
    /* wait for the acknowledgement transmission */
396
    while ((CANx->RF0R&(blt_int32u)0x00000003) == 0) {
397
      /* keep the watchdog happy */
398
      CopService();
399
    }
400

    
401
    /* read out the message identifier, length and payload */
402
    ackMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
403
    ackMsgLen = (blt_int8u)0x0F & CANx->sFIFOMailBox[0].RDTR;
404
    canData[0] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDLR;
405
    canData[1] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 8);
406
    canData[2] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 16);
407
    canData[3] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 24);
408
    canData[4] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDHR;
409
    canData[5] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 8);
410
    canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
411
    canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
412

    
413
#if (CAN_DEBUG > 0)
414
    /* verification:
415
     * - ID must be "address & BOOT_COM_CAN_MSG_ACK"
416
     * - length must be 1
417
     * - canData[0] must b equal to restLen
418
     */
419
    if (ackMsgId != (address | (blt_int32u)BOOT_COM_CAN_MSG_ACK) ||
420
        ackMsgLen != 1 ||
421
        canData[0] != restLen) {
422
      /* some error occurred */
423
      blinkSOS(1);
424
      msleep(500);
425
      visualizeData((blt_int8u*)&ackMsgId, 2, 1);
426
      msleep(500);
427
      visualizeByte(ackMsgLen, 1);
428
      msleep(500);
429
      visualizeByte(canData[0], 1);
430
      msleep(500);
431
      visualizeByte(restLen, 1);
432
      blinkSOSinf();
433
    }
434
#endif /* CAN_DEBUG > 0 */
435

    
436
    /* release FIFO0 */
437
    CANx->RF0R |= CAN_BIT_RFOM0;
438

    
439
    /* modify address so that receivers can filter */
440
    address |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
441
  }
442
} /*** end of CanTransmitPacket ***/
443

    
444

    
445
/************************************************************************************//**
446
** \brief     Receives a communication interface packet if one is present.
447
** \param     data Pointer to byte array where the data is to be stored.
448
** \return    Length of message (if the message is invalid, the length will be 0).
449
**
450
****************************************************************************************/
451
blt_int8u CanReceivePacket(blt_int8u *data)
452
{
453
  blt_int32u rxMsgId;
454
  blt_bool   result = BLT_FALSE;
455
  blt_int8u  length = 0;
456

    
457
  static blt_int8u readData[BOOT_COM_RX_MAX_DATA];
458
  static blt_int8u receivedLen = 0;
459
  static blt_int8u lastLen = 0;
460
  static blt_int8u toReceive = 0;
461
  blt_int8u canData[8];
462
  blt_int8u restLen;
463
  blt_int8u canLength;
464
  blt_int8u idx;
465

    
466
  blt_int32u compID;
467
#if (BOOT_GATE_CAN_ENABLE > 0)
468
  if (commandSend == BLT_TRUE) {
469
    compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
470
  } else {
471
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
472
    compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
473
#if (BOOT_GATE_CAN_ENABLE > 0)
474
  }
475
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
476

    
477
  /* check if a new message was received  or is more to come */
478
  while ((CANx->RF0R&(blt_int32u)0x00000003) > 0 || receivedLen < toReceive)
479
  {
480
    /* wait for a transmission if required */
481
    while (receivedLen < toReceive && (CANx->RF0R&(blt_int32u)0x00000003) == 0) {
482
      /* keep the watchdog happy */
483
      CopService();
484
    }
485

    
486
    /* read out the message identifier */
487
    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
488
    /* is this the packet identifier */
489
    if (rxMsgId == compID)
490
    {
491
      result = BLT_TRUE;
492

    
493
      /* save length */
494
      canLength = (blt_int8u)0x0F & CANx->sFIFOMailBox[0].RDTR;
495
      /* store the received packet data */
496
      canData[0] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDLR;
497
      canData[1] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 8);
498
      canData[2] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 16);
499
      canData[3] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 24);
500
      canData[4] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDHR;
501
      canData[5] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 8);
502
      canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
503
      canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
504

    
505
#if (CAN_DEBUG > 0)
506
      if ((receivedLen == 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) != 0) ||
507
          (receivedLen > 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) == 0)) {
508
        blinkSOS(4);
509
        msleep(500);
510
        visualizeByte(toReceive, 1);
511
        msleep(500);
512
        visualizeByte(receivedLen, 1);
513
        msleep(500);
514
        visualizeData((blt_int8u*)&rxMsgId, 2, 1);
515
        msleep(500);
516
        blinkSOSinf();
517
      }
518
#endif /* CAN_DEBUG > 0 */
519

    
520
      /* if this is the first transmission of this packet */
521
      if (receivedLen == 0) {
522
        /* abort if the message was meant for someone else */
523
        blt_int32u deviceID = (((blt_int32u)canData[3]) << 24) | \
524
                              (((blt_int32u)canData[2]) << 16) | \
525
                              (((blt_int32u)canData[1]) <<  8) | \
526
                              (((blt_int32u)canData[0]));
527
#if (BOOT_GATE_ENABLE > 0)
528
#if defined(BOOT_COM_DEVICE_LEGACY_ID)
529
        if ((commandSend == BLT_TRUE && deviceID == 0) ||
530
            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID || deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID))) {
531
#else
532
        if ((commandSend == BLT_TRUE && deviceID == 0) ||
533
            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID))) {
534
#endif
535
#else
536
#if defined(BOOT_COM_DEVICE_LEGACY_ID)
537
        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID ||
538
            deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID) {
539
#else
540
        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) {
541
#endif
542
#endif
543
          /* store length of the packet */
544
          toReceive = canData[4];
545
          lastLen = canData[4];
546
          idx = 5;
547

    
548
          /* modify the listening address for filtering of subsequent transmissions */
549
          compID |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
550
        } else {
551
          /* release FIFO0 */
552
          CANx->RF0R |= CAN_BIT_RFOM0;
553
          break;
554
        }
555
      }
556
      /* if this is a subsequent transmission of a packet */
557
      else {
558
        /* store rest length and check if possible */
559
        restLen = canData[0];
560
#if (CAN_DEBUG > 0)
561
        if (restLen != toReceive-receivedLen ||
562
            canLength > restLen+1 ||
563
            lastLen-restLen != ((lastLen==toReceive) ? 3 : 7)) {
564
          /* transmission has been lost */
565
          blinkSOS(2);
566
          msleep(500);
567
          visualizeData((blt_int8u*)&rxMsgId, 4, 1);
568
          msleep(500);
569
          visualizeByte(toReceive, 1);
570
          msleep(500);
571
          visualizeByte(receivedLen, 1);
572
          msleep(500);
573
          visualizeByte(lastLen, 1);
574
          msleep(500);
575
          visualizeByte(restLen, 1);
576
          msleep(500);
577
          visualizeByte(canLength, 1);
578
          msleep(500);
579
          visualizeData(readData, receivedLen, 1);
580
          blinkSOSinf();
581
        }
582
#endif /* CAN_DEBUG > 0 */
583
        lastLen = restLen;
584
        idx = 1;
585
      }
586

    
587
      /* store the payload */
588
      for (; idx < canLength; idx++) {
589
        readData[receivedLen] = canData[idx];
590
        receivedLen++;
591
      }
592

    
593
      /* release FIFO0 */
594
      CANx->RF0R |= CAN_BIT_RFOM0;
595

    
596
      /* send acknowledgement */
597
      CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
598
      CANx->sTxMailBox[0].TIR |= ((rxMsgId | (blt_int32u)BOOT_COM_CAN_MSG_ACK) << 21);
599
      CANx->sTxMailBox[0].TDTR = 1;
600
      CANx->sTxMailBox[0].TDLR = (((blt_int32u)0 << 24) | \
601
                                  ((blt_int32u)0 << 16) | \
602
                                  ((blt_int32u)0 <<  8) | \
603
                                  ((blt_int32u)(toReceive-receivedLen)));
604
      CANx->sTxMailBox[0].TDHR = (((blt_int32u)0 << 24) | \
605
                                  ((blt_int32u)0 << 16) | \
606
                                  ((blt_int32u)0 <<  8) | \
607
                                  ((blt_int32u)0));
608

    
609
      /* request the start of message transmission */
610
      CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
611
      /* wait for transmit completion */
612
      while ((CANx->TSR&CAN_BIT_TME0) == 0)
613
      {
614
        /* keep the watchdog happy */
615
        CopService();
616
      }
617

    
618
      /* check if full package has been received */
619
      if (receivedLen == toReceive) {
620
#if (BOOT_GATE_CAN_ENABLE > 0)
621
        commandSend = BLT_FALSE;
622
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
623
        for (idx = 0; idx < toReceive; idx++) {
624
          data[idx] = readData[idx];
625
        }
626
        length = toReceive;
627
        /* reset static variables */
628
        receivedLen = 0;
629
        toReceive = 0;
630
        break;
631
      } else {
632
#if (CAN_DEBUG > 0)
633
        if (receivedLen > toReceive) {
634
          /* something strange happened */
635
          blinkSOS(3);
636
          msleep(500);
637
          visualizeByte(toReceive, 1);
638
          msleep(500);
639
          visualizeByte(receivedLen, 1);
640
          blinkSOSinf();
641
        }
642
#endif /* CAN_DEBUG > 0 */
643
        length = 0;
644
      }
645
    } else {
646
      /* release FIFO0 */
647
      CANx->RF0R |= CAN_BIT_RFOM0;
648
    }
649
  }
650

    
651
  return length;
652
} /*** end of CanReceivePacket ***/
653
#endif /* BOOT_COM_CAN_ENABLE > 0  || BOOT_GATE_CAN_ENABLE > 0 */
654

    
655

    
656
/*********************************** end of can.c **************************************/