Statistics
| Branch: | Tag: | Revision:

amiro-blt / Target / Source / ARMCM4_STM32 / can.c @ f7d2c786

History | View | Annotate | Download (28.617 KB)

1
/************************************************************************************//**
2
* \file         Source\ARMCM4_STM32\can.c
3
* \brief        Bootloader CAN communication interface source file.
4
* \ingroup      Target_ARMCM4_STM32
5
* \internal
6
*----------------------------------------------------------------------------------------
7
*                          C O P Y R I G H T
8
*----------------------------------------------------------------------------------------
9
*   Copyright (c) 2013  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[28];
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 14 selection bit. */
117
#define CAN_BIT_FILTER14 ((blt_int32u)0x00004000)
118
/** \brief Filter init mode bit. */
119
#define CAN_BIT_FINIT    ((blt_int32u)0x00000001)
120
/** \brief Transmit mailbox 0 empty bit. */
121
#define CAN_BIT_TME0     ((blt_int32u)0x04000000)
122
/** \brief Transmit mailbox request bit. */
123
#define CAN_BIT_TXRQ     ((blt_int32u)0x00000001)
124
/** \brief Release FIFO 0 mailbox bit. */
125
#define CAN_BIT_RFOM0    ((blt_int32u)0x00000020)
126

    
127
#if (BOOT_GATE_CAN_ENABLE > 0)
128
blt_bool commandSend;
129
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
130

    
131

    
132
/****************************************************************************************
133
* Register definitions
134
****************************************************************************************/
135
#if (BOOT_COM_CAN_CHANNEL_INDEX == 0)
136
/** \brief Macro for accessing CAN1 controller registers. */
137
#define CANx             ((tCanRegs *) (blt_int32u)0x40006400)
138
#else
139
/** \brief Macro for accessing CAN2 controller registers. */
140
#define CANx             ((tCanRegs *) (blt_int32u)0x40006800)
141
#endif
142
/** \brief Macro for accessing CAN1 controller registers. */
143
#define CAN1             ((tCanRegs *) (blt_int32u)0x40006400)
144

    
145

    
146
/****************************************************************************************
147
* Type definitions
148
****************************************************************************************/
149
/** \brief Structure type for grouping CAN bus timing related information. */
150
typedef struct t_can_bus_timing
151
{
152
  blt_int8u tseg1;                                    /**< CAN time segment 1          */
153
  blt_int8u tseg2;                                    /**< CAN time segment 2          */
154
} tCanBusTiming;
155

    
156

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

    
190
int counter = 0;
191
/************************************************************************************//**
192
** \brief     Search algorithm to match the desired baudrate to a possible bus
193
**            timing configuration.
194
** \param     baud The desired baudrate in kbps. Valid values are 10..1000.
195
** \param     prescaler Pointer to where the value for the prescaler will be stored.
196
** \param     tseg1 Pointer to where the value for TSEG2 will be stored.
197
** \param     tseg2 Pointer to where the value for TSEG2 will be stored.
198
** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE
199
**            otherwise.
200
**
201
****************************************************************************************/
202
static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler,
203
                                  blt_int8u *tseg1, blt_int8u *tseg2)
204
{
205
  blt_int8u  cnt;
206

    
207
  /* loop through all possible time quanta configurations to find a match */
208
  for (cnt=0; cnt < sizeof(canTiming)/sizeof(canTiming[0]); cnt++)
209
  {
210
    if (((BOOT_CPU_SYSTEM_SPEED_KHZ/4) % (baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1))) == 0)
211
    {
212
      /* compute the prescaler that goes with this TQ configuration */
213
      *prescaler = (BOOT_CPU_SYSTEM_SPEED_KHZ/4)/(baud*(canTiming[cnt].tseg1+canTiming[cnt].tseg2+1));
214

    
215
      /* make sure the prescaler is valid */
216
      if ( (*prescaler > 0) && (*prescaler <= 1024) )
217
      {
218
        /* store the bustiming configuration */
219
        *tseg1 = canTiming[cnt].tseg1;
220
        *tseg2 = canTiming[cnt].tseg2;
221
        /* found a good bus timing configuration */
222
        return BLT_TRUE;
223
      }
224
    }
225
  }
226
  /* could not find a good bus timing configuration */
227
  return BLT_FALSE;
228
} /*** end of CanGetSpeedConfig ***/
229

    
230

    
231
/************************************************************************************//**
232
** \brief     Initializes the CAN controller and synchronizes it to the CAN bus.
233
** \return    none.
234
**
235
****************************************************************************************/
236
void CanInit(void)
237
{
238
  blt_int16u prescaler;
239
  blt_int8u  tseg1, tseg2;
240
  blt_bool   result;
241

    
242
#if (BOOT_GATE_CAN_ENABLE > 0)
243
  commandSend = BLT_FALSE;
244
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
245

    
246
  /* the current implementation supports CAN1 and 2. throw an assertion error in case a
247
   * different CAN channel is configured.
248
   */
249
  ASSERT_CT((BOOT_COM_CAN_CHANNEL_INDEX == 0 || BOOT_COM_CAN_CHANNEL_INDEX == 1));
250

    
251
  /* obtain bittiming configuration information */
252
  result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2);
253
  ASSERT_RT(result == BLT_TRUE);
254
  /* disable all can interrupt. this driver works in polling mode */
255
  CANx->IER = (blt_int32u)0;
256
  /* set request to reset the can controller */
257
  CANx->MCR |= CAN_BIT_RESET ;
258
  /* wait for acknowledge that the can controller was reset */
259
  while ((CANx->MCR & CAN_BIT_RESET) != 0)
260
  {
261
    /* keep the watchdog happy */
262
    CopService();
263
  }
264
  /* exit from sleep mode, which is the default mode after reset */
265
  CANx->MCR &= ~CAN_BIT_SLEEP;
266
  /* set request to enter initialisation mode */
267
  CANx->MCR |= CAN_BIT_INRQ ;
268
  /* wait for acknowledge that initialization mode was entered */
269
  while ((CANx->MSR & CAN_BIT_INAK) == 0)
270
  {
271
    /* keep the watchdog happy */
272
    CopService();
273
  }
274
  /* configure the bittming */
275
  CANx->BTR = (blt_int32u)((blt_int32u)(3) << 24) | \
276
              (blt_int32u)((blt_int32u)(tseg1 - 1) << 16) | \
277
              (blt_int32u)((blt_int32u)(tseg2 - 1) << 20) | \
278
              (blt_int32u)(prescaler - 1);
279
//  CANx->BTR = (blt_int32u)((blt_int32u)(tseg1 - 1) << 16) | \
280
              (blt_int32u)((blt_int32u)(tseg2 - 1) << 20) | \
281
              (blt_int32u)(prescaler - 1) | \
282
              (blt_int32u)(0x3 << 30);
283
//  CANx->BTR = (blt_int32u)((blt_int32u)(15) << 16) | \
284
              (blt_int32u)((blt_int32u)(3) << 20) | \
285
              (blt_int32u)((blt_int32u)(1) << 24) | \
286
              (blt_int32u)(1) | \
287
              (blt_int32u)(0x3 << 30);
288
  /* set request to leave initialisation mode */
289
  CANx->MCR &= ~CAN_BIT_INRQ;
290
  /* wait for acknowledge that initialization mode was exited */
291
  while ((CANx->MSR & CAN_BIT_INAK) != 0)
292
  {
293
    /* keep the watchdog happy */
294
    CopService();
295
  }
296

    
297
#if (BOOT_COM_CAN_CHANNEL_INDEX == 0)
298
  /* enter initialisation mode for the acceptance filter */
299
  CAN1->FMR |= CAN_BIT_FINIT;
300
  /* deactivate filter 0 */
301
  CAN1->FA1R &= ~CAN_BIT_FILTER0;
302
  /* 32-bit scale for the filter */
303
  CAN1->FS1R |= CAN_BIT_FILTER0;
304
  /* open up the acceptance filter to receive all messages */
305
  CAN1->sFilterRegister[0].FR1 = 0;
306
  CAN1->sFilterRegister[0].FR2 = 0;
307
  /* select id/mask mode for the filter */
308
  CAN1->FM1R &= ~CAN_BIT_FILTER0;
309
  /* FIFO 0 assignation for the filter */
310
  CAN1->FFA1R &= ~CAN_BIT_FILTER0;
311
  /* filter activation */
312
  CAN1->FA1R |= CAN_BIT_FILTER0;
313
  /* leave initialisation mode for the acceptance filter */
314
  CAN1->FMR &= ~CAN_BIT_FINIT;
315
#else
316
  /* enter initialisation mode for the acceptance filter */
317
  CAN1->FMR |= CAN_BIT_FINIT;
318
  /* deactivate filter 14 */
319
  CAN1->FA1R &= ~CAN_BIT_FILTER14;
320
  /* 32-bit scale for the filter */
321
  CAN1->FS1R |= CAN_BIT_FILTER14;
322
  /* open up the acceptance filter to receive all messages */
323
  CAN1->sFilterRegister[14].FR1 = 0;
324
  CAN1->sFilterRegister[14].FR2 = 0;
325
  /* select id/mask mode for the filter */
326
  CAN1->FM1R &= ~CAN_BIT_FILTER14;
327
  /* FIFO 0 assignation for the filter */
328
  CAN1->FFA1R &= ~CAN_BIT_FILTER14;
329
  /* filter activation */
330
  CAN1->FA1R |= CAN_BIT_FILTER14;
331
  /* leave initialisation mode for the acceptance filter */
332
  CAN1->FMR &= ~CAN_BIT_FINIT;
333
#endif
334
} /*** end of CanInit ***/
335

    
336

    
337
/************************************************************************************//**
338
** \brief     Transmits a packet formatted for the communication interface.
339
** \param     data Pointer to byte array with data that it to be transmitted.
340
** \param     len  Number of bytes that are to be transmitted.
341
** \return    none.
342
**
343
****************************************************************************************/
344
void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID)
345
{
346
  /* make sure that transmit mailbox 0 is available */
347
  ASSERT_RT((CANx->TSR&CAN_BIT_TME0) == CAN_BIT_TME0);
348

    
349
  blt_int32u address;
350
#if (BOOT_GATE_CAN_ENABLE > 0)
351
  if (deviceID == 0) {
352
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
353
    address = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
354
#if (BOOT_GATE_CAN_ENABLE > 0)
355
    commandSend = BLT_FALSE;
356
  } else {
357
    address = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
358
    commandSend = BLT_TRUE;
359
  }
360
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
361

    
362
  /* init variables */
363
  blt_int8u canData[8];
364
  blt_int8u restLen = len;
365
  blt_int8u canIdx = 0;
366
  blt_int32u ackMsgId;
367
  blt_int8u ackMsgLen;
368

    
369
  /* send the given package in 8 byte packages */
370
  while (restLen > 0) {
371
    /* build the message identifier */
372
    CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
373
    CANx->sTxMailBox[0].TIR |= (address << 21);
374

    
375
    /* if this is the first transmission of this packet */
376
    if (restLen == len) {
377

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

    
381
      /* store the device ID */
382
      canData[0] = (blt_int8u)(0xFF & (deviceID >> 0));
383
      canData[1] = (blt_int8u)(0xFF & (deviceID >> 8));
384
      canData[2] = (blt_int8u)(0xFF & (deviceID >> 16));
385
      canData[3] = (blt_int8u)(0xFF & (deviceID >> 24));
386

    
387
      /* store the remaining packet length */
388
      canData[4] = restLen;
389

    
390
      canIdx = 5;
391
    }
392
    /* if this is a succeeding transmission of this packet */
393
    else {
394

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

    
398
      /* store the remaining packet length */
399
      canData[0] = restLen;
400

    
401
      canIdx = 1;
402
    }
403

    
404
    /* store the packet payload */
405
    while (restLen > 0 && canIdx < 8) {
406
      canData[canIdx] = data[len-restLen];
407
      canIdx++;
408
      restLen--;
409
    }
410
    /* fill rest with nulls */
411
    while (canIdx < 8) {
412
      canData[canIdx] = 0;
413
      canIdx++;
414
    }
415

    
416
    /* store the message data bytes */
417
    CANx->sTxMailBox[0].TDLR = (((blt_int32u)canData[3] << 24) | \
418
                                ((blt_int32u)canData[2] << 16) | \
419
                                ((blt_int32u)canData[1] <<  8) | \
420
                                ((blt_int32u)canData[0]));
421
    CANx->sTxMailBox[0].TDHR = (((blt_int32u)canData[7] << 24) | \
422
                                ((blt_int32u)canData[6] << 16) | \
423
                                ((blt_int32u)canData[5] <<  8) | \
424
                                ((blt_int32u)canData[4]));
425

    
426
    /* request the start of message transmission */
427
    CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
428
    /* wait for transmit completion */
429
    while ((CANx->TSR&CAN_BIT_TME0) == 0)
430
    {
431
      /* keep the watchdog happy */
432
      CopService();
433
    }
434

    
435
    /* wait for the acknowledgement transmission */
436
    while ((CANx->RF0R&(blt_int32u)0x00000003) == 0) {
437
      /* keep the watchdog happy */
438
      CopService();
439
    }
440

    
441
    /* read out the message identifier, length and payload */
442
    ackMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
443
    ackMsgLen = (blt_int8u)0x0F & CANx->sFIFOMailBox[0].RDTR;
444
    canData[0] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDLR;
445
    canData[1] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 8);
446
    canData[2] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 16);
447
    canData[3] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 24);
448
    canData[4] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDHR;
449
    canData[5] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 8);
450
    canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
451
    canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
452

    
453
#if (CAN_DEBUG > 0)
454
    /* verification:
455
     * - ID must be "address & BOOT_COM_CAN_MSG_ACK"
456
     * - length must be 1
457
     * - canData[0] must b equal to restLen
458
     */
459
    if (ackMsgId != (address | (blt_int32u)BOOT_COM_CAN_MSG_ACK) ||
460
        ackMsgLen != 1 ||
461
        canData[0] != restLen) {
462
      /* some error occurred */
463
      blinkSOS(1);
464
      msleep(500);
465
      visualizeData((blt_int8u*)&ackMsgId, 2, 1);
466
      msleep(500);
467
      visualizeByte(ackMsgLen, 1);
468
      msleep(500);
469
      visualizeByte(canData[0], 1);
470
      msleep(500);
471
      visualizeByte(restLen, 1);
472
      blinkSOSinf();
473
    }
474
#endif /* CAN_DEBUG > 0 */
475

    
476
    /* release FIFO0 */
477
    CANx->RF0R |= CAN_BIT_RFOM0;
478

    
479
    /* modify address so that receivers can filter */
480
    address |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
481
  }
482
} /*** end of CanTransmitSinglePacket ***/
483

    
484

    
485
/************************************************************************************//**
486
** \brief     Transmits many packets formatted for the communication interface.
487
** \param     data Pointer to byte array with data that it to be transmitted.
488
** \param     len  Number of bytes that are to be transmitted.
489
** \return    none.
490

491
**
492
****************************************************************************************/
493
/*void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
494
{
495
  static blt_int8u canPacketData[8];
496

497
  canPacketData[0] = len;
498
  blt_int8u restLength = len;
499
  while (restLength > 0) {
500
    blt_int8u canIdx = 0;
501
    if (restLength == len) {
502
      canIdx = 1;
503
    }
504

505
/*    while (restLength > 0 && canIdx < 8) {
506
      canPacketData[canIdx] = data[len-restLength];
507
      canIdx++;
508
      restLength--;
509
    }*/
510
/*    blt_int8u dataLength = 8;
511
    if (dataLength > restLength) {
512
      dataLength = restLength;
513
    }
514
    CpuMemCopy((blt_int32u)&canPacketData[1], (blt_int32u)&data[], toReceive);
515

516
    CanTransmitSinglePacket(canPacketData, canIdx, deviceID);
517
  }
518
} /*** end of CanTransmitPacket ***/
519

    
520

    
521
/************************************************************************************//**
522
** \brief     Receives a communication interface packet if one is present.
523
** \param     data Pointer to byte array where the data is to be stored.
524
** \return    Length of message (if the message is invalid, the length will be 0).
525
**
526
****************************************************************************************/
527
blt_int8u CanReceivePacket(blt_int8u *data)
528
{
529
  blt_int32u rxMsgId;
530
  blt_bool   result = BLT_FALSE;
531
  blt_int8u  length = 0;
532

    
533
  static blt_int8u readData[BOOT_COM_RX_MAX_DATA];
534
  static blt_int8u receivedLen = 0;
535
  static blt_int8u lastLen = 0;
536
  static blt_int8u toReceive = 0;
537
  blt_int8u canData[8];
538
  blt_int8u restLen;
539
  blt_int8u canLength;
540
  blt_int8u idx;
541

    
542
  blt_int32u compID;
543
#if (BOOT_GATE_CAN_ENABLE > 0)
544
  if (commandSend == BLT_TRUE) {
545
    compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
546
  } else {
547
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
548
    compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
549
#if (BOOT_GATE_CAN_ENABLE > 0)
550
  }
551
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
552

    
553
  /* check if a new message was received  or is more to come */
554
  while ((CANx->RF0R&(blt_int32u)0x00000003) > 0 || receivedLen < toReceive)
555
  {
556
    /* wait for a transmission if required */
557
    while (receivedLen < toReceive && (CANx->RF0R&(blt_int32u)0x00000003) == 0) {
558
      /* keep the watchdog happy */
559
      CopService();
560
    }
561

    
562
    /* read out the message identifier */
563
    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
564
    /* is this the packet identifier */
565
    if (rxMsgId == compID)
566
    {
567
      result = BLT_TRUE;
568

    
569
      /* save length */
570
      canLength = (blt_int8u)0x0F & CANx->sFIFOMailBox[0].RDTR;
571
      /* store the received packet data */
572
      canData[0] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDLR;
573
      canData[1] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 8);
574
      canData[2] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 16);
575
      canData[3] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDLR >> 24);
576
      canData[4] = (blt_int8u)0xFF & CANx->sFIFOMailBox[0].RDHR;
577
      canData[5] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 8);
578
      canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
579
      canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
580

    
581
#if (CAN_DEBUG > 0)
582
      if ((receivedLen == 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) != 0) ||
583
          (receivedLen > 0 && (rxMsgId & (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT) == 0)) {
584
        blinkSOS(4);
585
        msleep(500);
586
        visualizeByte(toReceive, 1);
587
        msleep(500);
588
        visualizeByte(receivedLen, 1);
589
        msleep(500);
590
        visualizeData((blt_int8u*)&rxMsgId, 2, 1);
591
        msleep(500);
592
        blinkSOSinf();
593
      }
594
#endif /* CAN_DEBUG > 0 */
595

    
596
      /* if this is the first transmission of this packet */
597
      if (receivedLen == 0) {
598
        /* abort if the message was meant for someone else */
599
        blt_int32u deviceID = (((blt_int32u)canData[3]) << 24) | \
600
                              (((blt_int32u)canData[2]) << 16) | \
601
                              (((blt_int32u)canData[1]) <<  8) | \
602
                              (((blt_int32u)canData[0]));
603
#if (BOOT_GATE_ENABLE > 0)
604
#if defined(BOOT_COM_DEVICE_LEGACY_ID)
605
        if ((commandSend == BLT_TRUE && deviceID == 0) ||
606
            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID || deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID))) {
607
#else
608
        if ((commandSend == BLT_TRUE && deviceID == 0) ||
609
            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID))) {
610
#endif
611
#else
612
        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) {
613
#endif
614
          /* store length of the packet */
615
          toReceive = canData[4];
616
          lastLen = canData[4];
617
          idx = 5;
618

    
619
          /* modify the listening address for filtering of subsequent transmissions */
620
          compID |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
621
        } else {
622
          /* release FIFO0 */
623
          CANx->RF0R |= CAN_BIT_RFOM0;
624
          break;
625
        }
626
      }
627
      /* if this is a subsequent transmission of a packet */
628
      else {
629
        /* store rest length and check if possible */
630
        restLen = canData[0];
631
#if (CAN_DEBUG > 0)
632
        if (restLen != toReceive-receivedLen ||
633
            canLength > restLen+1 ||
634
            lastLen-restLen != ((lastLen==toReceive) ? 3 : 7)) {
635
          /* transmission has been lost */
636
          blinkSOS(2);
637
          msleep(500);
638
          visualizeData((blt_int8u*)&rxMsgId, 4, 1);
639
          msleep(500);
640
          visualizeByte(toReceive, 1);
641
          msleep(500);
642
          visualizeByte(receivedLen, 1);
643
          msleep(500);
644
          visualizeByte(lastLen, 1);
645
          msleep(500);
646
          visualizeByte(restLen, 1);
647
          msleep(500);
648
          visualizeByte(canLength, 1);
649
          msleep(500);
650
          visualizeData(readData, receivedLen, 1);
651
          blinkSOSinf();
652
        }
653
#endif /* CAN_DEBUG > 0 */
654
        lastLen = restLen;
655
        idx = 1;
656
      }
657

    
658
      /* store the payload */
659
      for (; idx < canLength; idx++) {
660
        readData[receivedLen] = canData[idx];
661
        receivedLen++;
662
      }
663

    
664
      /* release FIFO0 */
665
      CANx->RF0R |= CAN_BIT_RFOM0;
666

    
667
      /* send acknowledgement */
668
      CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
669
      CANx->sTxMailBox[0].TIR |= ((rxMsgId | (blt_int32u)BOOT_COM_CAN_MSG_ACK) << 21);
670
      CANx->sTxMailBox[0].TDTR = 1;
671
      CANx->sTxMailBox[0].TDLR = (((blt_int32u)0 << 24) | \
672
                                  ((blt_int32u)0 << 16) | \
673
                                  ((blt_int32u)0 <<  8) | \
674
                                  ((blt_int32u)(toReceive-receivedLen)));
675
      CANx->sTxMailBox[0].TDHR = (((blt_int32u)0 << 24) | \
676
                                  ((blt_int32u)0 << 16) | \
677
                                  ((blt_int32u)0 <<  8) | \
678
                                  ((blt_int32u)0));
679

    
680
      /* request the start of message transmission */
681
      CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
682
      /* wait for transmit completion */
683
      while ((CANx->TSR&CAN_BIT_TME0) == 0)
684
      {
685
        /* keep the watchdog happy */
686
        CopService();
687
      }
688

    
689
      /* check if full package has been received */
690
      if (receivedLen == toReceive) {
691
#if (BOOT_GATE_CAN_ENABLE > 0)
692
        commandSend = BLT_FALSE;
693
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
694
        for (idx = 0; idx < toReceive; idx++) {
695
          data[idx] = readData[idx];
696
        }
697
        length = toReceive;
698
        /* reset static variables */
699
        receivedLen = 0;
700
        toReceive = 0;
701
        break;
702
      } else {
703
#if (CAN_DEBUG > 0)
704
        if (receivedLen > toReceive) {
705
          /* something strange happened */
706
          blinkSOS(3);
707
          msleep(500);
708
          visualizeByte(toReceive, 1);
709
          msleep(500);
710
          visualizeByte(receivedLen, 1);
711
          blinkSOSinf();
712
        }
713
#endif /* CAN_DEBUG > 0 */
714
        length = 0;
715
      }
716
    } else {
717
      /* release FIFO0 */
718
      CANx->RF0R |= CAN_BIT_RFOM0;
719
    }
720
  }
721

    
722
  return length;
723
} /*** end of CanReceiveSinglePacket ***/
724

    
725

    
726
/************************************************************************************//**
727
** \brief     Receives some communication interface packets if they are present.
728
** \param     data Pointer to byte array where the data is to be stored.
729
** \return    Length of message (if the message is invalid, the length will be 0).
730
**
731
****************************************************************************************/
732
#if (0)
733
blt_int8u CanReceivePacket(blt_int8u *data)
734
{
735
  static blt_int8u canPacketData[8];
736
  static blt_int8u canData[BOOT_COM_RX_MAX_DATA];
737
  static blt_int8u receivedLength = 0;
738
  static blt_int8u toReceive = 0;
739

    
740
  // get CAN packet
741
  blt_int8u len = CanReceiveSinglePacket(canPacketData);
742

    
743
  // check, if packet has been received
744
  if (len == 0) {
745
    return 0;
746
  }
747

    
748
  // if it's the first packet of a flow, save data length
749
  blt_int8u startRead = 0;
750
  if (receivedLength == 0) {
751
    toReceive = canPacketData[0];
752
    startRead = 1;
753
  }
754

    
755
  // copy CAN packet data into complete data packet
756
  blt_int8u canIdx = 0;
757
  while (receivedLength < toReceive && canIdx < 8) {
758
    canData[receivedLength] = canPacketData[canIdx];
759
    receivedLength++;
760
    canIdx++;
761
  }
762

    
763
  // check, if data packet is finished
764
  if (receivedLength == toReceive) {
765
    receivedLength = 0;
766
    CpuMemCopy((blt_int32u)data, (blt_int32u)&canData[0], toReceive);
767
    return toReceive;
768
  } else {
769
    return 0;
770
  }
771

    
772

    
773
} /*** end of CanReceivePacket ***/
774
#endif
775
#endif /* BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0 */
776

    
777

    
778
/*********************************** end of can.c **************************************/