issue:s32k144 CAN0 Rx With Fifo DMA

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

issue:s32k144 CAN0 Rx With Fifo DMA

Jump to solution
2,627 Views
cqhcau
Contributor I

I want to Receive 2 CAN messages with CAN0,I use the Fifo with DMA.

I modify on the “Example S32K144 FlexCAN RXFIFO DMA S32DS.ARM.2018.R1”.

Example S32K144 FlexCAN RXFIFO DMA S32DS.ARM.2018.R1 ;

The main configuration as flows:

1、filter table

void J1939_CAN0_init(void)
{
YCECU2FDM1.id=0x18F2E100 ;
YCECU2FDM2.id=0x14FD3E83 ;
/*--第0个报文匹配--*/
filterTable[0].isRemoteFrame = false;
filterTable[0].isExtendedFrame =true;
filterTable[0].id = YCECU2FDM1.id ;
/*--第1个报文匹配--*/
filterTable[1].isRemoteFrame = false;
filterTable[1].isExtendedFrame = true;
filterTable[1].id = YCECU2FDM2.id ;
}

2、Initialization 

/*Initialize eDMA driver */
EDMA_DRV_Init(&dmaController1_State, &dmaController1_InitConfig0, edmaChnStateArray, edmaChnConfigArray, EDMA_CONFIGURED_CHANNELS_COUNT);

/*Initialize FlexCAN driver */
FLEXCAN_DRV_Init(INST_CANCOM1, &canCom1_State, &canCom1_InitConfig0);
/* Install callback function */
FLEXCAN_DRV_InstallEventCallback(INST_CANCOM1, flexcan0_Callback, NULL);

/* Set information about the data to be received */
flexcan_data_info_t dataInfo =
{
.data_length = 1U,
.msg_id_type = FLEXCAN_MSG_ID_STD,
.enable_brs = false,
.fd_enable = false,
.fd_padding = 0U
};

/* Configure RX message buffer with index RX_MSG_ID and RX_MAILBOX */
FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, RX_MAILBOX, &dataInfo, RX_MSG_ID);

J1939_CAN0_init();
/* Configure RX FIFO ID filter table elements based on filter table defined above*/
FLEXCAN_DRV_ConfigRxFifo(INST_CANCOM1, FLEXCAN_RX_FIFO_ID_FORMAT_A, filterTable);
/* set individual masking type */
FLEXCAN_DRV_SetRxMaskType(INST_CANCOM1, FLEXCAN_RX_MASK_INDIVIDUAL);
/* first 14 filter items are masked with RXIMR0-RXIMR9 */
for(id_counter=0;id_counter<10;id_counter++)
FLEXCAN_DRV_SetRxIndividualMask(INST_CANCOM1, FLEXCAN_MSG_ID_EXT, id_counter, 0xffffffff);
/* rest of filter items are masked with RXFGMASK */
FLEXCAN_DRV_SetRxFifoGlobalMask(INST_CANCOM1, FLEXCAN_MSG_ID_EXT, 0xffffffff);

/* set mask affecting MB10 */
FLEXCAN_DRV_SetRxIndividualMask(INST_CANCOM1, FLEXCAN_MSG_ID_EXT, RX_MAILBOX, 0xFFFFFFFF);

/* Start receiving data in RX_MAILBOX. */
FLEXCAN_DRV_Receive(INST_CANCOM1, RX_MAILBOX, &recvBuff1);
/* Start receiving data in RX_RXFIFO. */
FLEXCAN_DRV_RxFifo(INST_CANCOM1,&recvBuff2);

3、call back

void flexcan0_Callback(uint8_t instance, flexcan_event_type_t eventType,uint32_t buffIdx,
flexcan_state_t *flexcanState)
{
(void)flexcanState;
(void)instance;
(void)buffIdx;
uint8_t idx;

switch(eventType)
{
case FLEXCAN_EVENT_RX_COMPLETE:
{
rxMBdone = 1;
}
break;
case FLEXCAN_EVENT_RXFIFO_COMPLETE:
{

}
break;
case FLEXCAN_EVENT_DMA_COMPLETE:
{
if(recvBuff2.msgId==YCECU2FDM1.id)
{
for(idx=0;idx<recvBuff2.dataLen;idx++)
YCECU2FDM1.Data[idx]=recvBuff2.data[idx];
}

if(recvBuff2.msgId==YCECU2FDM2.id)
{
for(idx=0;idx<recvBuff2.dataLen;idx++)
YCECU2FDM2.Data[idx]=recvBuff2.data[idx];
}
rxFIFOdone=1;
}
break;
case FLEXCAN_EVENT_TX_COMPLETE:
{
}
break;
default:
break;
}
}

4、The "while"loop:

while(1)
{

if(rxFIFOdone==1)
{
rxFIFOdone=0;
FLEXCAN_DRV_RxFifo(INST_CANCOM1,&recvBuff2);
}

}

The project can receive the two CAN messages correctly.

But when I modify  the "callback" and the "while loop" as flow, the project can only receive the two messages once and the project seems halt.I guess the problem is the interrupt, so What could be the cause?

3、callback

void flexcan0_Callback(uint8_t instance, flexcan_event_type_t eventType,uint32_t buffIdx,
flexcan_state_t *flexcanState)
{
(void)flexcanState;
(void)instance;
(void)buffIdx;
uint8_t idx;

switch(eventType)
{
case FLEXCAN_EVENT_RX_COMPLETE:
{
rxMBdone = 1;
}
break;
case FLEXCAN_EVENT_RXFIFO_COMPLETE:
{

}
break;
case FLEXCAN_EVENT_DMA_COMPLETE:
{
if(recvBuff2.msgId==YCECU2FDM1.id)
{
for(idx=0;idx<recvBuff2.dataLen;idx++)
YCECU2FDM1.Data[idx]=recvBuff2.data[idx];
}

if(recvBuff2.msgId==YCECU2FDM2.id)
{
for(idx=0;idx<recvBuff2.dataLen;idx++)
YCECU2FDM2.Data[idx]=recvBuff2.data[idx];
}
//rxFIFOdone=1;
FLEXCAN_DRV_RxFifo(INST_CANCOM1,&recvBuff2);
}
break;
case FLEXCAN_EVENT_TX_COMPLETE:
{
CANFillBufferTx();

}
break;
default:
break;
}
}

4、while loop

while(1)
{

}

Labels (1)
0 Kudos
1 Solution
2,285 Views
alexandrunan
NXP Employee
NXP Employee

We don't encourage using calls of driver APIs from callbacks, the callback are done for signaling driver states. 
The showed issue is well known and a fix will be provided with S32K1xx RTM 3.0.3. A correct use is as scenario 1. 

The second scenario is not valid in this case because after callback finish execution the driver will modify the status of the Rx MB Fifo as complete in accordance with the first message.

View solution in original post

0 Kudos
4 Replies
2,286 Views
alexandrunan
NXP Employee
NXP Employee

We don't encourage using calls of driver APIs from callbacks, the callback are done for signaling driver states. 
The showed issue is well known and a fix will be provided with S32K1xx RTM 3.0.3. A correct use is as scenario 1. 

The second scenario is not valid in this case because after callback finish execution the driver will modify the status of the Rx MB Fifo as complete in accordance with the first message.

0 Kudos
2,285 Views
manujagrawal
Contributor II

Dear alexandrunan

We have faced a similar issue and trying to find a workaround as we cannot have a while loop to check EVENT_DMA_COMPLETE in our application. 

After going through the driver's code, here is what I found:

FLEXCAN_CompleteRxMessageFifoData() is the function which calls the user callback on DMA completion and passes FLEXCAN_EVENT_DMA_COMPLETE as the event type to the user callback.

pastedImage_1.png

pastedImage_2.png

FLEXCAN_CompleteRxMessageFifoData() then returns to the parent function FLEXCAN_IRQHandlerRxFIFO() and after a few lines of code, the user callback is called again, but this time with FLEXCAN_EVENT_RXFIFO_COMPLETE event type. Hence, I assumed that at each RX_FIFO receive event with DMA, user callback will be called two times. After the user callback returns for the second time, FLEXCAN_IRQHandlerRxFIFO() function does not modify the status of the Rx MB Fifo as complete in accordance with the first message (it does that after the first call).

Therefore, I tried check for FLEXCAN_EVENT_RXFIFO_COMPLETE event instead of FLEXCAN_EVENT_DMA_COMPLETE in the event, like this:

pastedImage_5.png

But, but didn't get the second call of my callback. Practically, my callback was called only once with FLEXCAN_EVENT_DMA_COMPLETE after I ran the code. I tried with a breakpoint too at "RxFIFOdone = 1;", the code didn't stop.

Can you tell me if I am correct in my approach?

As a temporary fix (which works without while loop), I have modified the FLEXCAN_CompleteRxMessageFifoData() function by calling my callback again at the end with FLEXCAN_EVENT_RXFIFO_COMPLETE event; as shown in the image below. 

Can the temporary fix be a permanent solution too? Or you can help me debug my first approach?

pastedImage_6.png

Thanks and Regards

Manuj Agrawal

   PetrSalexandrunan

0 Kudos
2,285 Views
alexandrunan
NXP Employee
NXP Employee

Hello Manuj,

First I need to know some details about this issue, what version of SDK release did you use ? Based on code snippets from pictures it looks like an previous code version from RTM 303. 

Second we don't support driver modifications by customers only for special quotes and requested features. 

cuongtranmanh‌, can you check if in last release is an issue mentioned by Manuj.

BR,
Alexandru Nan

0 Kudos
2,285 Views
manujagrawal
Contributor II

Hello alexandrunan

   I have been using SDK verion RTM 3.0.0 with came with update package 11 of S32DS-2018.R1

   Please do let me know an appropriate fix for avoiding the use of while loop with RxFIFO DMA.

   Also, is there a newer version of SDK available, if so, how do I obtain it?

Regards

Manuj Agrawal

0 Kudos