Dear support team:
I have a problem when i process the busoff event. It will lose the Busoff event process in some cases.
The main CAN interrupt process flow is showed below.
When the bus off event is occured after the condition check ((esr_reg & CAN_ESR1_BOFFINT_MASK) != 0) in the callback function, the last operation (clear all interrupt flags) will clear the busoff flag(BOFFINT: bit2 of ESR1). So when we enter the interrupt again because of the busoff event, we will find the BOFFINT bit is not set and the busoff event will not be processed.
The solution in our side is to change the last operation from <Clear all error interrupt flags> to <clear the processed error interrupt flags>. Now it works fine.
Because it need change the SDK, so i hope you can give a solution that will not changed the SDK.
Best regards!
Cheney.
已解决! 转到解答。
As I told you your request affects the driver if I implemented some errors events can be lost, maybe you are not interested in that events but some else can use it, this is why user need to read first the ESR register.
But we will evaluate if this impacts the driver or not !
As I told you your request affects the driver if I implemented some errors events can be lost, maybe you are not interested in that events but some else can use it, this is why user need to read first the ESR register.
But we will evaluate if this impacts the driver or not !
In the callback do you have a function that keeps isr asserted to much from what I saw from your example, probably in the callback you hook a big function call. Another issue can be is to remove from FLEXCAN_IRQHandler the part with esr check and handler error that is for other platform. In case of S32K144 have dedicated error handler if activated.
#if (defined(CPU_S32K116) || defined(CPU_S32K118))
uint32_t ecr = FLEXCAN_GetErrorCounters(base);
/* Check if any error occurred */
if (ecr != 0U)
{
FLEXCAN_Error_IRQHandler(instance);
}
#endif /* (defined(CPU_S32K116) || defined(CPU_S32K118)) */
BR,
Alexandru Nan
Hi, Alexandru:
Thank you for your reply.
I defined a CAN error process callback function as Figure2. And i install it when system is start.
FLEXCAN_DRV_InstallErrorCallback(canHwChannel, CanErrIsrCbk, NULL);
The following is the key code.
Figure 1: Error handler in flexcan_driver.c
Figure 2: CAN error handler callback funtion
you can imagine such a scenario:
Is there a way to evade the problem in the condition using the original the SDK?
Best Regards!
Cheney.
To avoid this problem I suggest you to read ESR register and modify the FLEXCAN_ClearErrIntStatusFlag function to allow another parameter as mask to clear, and the Error_Handler.
Be aware that reading the ESR register can alter the content of the register from previous read by clear the status of some bits. RM : "Read this register to capture all error condition and status bits. This action clears the
respective bits that were set since the last read access."
This is way the driver was implemented by clear all condition and to user to read the status of errors to capture all the events.
void FLEXCAN_Error_IRQHandler(uint8_t instance)
{
DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
CAN_Type * base = g_flexcanBase[instance];
flexcan_state_t * state = g_flexcanStatePtr[instance];
/* Invoke callback */
aux = read ESR;
if (state->error_callback != NULL)
{
state->error_callback(instance, FLEXCAN_EVENT_ERROR, state);
}
/* Clear all other interrupts in ESR1 register (Error, Busoff, Wakeup) */
FLEXCAN_ClearErrIntStatusFlag(base,aux);
return;
}
void FLEXCAN_ClearErrIntStatusFlag(CAN_Type * base, uint32_t aux)
{
if((base->ESR1 & FLEXCAN_ALL_INT) != 0U)
{
(base->ESR1) = FLEXCAN_ALL_INT&aux;
#ifdef ERRATA_E9005
/* Dummy read as a workaround for errata e9005 to ensure the flags are
cleared before continuing. */
(void)(base->ESR1);
#endif
}
}
BR,
Alexandru Nan