Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 25 of 181

Thread: IFCT - Improved Flexcan Teensy Library

Threaded View

  1. #1
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,078

    IFCT - Improved Flexcan Teensy Library

    Hi, I decided to work on a different twist of the current libraries and forks of collin80, teachop, and pawelsky, and rework most of the existing code from scratch into a new library that has, currently, these features:

    Before you ask, I'm currently doing it on a 3.6 and only for FLEXCAN0 until it matures, only then I would add CAN1 support and 3.2 registers
    Debug will be enabled for initial version for any testers interested on testing, and suggesting other ideas to implement.
    Secondly, I havn't added masking/filter support yet as I work on the structure, but by default I enable both in FIFO mode and mailbox mode all frames accepted, again, until it matures, then they will be added

    1) FIFO (enabled or disabled dynamically), with interrupt capability (enableFIFOInterrupt/disableFIFOInterrupt)

    2) Dynamic mailbox setup support: setMB(MB9, TX) (transmit mailbox), or setMB(MB9,RX,IDE) (setup an extended ID reception box)

    3) Individual mailbox interrupt enabling (*.enableMBInterrupt(MB5)/*.disableMBInterrupt(MB5);

    4) there is a pollFIFO() function that can give a user direct access to the FIFO frames, and at the same time, disable MB/FIFO interrupts, for as long as you poll frames.
    This allows users to access frames directly rather than handling in their callbacks. The interrupts are restored when pollFIFO is called with a 0 overload. (myCAN.pollFIFO(msg, 1))(disable interrupt)(CAN.pollFIFO(msg, 0))(enable interrupt)

    5) Callbacks, you have a global callback, and, if necessary, I've added individual mailbox callbacks as well!
    Code:
        void onReceive(const IFCTMBNUM &mb_num, _MB_ptr handler); /* individual mailbox callback function */
        void onReceive(_MB_ptr handler); /* global callback function */
    This allows you to handle specific mailboxes with interrupts. everything else goes in global callback, including the individual which goes to both.

    6) The constructor is pretty basic with only 2 initializers:
    Code:
    IFCT myCAN = IFCT(); // initialized default, 1Mbps on Can0
    // or
    IFCT myCAN = IFCT(1000000,FLEXCAN0_BASE); // initialize with 1Mbps on Can0 (register base address);
    // or just do baud alone
    IFCT myCAN = IFCT(1000000);
    7) The .write(...) function has been redesigned. There is an attempt to scan for transmit buffers that are available, if none are available, it checks 2 more times before returning to user (0) that a transmit wasnt possible.
    This has FIFO check routine for adaptation.

    8) The .read(...) function has been redesigned. FIFO check routine optimizes mailbox reading. read(...) is not meant to read the FIFO buffer, use pollFIFO for that. However, the new way the read() function is done is it goes incrementally up each mailbox each read, so every time you request a read(), it never hits the same mailbox twice, ensuring even data requests. Should it encouter any TX buffers, it will skip them till the next available read buffer. Should nothing be readable (no data) within 2 cycles, the function is exited with a return of 0 as it should.

    9) By default, when you enable FIFO, the library will setup FIFO for you with the 8 remaining mailboxes as transmit buffers. When you disable FIFO, the library will setup the first 4 mailboxes for Standard IDs and the next 4 for Extended IDs, remaining 8 for TX buffers. Should you want to change specific ones later on, just use setMB.

    simple sending in the main loop :

    Code:
      msg.flags.extended = random(0,2);
      msg.flags.remote = 0;
      msg.len = 8;
      msg.id = random(0x69, 0x178);
      msg.buf[0] = random(0, 255);
      msg.buf[1] = random(0, 255);
      msg.buf[2] = random(0, 255);
      msg.buf[3] = random(0, 255);
      msg.buf[4] = random(0, 255);
      msg.buf[5] = random(0, 255);
      msg.buf[6] = random(0, 255);
      msg.buf[7] = random(0, 255);
      CAN.write(msg);
    and reading mailboxes:
    Code:
        if (CAN.read(msg)) {
          Serial.print("  LEN: "); Serial.print(msg.len);
          Serial.print(" EXT: "); Serial.print(msg.flags.extended);
          Serial.print(" REMOTE: "); Serial.print(msg.rtr);
          Serial.print(" TS: "); Serial.print(msg.timestamp);
          Serial.print(" ID: "); Serial.print(msg.id);
          Serial.print(" Buffer: ");
          for ( uint8_t i = 0; i < msg.len; i++ ) {
            Serial.print(msg.buf[i], HEX); Serial.print(" ");
          } Serial.println();
        }

    Here is the All / Individual callbacks tests:

    Code:
      CAN.enableFIFO(0);
      CAN.enableFIFOInterrupt(0);
      CAN.onReceive(myMSG);
      CAN.onReceive(MB1, MB1cb);
    Output:

    Code:
    MB 0  LEN: 8 EXT: 0 REMOTE: 0 TS: 61237 ID: 256 Buffer: BE 14 0 64 80 40 20 10 
    MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 61360 ID: 256 Buffer: BF 14 0 64 80 40 20 10 
    *** MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 61360 ID: 256 Buffer: BF 14 0 64 80 40 20 10 
    MB 4  LEN: 8 EXT: 1 REMOTE: 0 TS: 44858 ID: 291 Buffer: A 14 0 64 80 40 20 10 
    MB 0  LEN: 8 EXT: 0 REMOTE: 0 TS: 61481 ID: 256 Buffer: C0 14 0 64 80 40 20 10 
    MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 61603 ID: 256 Buffer: C1 14 0 64 80 40 20 10 
    *** MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 61603 ID: 256 Buffer: C1 14 0 64 80 40 20 10 
    MB 0  LEN: 8 EXT: 0 REMOTE: 0 TS: 12683 ID: 256 Buffer: C3 14 0 64 80 40 20 10 
    MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 12804 ID: 256 Buffer: C4 14 0 64 80 40 20 10 
    *** MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 12804 ID: 256 Buffer: C4 14 0 64 80 40 20 10 
    MB 4  LEN: 8 EXT: 1 REMOTE: 0 TS: 61845 ID: 291 Buffer: A 14 0 64 80 40 20 10 
    MB 0  LEN: 8 EXT: 0 REMOTE: 0 TS: 12927 ID: 256 Buffer: C5 14 0 64 80 40 20 10 
    MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 13049 ID: 256 Buffer: C6 14 0 64 80 40 20 10 
    *** MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 13049 ID: 256 Buffer: C6 14 0 64 80 40 20 10 
    MB 0  LEN: 8 EXT: 0 REMOTE: 0 TS: 29664 ID: 256 Buffer: C8 14 0 64 80 40 20 10 
    MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 29787 ID: 256 Buffer: C9 14 0 64 80 40 20 10 
    *** MB 1  LEN: 8 EXT: 0 REMOTE: 0 TS: 29787 ID: 256 Buffer: C9 14 0 64 80 40 20 10
    *** MB1 dipicts code printed from MB1 callback
    without the *** dipicts normal catchall callback
    An individual callback frame will be in both.

    And here is the receiving MCU receiving the loop sends:
    Code:
     
    LEN: 8 EXT: 1 REMOTE: 0 TS: 11536 ID: 354 Buffer: 11 82 57 4F 4A 4C 8D 21 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 31544 ID: 268 Buffer: 82 46 4F F1 DA 9C 7D A6 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 51550 ID: 173 Buffer: B0 52 F4 7D 2 5F E5 C6 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 6021 ID: 288 Buffer: 4C F4 AB 2F B8 88 CE 21 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 26028 ID: 351 Buffer: 18 24 39 C4 E5 51 39 3E 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 46035 ID: 361 Buffer: B1 B1 F2 C1 BA FE 56 44 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 506 ID: 319 Buffer: DF 6 54 7 E2 DA D3 59 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 20512 ID: 140 Buffer: 61 41 A 44 59 B6 DA 72 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 40519 ID: 353 Buffer: 23 D0 92 2A EE F7 71 2E 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 60527 ID: 153 Buffer: DB 1A BC 57 F3 A7 9F 2C 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 14998 ID: 226 Buffer: 61 B5 3E D8 CB 40 14 E0 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 35005 ID: 221 Buffer: 61 FB 14 B0 1C 85 D 19 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 55012 ID: 232 Buffer: 47 F8 14 23 C7 32 D1 5B 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 9483 ID: 261 Buffer: AB A2 93 E8 F3 9 59 73 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 29490 ID: 198 Buffer: 35 70 C0 84 27 A5 50 DC 
    LEN: 8 EXT: 1 REMOTE: 0 TS: 49497 ID: 112 Buffer: 69 D5 36 56 95 F0 B5 54 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 3969 ID: 171 Buffer: DE A5 98 48 14 C5 34 F7 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 23976 ID: 208 Buffer: 13 50 E7 34 6A 41 D3 81 
    LEN: 8 EXT: 0 REMOTE: 0 TS: 43983 ID: 195 Buffer: 22 4 FE 31 71 12 F1 1F
    One of a good ideas is that in FIFO mode, we can setMB a mailbox with a reception interrupt box, keep FIFO interrupts off, and when you receive a match in your mailbox you could trigger the poll method to collect all your frames in ordered fashion. Mailboxes have interrupt priority over FIFO, I've tested an extended frame reception on MB9 with FIFO enabled and was able to do what I want when the callback fired
    pollFIFO would be very useful for external libraries, where you can pass the frames directly to another function without touching your callback

    By the way, I'm testing also with Fusion's dual can transceiver breakout from Tindie

    Click image for larger version. 

Name:	2016-11-12T15 59 10.613Z-candual.jpg 
Views:	69 
Size:	85.0 KB 
ID:	14068



    Current Compilation:

    Blank Sketch:
    Code:
    Sketch uses 9200 bytes (0%) of program storage space. Maximum is 1048576 bytes.
    Global variables use 4212 bytes (1%) of dynamic memory, leaving 257932 bytes for local variables. Maximum is 262144 bytes.
    IFCT Library Demo Sketch:
    Code:
    Sketch uses 20348 bytes (1%) of program storage space. Maximum is 1048576 bytes.
    Global variables use 5416 bytes (2%) of dynamic memory, leaving 256728 bytes for local variables. Maximum is 262144 bytes.
    Flexcan_Library Demo compilation:
    Code:
    Sketch uses 16924 bytes (1%) of program storage space. Maximum is 1048576 bytes.
    Global variables use 7624 bytes (2%) of dynamic memory, leaving 254520 bytes for local variables. Maximum is 262144 bytes.
    looks like a 1200 byte memory difference betweeen blank sketch
    The fork demo is 2K difference between mine as well


    Here's a video of it in action:
    https://www.youtube.com/watch?v=9H0HKlfSoRY


    I should have it up on github sometime today
    Last edited by tonton81; 06-22-2018 at 11:25 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •