Tool/software:
Hello,
I have a few questions regarding receiving CAN RX frames from the interrupt handler. (Full handler code included at the bottom).
It is based on the example project implementation for CAN RX and it is operating in the fifo mode.
There are a few somewhat confusing moments that I would like to clarify with your help.
Firstly, is the following do while check necessary (I saw it in the example project for can rx) ?
do {
DL_MCAN_getRxFIFOStatus(CANFD0, &rx_fs);
} while ((rx_fs.fillLvl) == 0);
I would think if we get the rx event, then there is already a message in the rx fifo and I do not need to poll for it.
Secondly. If there are several messages in the fifo buffered up, what is the correct way to read them all out ?
Currently I just do it like this:
do {
DL_MCAN_readMsgRam(CANFD0, DL_MCAN_MEM_TYPE_FIFO, 0U, rx_fs.num, &rx_msg);
DL_MCAN_writeRxFIFOAck(CANFD0, rx_fs.num, rx_fs.getIdx);
for (int i = 0; i < rx_msg.dlc; i++) {
frame[i] = rx_msg.data[i];
}
can_rx_handler(rx_msg.id, frame, rx_msg.dlc); // Process received frame
DL_MCAN_getRxFIFOStatus(CANFD0, &rx_fs);
} while (rx_fs.fillLvl > 0);
Here is a complete code snippet of the handler:
void CANFD0_IRQHandler(void) {
uint32_t intr_status;
DL_MCAN_RxFIFOStatus rx_fs;
DL_MCAN_RxBufElement rx_msg;
uint8_t frame[8];
switch (DL_MCAN_getPendingInterrupt(CANFD0)) {
case DL_MCAN_IIDX_LINE0:
intr_status = DL_MCAN_getIntrStatus(CANFD0);
DL_MCAN_clearIntrStatus(CANFD0, intr_status, DL_MCAN_INTR_SRC_MCAN_LINE_0);
if ((intr_status & MCAN_IR_RF0N_MASK)) {
rx_fs.num = DL_MCAN_RX_FIFO_NUM_0;
// wait until the message is in the fifo
do {
DL_MCAN_getRxFIFOStatus(CANFD0, &rx_fs);
} while ((rx_fs.fillLvl) == 0);
// read until fifo is empty
do {
DL_MCAN_readMsgRam(CANFD0, DL_MCAN_MEM_TYPE_FIFO, 0U, rx_fs.num, &rx_msg);
DL_MCAN_writeRxFIFOAck(CANFD0, rx_fs.num, rx_fs.getIdx);
for (int i = 0; i < rx_msg.dlc; i++) {
frame[i] = rx_msg.data[i];
}
can_rx_handler(rx_msg.id, frame, rx_msg.dlc); // Process received frame
DL_MCAN_getRxFIFOStatus(CANFD0, &rx_fs);
} while (rx_fs.fillLvl > 0);
}
if (intr_status & MCAN_IR_BO_MASK) {
DL_MCAN_setOpMode(CANFD0, DL_MCAN_OPERATION_MODE_NORMAL);
}
break;
default:
break;
}
}