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?
thanks, I will try it some time later on
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