How to set up receiving on multiple CAN interfaces

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to set up receiving on multiple CAN interfaces

990 Views
pmrlcbtcphtzjdq
Contributor III

Hello!
I need to develop an application that receives messages on two CAN modules. I am using freeRTOS and would like to make it as easy as possible.
I was considering if using simple SDK functions in a single task would work - they are supposed to be non-blocking.
I was thinking about something like this:

 

 

    uint8_t rx_mailbox1 = 1;
    uint8_t rx_mailbox2 = 2;
    
    // Set information about the data to be received
    flexcan_data_info_t dataInfo =
    {
            .data_length = 1U, //don't care - larger msgs are also received
            .msg_id_type = FLEXCAN_MSG_ID_STD,
            .enable_brs  = false,
            .fd_enable   = false,
            .fd_padding  = 0U
    };

    // Configure RX message buffer
    FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, rx_mailbox1, &dataInfo, 1);
    FLEXCAN_DRV_ConfigRxMb(INST_CANCOM2, rx_mailbox2, &dataInfo, 1);

    // set the Mask to receive all the messages
    FLEXCAN_DRV_SetRxMbGlobalMask(INST_CANCOM1, FLEXCAN_MSG_ID_STD, 0);
    FLEXCAN_DRV_SetRxMbGlobalMask(INST_CANCOM2, FLEXCAN_MSG_ID_STD, 0);

    while(1){
        // Define receive buffer
        flexcan_msgbuff_t recvBuff1, recvBuff2;

        FLEXCAN_DRV_Receive(INST_CANCOM1, rx_mailbox1, &recvBuff);
        FLEXCAN_DRV_Receive(INST_CANCOM2, rx_mailbox2, &recvBuff);

	}

 

If this doesn't work I was thinking about using the interrupt flags to monitor any changes on the message buffers. However, I am not really sure if this approach could work.
My idea is as follows:

 

  uint8_t rx_mailbox1 = 1;
  uint8_t rx_mailbox2 = 2;

  // Set information about the data to be received
   flexcan_data_info_t dataInfo =
   {
      .data_length = 1U, //don't care - larger msgs are also received
      .msg_id_type = FLEXCAN_MSG_ID_STD,
      .enable_brs  = false,
      .fd_enable   = false,
      .fd_padding  = 0U
    };

    // Configure RX message buffer
    FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, rx_mailbox1, &dataInfo, 1);
    FLEXCAN_DRV_ConfigRxMb(INST_CANCOM2, rx_mailbox2, &dataInfo, 1);

    // set the Mask to receive all the messages
    FLEXCAN_DRV_SetRxMbGlobalMask(INST_CANCOM1, FLEXCAN_MSG_ID_STD, 0);
    FLEXCAN_DRV_SetRxMbGlobalMask(INST_CANCOM2, FLEXCAN_MSG_ID_STD, 0);

    //enable interrupts for all the message buffers on two CANs
    CAN0->IMASK1 |= CAN_IMASK1_BUF31TO0M_MASK; //for INST_CANCOM1 Interface
    CAN1->IMASK1 |= CAN_IMASK1_BUF31TO0M_MASK; //for INST_CANCOM2 Interface 

while(1){
        flexcan_msgbuff_t recvBuff1, recvBuff2;

	//check for a flag 
 	if (*CAN0->IFLAG1 = 0x1){ //something on CAN0 
		FLEXCAN_DRV_Receive(INST_CANCOM1, rx_mailbox, &recvBuff);
                CAN0->IFLAG &= 0x0; //clear the flag
	}else if(*CAN1->IFLAG1 = 0x2){ //something on CAN1
		FLEXCAN_DRV_Receive(INST_CANCOM2, rx_mailbox2, &recvBuff);
                CAN1->IFLAG &= 0x0; //clear the flag
	}
	vTaskDelay(0)
	}

 


However, I have few concerns:
- does every CAN instance have 96 Message Buffers? Or are there 96 MB in general?
- are Message Buffers in this case correctly assigned to Mailboxes?
- the whole code is located in a Task, however, the two comparisons are actually blocking calls. Would an interrupt routine be better?
- how come the CAN message ID needs to be set up BEFORE receiving a CAN message?
- do I need to enter any special mode to manipulate the IFLAG and IMASK registers?

And maybe the first approach is simply better?
Thanks for any suggestions?

 

0 Kudos
2 Replies

945 Views
pmrlcbtcphtzjdq
Contributor III

thanks, I will try it some time later on

0 Kudos

981 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

yes, each module has 96MBs.
Single task could work I think, but you should wait for driver status or use interrupt to know when to read/use received data and prepare MB for new reception. Manipulating with IFLAG and MASK register is not recommended, it is done within driver.
You can try to prepare MB for reception (calling  FLEXCAN_DRV_ConfigRxMb with FLEXCAN_DRV_Receive) before scheduler is started or in some init task. Then in your RX task you can do  

for ( ;; )
{
/* Define receive buffer */
flexcan_msgbuff_t recvBuff1, recvBuff2;

/* if the previous FlexCAN receive is completed */
if(FLEXCAN_DRV_GetTransferStatus(INST_CANCOM1, RX_MAILBOX1) <> STATUS_BUSY)
{
   // read recvBuff1 data as needed
   /* Start receiving data in RX_MAILBOX1 again. */
   FLEXCAN_DRV_Receive(INST_CANCOM1, RX_MAILBOX1, &recvBuff1);
}

if(FLEXCAN_DRV_GetTransferStatus(INST_CANCOM2, RX_MAILBOX2) <> STATUS_BUSY)
{
   // read recvBuff2 data as needed
   /* Start receiving data in RX_MAILBOX2 again. */
   FLEXCAN_DRV_Receive(INST_CANCOM2, RX_MAILBOX2, &recvBuff2);
}

}

Could be a question if you do not miss some messages this way, depends on bus load.

BR, Petr

0 Kudos