Revision d54d2f07 Target/Source/ARMCM3_STM32/can.c

View differences:

Target/Source/ARMCM3_STM32/can.c
23 23
* You should have received a copy of the GNU General Public License along with OpenBLT.
24 24
* If not, see <http://www.gnu.org/licenses/>.
25 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 
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 28
* proprietary components. The exception text is included at the bottom of the license
29 29
* file <license.html>.
30
* 
30
*
31 31
* \endinternal
32 32
****************************************************************************************/
33 33

  
34
#define CAN_DEBUG       (0)
34 35

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

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

  
40 45

  
41 46
#if (BOOT_COM_CAN_ENABLE > 0 || BOOT_GATE_CAN_ENABLE > 0)
42 47
/****************************************************************************************
......
58 63
  volatile blt_int32u RDTR;
59 64
  volatile blt_int32u RDLR;
60 65
  volatile blt_int32u RDHR;
61
} tCanRxFIFOMailBox; 
66
} tCanRxFIFOMailBox;
62 67

  
63 68
/** \brief CAN filter register layout. */
64 69
typedef struct
......
92 97
  volatile blt_int32u FA1R;
93 98
  blt_int32u          RESERVED5[8];
94 99
  tCanFilter          sFilterRegister[14];
95
} tCanRegs;                                           
100
} tCanRegs;
96 101

  
97 102

  
98 103
/****************************************************************************************
......
144 149
* Local constant declarations
145 150
****************************************************************************************/
146 151
/** \brief CAN bittiming table for dynamically calculating the bittiming settings.
147
 *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25 
148
 *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC 
149
 *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) * 
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) *
150 155
 *           100%. This array contains possible and valid time quanta configurations with
151 156
 *           a sample point between 68..78%.
152 157
 */
......
175 180

  
176 181

  
177 182
/************************************************************************************//**
178
** \brief     Search algorithm to match the desired baudrate to a possible bus 
183
** \brief     Search algorithm to match the desired baudrate to a possible bus
179 184
**            timing configuration.
180 185
** \param     baud The desired baudrate in kbps. Valid values are 10..1000.
181 186
** \param     prescaler Pointer to where the value for the prescaler will be stored.
182 187
** \param     tseg1 Pointer to where the value for TSEG2 will be stored.
183 188
** \param     tseg2 Pointer to where the value for TSEG2 will be stored.
184
** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE 
189
** \return    BLT_TRUE if the CAN bustiming register values were found, BLT_FALSE
185 190
**            otherwise.
186 191
**
187 192
****************************************************************************************/
188
static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler, 
193
static blt_bool CanGetSpeedConfig(blt_int16u baud, blt_int16u *prescaler,
189 194
                                  blt_int8u *tseg1, blt_int8u *tseg2)
190 195
{
191 196
  blt_int8u  cnt;
......
229 234
  commandSend = BLT_FALSE;
230 235
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
231 236

  
232
  /* the current implementation supports CAN1. throw an assertion error in case a 
233
   * different CAN channel is configured.  
237
  /* the current implementation supports CAN1. throw an assertion error in case a
238
   * different CAN channel is configured.
234 239
   */
235
  ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0); 
240
  ASSERT_CT(BOOT_COM_CAN_CHANNEL_INDEX == 0);
236 241
  /* obtain bittiming configuration information */
237 242
  result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2);
238 243
  ASSERT_RT(result == BLT_TRUE);
......
275 280
  /* 32-bit scale for the filter */
276 281
  CANx->FS1R |= CAN_BIT_FILTER0;
277 282
  /* open up the acceptance filter to receive all messages */
278
  CANx->sFilterRegister[0].FR1 = 0; 
279
  CANx->sFilterRegister[0].FR2 = 0; 
283
  CANx->sFilterRegister[0].FR1 = 0;
284
  CANx->sFilterRegister[0].FR2 = 0;
280 285
  /* select id/mask mode for the filter */
281 286
  CANx->FM1R &= ~CAN_BIT_FILTER0;
282 287
  /* FIFO 0 assignation for the filter */
......
296 301
** \return    none.
297 302
**
298 303
****************************************************************************************/
299
void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
304
void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID)
300 305
{
301 306
  /* make sure that transmit mailbox 0 is available */
302 307
  ASSERT_RT((CANx->TSR&CAN_BIT_TME0) == CAN_BIT_TME0);
303
  /* build the message identifier */
304
  CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
305 308

  
306 309
  blt_int32u address;
307 310
#if (BOOT_GATE_CAN_ENABLE > 0)
......
311 314
#if (BOOT_GATE_CAN_ENABLE > 0)
312 315
    commandSend = BLT_FALSE;
313 316
  } else {
314
    address = ((blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)deviceID);
317
    address = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
315 318
    commandSend = BLT_TRUE;
316 319
  }
317 320
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
......
320 323
  blt_int8u canData[8];
321 324
  blt_int8u restLen = len;
322 325
  blt_int8u canIdx = 0;
326
  blt_int32u ackMsgId;
327
  blt_int8u ackMsgLen;
323 328

  
324 329
  /* send the given package in 8 byte packages */
325 330
  while (restLen > 0) {
326

  
331
    /* build the message identifier */
332
    CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
327 333
    CANx->sTxMailBox[0].TIR |= (address << 21);
328
    /* store the message date length code (DLC) */
329
    if (restLen > 7) {
330
      CANx->sTxMailBox[0].TDTR = 8;
331
    } else {
332
      CANx->sTxMailBox[0].TDTR = restLen+1;
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;
333 362
    }
334
    /* Load max 8 bytes into message data bytes */
335
    canData[0] = restLen;
336
    canIdx = 1;
363

  
364
    /* store the packet payload */
337 365
    while (restLen > 0 && canIdx < 8) {
338 366
      canData[canIdx] = data[len-restLen];
339 367
      canIdx++;
......
344 372
      canData[canIdx] = 0;
345 373
      canIdx++;
346 374
    }
375

  
347 376
    /* store the message data bytes */
348 377
    CANx->sTxMailBox[0].TDLR = (((blt_int32u)canData[3] << 24) | \
349 378
                                ((blt_int32u)canData[2] << 16) | \
......
353 382
                                ((blt_int32u)canData[6] << 16) | \
354 383
                                ((blt_int32u)canData[5] <<  8) | \
355 384
                                ((blt_int32u)canData[4]));
385

  
356 386
    /* request the start of message transmission */
357 387
    CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
358 388
    /* wait for transmit completion */
......
362 392
      CopService();
363 393
    }
364 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;
365 441
  }
366 442
} /*** end of CanTransmitPacket ***/
367 443

  
......
385 461
  blt_int8u canData[8];
386 462
  blt_int8u restLen;
387 463
  blt_int8u canLength;
464
  blt_int8u idx;
388 465

  
389
  /* check if a new message was received */
390
  if ((CANx->RF0R&(blt_int32u)0x00000003) > 0)
391
  {
392
    /* read out the message identifier */
393
    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
394
    /* is this the packet identifier */
395

  
396
    blt_int32u compID;
466
  blt_int32u compID;
397 467
#if (BOOT_GATE_CAN_ENABLE > 0)
398
    if (commandSend == BLT_TRUE) {
399
      compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
400
    } else {
468
  if (commandSend == BLT_TRUE) {
469
    compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
470
  } else {
401 471
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
402
      compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)BOOT_COM_DEVICE_ID;
472
    compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
403 473
#if (BOOT_GATE_CAN_ENABLE > 0)
404
    }
474
  }
405 475
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
406 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 */
407 489
    if (rxMsgId == compID)
408 490
    {
409
#if (BOOT_GATE_CAN_ENABLE > 0)
410
      commandSend = BLT_FALSE;
411
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
412 491
      result = BLT_TRUE;
413 492

  
414 493
      /* save length */
......
423 502
      canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
424 503
      canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
425 504

  
426
      /* Store rest length of package and check if possible */
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 */
427 521
      if (receivedLen == 0) {
428
        toReceive = canData[0];
429
        lastLen = canData[0];
430
      } else {
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 ((commandSend == BLT_TRUE && deviceID == 0) ||
529
            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) || deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID)) {
530
#else
531
        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID ||
532
            deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID) {
533
#endif
534
          /* store length of the packet */
535
          toReceive = canData[4];
536
          lastLen = canData[4];
537
          idx = 5;
538

  
539
          /* modify the listening address for filtering of subsequent transmissions */
540
          compID |= (blt_int32u)BOOT_COM_CAN_MSG_SUBSEQUENT;
541
        } else {
542
          /* release FIFO0 */
543
          CANx->RF0R |= CAN_BIT_RFOM0;
544
          break;
545
        }
546
      }
547
      /* if this is a subsequent transmission of a packet */
548
      else {
549
        /* store rest length and check if possible */
431 550
        restLen = canData[0];
432
        if (lastLen-restLen != 7) {
433
          // package has been lost - but nothing happens
551
#if (CAN_DEBUG > 0)
552
        if (restLen != toReceive-receivedLen ||
553
            canLength > restLen+1 ||
554
            lastLen-restLen != ((lastLen==toReceive) ? 3 : 7)) {
555
          /* transmission has been lost */
556
          blinkSOS(2);
557
          msleep(500);
558
          visualizeData((blt_int8u*)&rxMsgId, 4, 1);
559
          msleep(500);
560
          visualizeByte(toReceive, 1);
561
          msleep(500);
562
          visualizeByte(receivedLen, 1);
563
          msleep(500);
564
          visualizeByte(lastLen, 1);
565
          msleep(500);
566
          visualizeByte(restLen, 1);
567
          msleep(500);
568
          visualizeByte(canLength, 1);
569
          msleep(500);
570
          visualizeData(readData, receivedLen, 1);
571
          blinkSOSinf();
434 572
        }
573
#endif /* CAN_DEBUG > 0 */
435 574
        lastLen = restLen;
575
        idx = 1;
436 576
      }
437 577

  
438
      /* store data in data package */
439
      blt_int8u idx;
440
      for (idx=1; idx < canLength; idx++) {
578
      /* store the payload */
579
      for (; idx < canLength; idx++) {
441 580
        readData[receivedLen] = canData[idx];
442 581
        receivedLen++;
443 582
      }
444 583

  
584
      /* release FIFO0 */
585
      CANx->RF0R |= CAN_BIT_RFOM0;
586

  
587
      /* send acknowledgement */
588
      CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
589
      CANx->sTxMailBox[0].TIR |= ((rxMsgId | (blt_int32u)BOOT_COM_CAN_MSG_ACK) << 21);
590
      CANx->sTxMailBox[0].TDTR = 1;
591
      CANx->sTxMailBox[0].TDLR = (((blt_int32u)0 << 24) | \
592
                                  ((blt_int32u)0 << 16) | \
593
                                  ((blt_int32u)0 <<  8) | \
594
                                  ((blt_int32u)(toReceive-receivedLen)));
595
      CANx->sTxMailBox[0].TDHR = (((blt_int32u)0 << 24) | \
596
                                  ((blt_int32u)0 << 16) | \
597
                                  ((blt_int32u)0 <<  8) | \
598
                                  ((blt_int32u)0));
599

  
600
      /* request the start of message transmission */
601
      CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
602
      /* wait for transmit completion */
603
      while ((CANx->TSR&CAN_BIT_TME0) == 0)
604
      {
605
        /* keep the watchdog happy */
606
        CopService();
607
      }
608

  
445 609
      /* check if full package has been received */
446
      if (receivedLen >= toReceive) {
447
        receivedLen = 0;
610
      if (receivedLen == toReceive) {
611
#if (BOOT_GATE_CAN_ENABLE > 0)
612
        commandSend = BLT_FALSE;
613
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
448 614
        for (idx = 0; idx < toReceive; idx++) {
449 615
          data[idx] = readData[idx];
450 616
        }
451 617
        length = toReceive;
618
        /* reset static variables */
619
        receivedLen = 0;
620
        toReceive = 0;
621
        break;
452 622
      } else {
623
#if (CAN_DEBUG > 0)
624
        if (receivedLen > toReceive) {
625
          /* something strange happened */
626
          blinkSOS(3);
627
          msleep(500);
628
          visualizeByte(toReceive, 1);
629
          msleep(500);
630
          visualizeByte(receivedLen, 1);
631
          blinkSOSinf();
632
        }
633
#endif /* CAN_DEBUG > 0 */
453 634
        length = 0;
454 635
      }
636
    } else {
637
      /* release FIFO0 */
638
      CANx->RF0R |= CAN_BIT_RFOM0;
455 639
    }
456
    /* release FIFO0 */
457
    CANx->RF0R |= CAN_BIT_RFOM0;
458 640
  }
641

  
459 642
  return length;
460 643
} /*** end of CanReceivePacket ***/
461 644
#endif /* BOOT_COM_CAN_ENABLE > 0  || BOOT_GATE_CAN_ENABLE > 0 */

Also available in: Unified diff