Revision d54d2f07 Target/Source/ARMCM4_STM32/can.c

View differences:

Target/Source/ARMCM4_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[28];
95
} tCanRegs;                                           
100
} tCanRegs;
96 101

  
97 102

  
98 103
/****************************************************************************************
......
153 158
* Local constant declarations
154 159
****************************************************************************************/
155 160
/** \brief CAN bittiming table for dynamically calculating the bittiming settings.
156
 *  \details According to the CAN protocol 1 bit-time can be made up of between 8..25 
157
 *           time quanta (TQ). The total TQ in a bit is SYNC + TSEG1 + TSEG2 with SYNC 
158
 *           always being 1. The sample point is (SYNC + TSEG1) / (SYNC + TSEG1 + SEG2) * 
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) *
159 164
 *           100%. This array contains possible and valid time quanta configurations with
160 165
 *           a sample point between 68..78%.
161 166
 */
......
184 189

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

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

  
246 251
  /* obtain bittiming configuration information */
247 252
  result = CanGetSpeedConfig(BOOT_COM_CAN_BAUDRATE/1000, &prescaler, &tseg1, &tseg2);
......
297 302
  /* 32-bit scale for the filter */
298 303
  CAN1->FS1R |= CAN_BIT_FILTER0;
299 304
  /* open up the acceptance filter to receive all messages */
300
  CAN1->sFilterRegister[0].FR1 = 0; 
301
  CAN1->sFilterRegister[0].FR2 = 0; 
305
  CAN1->sFilterRegister[0].FR1 = 0;
306
  CAN1->sFilterRegister[0].FR2 = 0;
302 307
  /* select id/mask mode for the filter */
303 308
  CAN1->FM1R &= ~CAN_BIT_FILTER0;
304 309
  /* FIFO 0 assignation for the filter */
......
315 320
  /* 32-bit scale for the filter */
316 321
  CAN1->FS1R |= CAN_BIT_FILTER14;
317 322
  /* open up the acceptance filter to receive all messages */
318
  CAN1->sFilterRegister[14].FR1 = 0; 
319
  CAN1->sFilterRegister[14].FR2 = 0; 
323
  CAN1->sFilterRegister[14].FR1 = 0;
324
  CAN1->sFilterRegister[14].FR2 = 0;
320 325
  /* select id/mask mode for the filter */
321 326
  CAN1->FM1R &= ~CAN_BIT_FILTER14;
322 327
  /* FIFO 0 assignation for the filter */
......
325 330
  CAN1->FA1R |= CAN_BIT_FILTER14;
326 331
  /* leave initialisation mode for the acceptance filter */
327 332
  CAN1->FMR &= ~CAN_BIT_FINIT;
328
#endif  
333
#endif
329 334
} /*** end of CanInit ***/
330 335

  
331 336

  
......
336 341
** \return    none.
337 342
**
338 343
****************************************************************************************/
339
void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int8u deviceID)
344
void CanTransmitPacket(blt_int8u *data, blt_int8u len, blt_int32u deviceID)
340 345
{
341 346
  /* make sure that transmit mailbox 0 is available */
342 347
  ASSERT_RT((CANx->TSR&CAN_BIT_TME0) == CAN_BIT_TME0);
343
  /* store the 11-bit message identifier */
344
  CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
345 348

  
346 349
  blt_int32u address;
347 350
#if (BOOT_GATE_CAN_ENABLE > 0)
......
351 354
#if (BOOT_GATE_CAN_ENABLE > 0)
352 355
    commandSend = BLT_FALSE;
353 356
  } else {
354
    address = ((blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)deviceID);
357
    address = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
355 358
    commandSend = BLT_TRUE;
356 359
  }
357 360
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
......
360 363
  blt_int8u canData[8];
361 364
  blt_int8u restLen = len;
362 365
  blt_int8u canIdx = 0;
366
  blt_int32u ackMsgId;
367
  blt_int8u ackMsgLen;
363 368

  
364 369
  /* send the given package in 8 byte packages */
365 370
  while (restLen > 0) {
366

  
371
    /* build the message identifier */
372
    CANx->sTxMailBox[0].TIR &= CAN_BIT_TXRQ;
367 373
    CANx->sTxMailBox[0].TIR |= (address << 21);
368
    /* store the message date length code (DLC) */
369
    if (restLen > 7) {
370
      CANx->sTxMailBox[0].TDTR = 8;
371
    } else {
372
      CANx->sTxMailBox[0].TDTR = restLen+1;
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;
373 402
    }
374
    /* Load max 8 bytes into message data bytes */
375
    canData[0] = restLen;
376
    canIdx = 1;
403

  
404
    /* store the packet payload */
377 405
    while (restLen > 0 && canIdx < 8) {
378 406
      canData[canIdx] = data[len-restLen];
379 407
      canIdx++;
......
384 412
      canData[canIdx] = 0;
385 413
      canIdx++;
386 414
    }
415

  
387 416
    /* store the message data bytes */
388 417
    CANx->sTxMailBox[0].TDLR = (((blt_int32u)canData[3] << 24) | \
389 418
                                ((blt_int32u)canData[2] << 16) | \
......
393 422
                                ((blt_int32u)canData[6] << 16) | \
394 423
                                ((blt_int32u)canData[5] <<  8) | \
395 424
                                ((blt_int32u)canData[4]));
425

  
396 426
    /* request the start of message transmission */
397 427
    CANx->sTxMailBox[0].TIR |= CAN_BIT_TXRQ;
398 428
    /* wait for transmit completion */
......
402 432
      CopService();
403 433
    }
404 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;
405 481
  }
406 482
} /*** end of CanTransmitSinglePacket ***/
407 483

  
......
461 537
  blt_int8u canData[8];
462 538
  blt_int8u restLen;
463 539
  blt_int8u canLength;
540
  blt_int8u idx;
464 541

  
465
  /* check if a new message was received */
466
  if ((CANx->RF0R&(blt_int32u)0x00000003) > 0)
467
  {
468
    /* read out the message identifier */
469
    rxMsgId = (blt_int32u)0x000007FF & (CANx->sFIFOMailBox[0].RIR >> 21);
470
    /* is this the packet identifier */
471

  
472
    blt_int32u compID;
542
  blt_int32u compID;
473 543
#if (BOOT_GATE_CAN_ENABLE > 0)
474
    if (commandSend == BLT_TRUE) {
475
      compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
476
    } else {
544
  if (commandSend == BLT_TRUE) {
545
    compID = (blt_int32u)BOOT_COM_CAN_TX_MSG_ID;
546
  } else {
477 547
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
478
      compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID | (blt_int32u)BOOT_COM_DEVICE_ID;
548
    compID = (blt_int32u)BOOT_COM_CAN_RX_MSG_ID;
479 549
#if (BOOT_GATE_CAN_ENABLE > 0)
480
    }
550
  }
481 551
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
482 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 */
483 565
    if (rxMsgId == compID)
484 566
    {
485
#if (BOOT_GATE_CAN_ENABLE > 0)
486
      commandSend = BLT_FALSE;
487
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
488 567
      result = BLT_TRUE;
489 568

  
490 569
      /* save length */
......
499 578
      canData[6] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 16);
500 579
      canData[7] = (blt_int8u)0xFF & (CANx->sFIFOMailBox[0].RDHR >> 24);
501 580

  
502
      /* Store rest length of package and check if possible */
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 */
503 597
      if (receivedLen == 0) {
504
        toReceive = canData[0];
505
        lastLen = canData[0];
506
      } else {
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 ((commandSend == BLT_TRUE && deviceID == 0) ||
605
            (commandSend != BLT_TRUE && (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) || deviceID == (blt_int32u)BOOT_COM_DEVICE_LEGACY_ID)) {
606
#else
607
        if (deviceID == (blt_int32u)BOOT_COM_DEVICE_ID) {
608
#endif
609
          /* store length of the packet */
610
          toReceive = canData[4];
611
          lastLen = canData[4];
612
          idx = 5;
613

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

  
514
      /* store data in data package */
515
      blt_int8u idx;
516
      for (idx=1; idx < canLength; idx++) {
653
      /* store the payload */
654
      for (; idx < canLength; idx++) {
517 655
        readData[receivedLen] = canData[idx];
518 656
        receivedLen++;
519 657
      }
520 658

  
659
      /* release FIFO0 */
660
      CANx->RF0R |= CAN_BIT_RFOM0;
661

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

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

  
521 684
      /* check if full package has been received */
522
      if (receivedLen >= toReceive) {
523
        receivedLen = 0;
685
      if (receivedLen == toReceive) {
686
#if (BOOT_GATE_CAN_ENABLE > 0)
687
        commandSend = BLT_FALSE;
688
#endif /* BOOT_GATE_CAN_ENABLE > 0 */
524 689
        for (idx = 0; idx < toReceive; idx++) {
525 690
          data[idx] = readData[idx];
526 691
        }
527 692
        length = toReceive;
693
        /* reset static variables */
694
        receivedLen = 0;
695
        toReceive = 0;
696
        break;
528 697
      } else {
698
#if (CAN_DEBUG > 0)
699
        if (receivedLen > toReceive) {
700
          /* something strange happened */
701
          blinkSOS(3);
702
          msleep(500);
703
          visualizeByte(toReceive, 1);
704
          msleep(500);
705
          visualizeByte(receivedLen, 1);
706
          blinkSOSinf();
707
        }
708
#endif /* CAN_DEBUG > 0 */
529 709
        length = 0;
530 710
      }
711
    } else {
712
      /* release FIFO0 */
713
      CANx->RF0R |= CAN_BIT_RFOM0;
531 714
    }
532
    /* release FIFO0 */
533
    CANx->RF0R |= CAN_BIT_RFOM0;
534 715
  }
716

  
535 717
  return length;
536 718
} /*** end of CanReceiveSinglePacket ***/
537 719

  
......
581 763
  } else {
582 764
    return 0;
583 765
  }
584
  
766

  
585 767

  
586 768
} /*** end of CanReceivePacket ***/
587 769
#endif

Also available in: Unified diff