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

Thread: Teensy 4.1 FlexCAN_t4 ext ID setMBFilter() 18 bits only?

  1. #1
    Junior Member
    Join Date
    Oct 2021
    Posts
    13

    Teensy 4.1 FlexCAN_t4 ext ID setMBFilter() 18 bits only?

    Hello,

    Recently I was working with the FlexCAN_t4 library but I encountered some behaviour that I was not expecting based on how I understand the filtering to work. I made a test script that displays the behaviour that I experienced. The behaviour is that only the 18 LSB of an extended CAN ID is used in the filter. So If the ID is 0x00070000 then other messages will alias with it such as 0x0003000 since they have the same 18 LSB. I looked at some of the library code and it appears that the ID is masked against 0x0003FFFF in FLEXCAN_MB_ID_IDEXT() so I'm assuming this is a known and required choice. My questions are:
    1. Are the 18 LSB the bits that can be used on a HW filter of a non-FIFO, ie MB, when receiving extended ID CAN frames (even if I'm not using the FIFO, and each mailbox only has a single ID not a range); can I match a full 29 bits extended ID?
    2. If it's not a HW limitation? I'm then curious on this design decision; otherwise then that makes a lot of sense but I swear I couldn't find anything on it in the manual (Rev 3). To me it looked like all of the FLEXCANx_RXIMRn registers are available.

    Oh yeah, I should mention that I do know about the handy enhanceFilter() method available and I am able to use that. Just seemed odd that it would not be possible to use all 29 bits in a filter, especially since the FIFO can.


    Code:
    #include <FlexCAN_T4.h>
    
    FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> can1;
    FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> can2;
    
    #define p(msg) Serial.print(msg)
    #define pl(msg) Serial.println(msg)
    #define ph(msg) Serial.print(msg, HEX)
    #define phl(msg) Serial.println(msg, HEX)
    
    #define myCAN_ID          0x00070000
    #define mb_rx_test        MB0
    #define NUMBER_RX_MB      1
    #define NUMBER_TX_MB      1
    #define CAN_ID_START      0x20000000
    #define CAN_ID_END        0x0
    #define CAN_ID_INC        0x0001000
    
    CAN_message_t get_ID_CAN_msg(const int id) {
        CAN_message_t msg;
        msg.len = 0;
        msg.flags.extended = 1;
        msg.id = id;
        return msg;
    }
    
    CAN_message_t get_ID_CAN_msg_STD(const int id) {
        CAN_message_t msg;
        msg.len = 0;
        msg.flags.extended = 0;
        msg.id = id;
        return msg;
    }
    
    CAN_message_t msg;
    long sum = 0;
    
    void setup() {
        Serial.begin(9600);
        while ((!Serial) && (millis() < 4000) );
        
        can1.begin();
        can1.setBaudRate(1000000);
        can1.setMaxMB(NUMBER_TX_MB);
        can1.setMB(MB0,TX);
        can1.setMBFilter(REJECT_ALL);
    
        can2.begin();
        can2.setBaudRate(1000000);
        can2.setMaxMB(NUMBER_RX_MB);
        can2.setMB(mb_rx_test, RX, EXT);
        can2.setMBFilter(mb_rx_test, myCAN_ID);
        //can2.enhanceFilter(mb_rx_test);
    
        pl("begin test");
        /*for (int id = 0x20000000; id >= 0 ; --id) {*/
        can1.write(get_ID_CAN_msg(myCAN_ID));
        for (int id = CAN_ID_START; id >= CAN_ID_END ; id -= CAN_ID_INC) {
            //if (id % 5000000 == 0) { p("Progess report: "); ph(id); p(" "); pl(sum); }
            can1.write(get_ID_CAN_msg(id));
            delayMicroseconds(500);
            if(can2.read(msg)) {
                ++sum;
                p(msg.mb); p(": "); phl(msg.id); 
            }
            delayMicroseconds(500);
        }
        p("Sum: "); pl(sum);
        pl("End test");
    }
    
    void loop() {}

  2. #2
    The macro FLEXCAN_MB_ID_IDEXT() is used in conjunction with FLEXCAN_MB_ID_IDSTD(), which checks the 11 MSB of the extended ID. I haven't had a chance to look over your code yet

  3. #3
    Junior Member
    Join Date
    Oct 2021
    Posts
    13
    Ah yes, I see what you mean. FLEXCAN_MB_ID_IDEXT() and FLEXCAN_MB_ID_IDSTD() are for separate banks of bits within the ID field. I didn't catch this the first time and it makes sense based on how it's laid out in HW.
    That being said those are used in a ternary operation meaning their application are mutually exclusive; it should only be STD ID or EXT ID though ideally I'd like to use all the bits to filter against 29 bits. I'm assuming the filter in HW is being set with FLEXCANb_MBn_ID() in setMBFilterProcessing() in which it selects a STD ID or EXT ID.
    I tired setting an extended ID filter followed by a STD ID filter to see if I could force it to set all the bits but that didn't work.

  4. #4
    Oh ok, I understand now. It's like the standard bits should always be set and then extended bits only if IDE==1. Since my uses of the library have never included extended frames with filters, I'm a out of my depth. I'd suggest posting an issue in the GitHub repo.

  5. #5
    Junior Member
    Join Date
    Oct 2021
    Posts
    13
    Thanks for the suggestion, I submitted an issue on the GitHub: Issue 60
    Furthermore I did some testing and found that changing FLEXCAN_MB_ID_IDEXT() to (filter_id & 0x1FFFFFFF) seems to have solved the issue in this case . I'll include the code here as well.

    Code:
    FCTP_FUNC void FCTP_OPT::setMBFilterProcessing(FLEXCAN_MAILBOX mb_num, uint32_t filter_id, uint32_t calculated_mask) {
      bool frz_flag_negate = !(FLEXCANb_MCR(_bus) & FLEXCAN_MCR_FRZ_ACK);
      FLEXCAN_EnterFreezeMode();
      FLEXCANb_RXIMR(_bus, mb_num) = calculated_mask | ((FLEXCANb_CTRL2(_bus) & FLEXCAN_CTRL2_EACEN) ? (1UL << 30) : 0);
      FLEXCANb_MBn_ID(_bus, mb_num) = ((!(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE)) ? FLEXCAN_MB_ID_IDSTD(filter_id) : (filter_id & 0x1FFFFFFF));
      if ( frz_flag_negate ) FLEXCAN_ExitFreezeMode();
    }
    
    FCTP_FUNC bool FCTP_OPT::setMBFilter(FLEXCAN_MAILBOX mb_num, uint32_t id1) {
      if ( mb_num < mailboxOffset() || mb_num >= FLEXCANb_MAXMB_SIZE(_bus) ) return 0; /* mailbox not available */
      if ( (FLEXCAN_get_code(FLEXCANb_MBn_CS(_bus, mb_num)) >> 3) ) return 0; /* exit on TX mailbox */ 
      uint32_t mask = ( !(FLEXCANb_MBn_CS(_bus, mb_num) & FLEXCAN_MB_CS_IDE) ) ? FLEXCAN_MB_ID_IDSTD(((id1) ^ (id1)) ^ 0x7FF) : ((((id1) ^ (id1)) ^ 0x1FFFFFFF) & 0x1FFFFFFF);
      setMBFilterProcessing2(mb_num,id1,mask);
      filter_store(FLEXCAN_MULTI, mb_num, 1, id1, 0, 0, 0, 0);
      return 1;
    }

  6. #6
    Junior Member
    Join Date
    Oct 2021
    Posts
    13
    Typo: setMBFilterProcessing2() should be setMBFilterProcessing()

Posting Permissions

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