1,这里我采用正序逻辑给出整个调用过程。
step1:去启动文件中找到对应的中断处理函数
PUBWEAK CAN0_IRQHandler
PUBWEAK CAN0_DriverIRQHandler
SECTION .text:CODE:REORDER:NOROOT(2)
CAN0_IRQHandler
LDR R0, =CAN0_DriverIRQHandler
BX R0
可以看出一旦有CAN相关的中断,都会将CAN0_DriverIRQHandler函数的地址赋值给R0,然后BX 跳转到R0中的地址上。
step2:追踪CAN0_DriverIRQHandler函数实现
void CAN0_DriverIRQHandler(void);
void CAN0_DriverIRQHandler(void)
{
assert(NULL != s_flexcanHandle[0]);
s_flexcanIsr(CAN0, s_flexcanHandle[0]); //这里使用了函数指针
//本质上调用FLEXCAN_TransferHandleIRQ
SDK_ISR_EXIT_BARRIER;
}
step3 追踪s_flexcanIsr变量的定义
/* Typedef for interrupt handler. */
typedef void (*flexcan_isr_t)(CAN_Type *base, flexcan_handle_t *handle);
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
static flexcan_isr_t s_flexcanIsr = (flexcan_isr_t)DefaultISR;
#else
static flexcan_isr_t s_flexcanIsr;
#endif
step4:对s_flexcanIsr变量的初始化以及输入参数
s_flexcanIsr = FLEXCAN_TransferHandleIRQ;
s_flexcanHandle[instance] = handle;//中断函数的参数
void FLEXCAN_TransferCreateHandle(CAN_Type *base,
flexcan_handle_t *handle,
flexcan_transfer_callback_t callback,
void *userData)
{
assert(NULL != handle);
uint8_t instance;
/* Clean FlexCAN transfer handle. */
(void)memset(handle, 0, sizeof(*handle));
/* Get instance from peripheral base address. */
instance = (uint8_t)FLEXCAN_GetInstance(base);
/* Save the context in global variables to support the double weak mechanism. */
s_flexcanHandle[instance] = handle;//中断函数的参数
/* Register Callback function. */
handle->callback = callback;
handle->userData = userData;
s_flexcanIsr = FLEXCAN_TransferHandleIRQ;// 实际的中断函数体 在CAN0_DriverIRQHandler中被调用
if (handle->callback != NULL)
{
FLEXCAN_EnableInterrupts(
base, (uint32_t)kFLEXCAN_BusOffInterruptEnable | (uint32_t)kFLEXCAN_ErrorInterruptEnable |
(uint32_t)kFLEXCAN_RxWarningInterruptEnable | (uint32_t)kFLEXCAN_TxWarningInterruptEnable |
(uint32_t)kFLEXCAN_WakeUpInterruptEnable
#if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
| (uint64_t)kFLEXCAN_PNMatchWakeUpInterruptEnable |
(uint64_t)kFLEXCAN_PNTimeoutWakeUpInterruptEnable
#endif
#if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
| (uint64_t)kFLEXCAN_HostAccessNCErrorInterruptEnable |
(uint64_t)kFLEXCAN_FlexCanAccessNCErrorInterruptEnable |
(uint64_t)kFLEXCAN_HostOrFlexCanCErrorInterruptEnable
#endif
);
}
else
{
FLEXCAN_DisableInterrupts(
base, (uint32_t)kFLEXCAN_BusOffInterruptEnable | (uint32_t)kFLEXCAN_ErrorInterruptEnable |
(uint32_t)kFLEXCAN_RxWarningInterruptEnable | (uint32_t)kFLEXCAN_TxWarningInterruptEnable |
(uint32_t)kFLEXCAN_WakeUpInterruptEnable
#if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE)
| (uint64_t)kFLEXCAN_PNMatchWakeUpInterruptEnable |
(uint64_t)kFLEXCAN_PNTimeoutWakeUpInterruptEnable
#endif
#if (defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
| (uint64_t)kFLEXCAN_HostAccessNCErrorInterruptEnable |
(uint64_t)kFLEXCAN_FlexCanAccessNCErrorInterruptEnable |
(uint64_t)kFLEXCAN_HostOrFlexCanCErrorInterruptEnable
#endif
);
}
/* Enable interrupts in NVIC. */
(void)EnableIRQ((IRQn_Type)(s_flexcanRxWarningIRQ[instance]));
(void)EnableIRQ((IRQn_Type)(s_flexcanTxWarningIRQ[instance]));
(void)EnableIRQ((IRQn_Type)(s_flexcanWakeUpIRQ[instance]));
(void)EnableIRQ((IRQn_Type)(s_flexcanErrorIRQ[instance]));
(void)EnableIRQ((IRQn_Type)(s_flexcanBusOffIRQ[instance]));
(void)EnableIRQ((IRQn_Type)(s_flexcanMbIRQ[instance]));
}
step5:中断触发时
上述配置完成后,如果使能中断将会进入下述的中断处理函数。函数末尾便是回调函数的调用。
void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle)
{
/* Assertion. */
assert(NULL != handle);
status_t status;
uint32_t mbNum = 0xFFU;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_PN_MODE) && FSL_FEATURE_FLEXCAN_HAS_PN_MODE) || \
(defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) || \
(defined(FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL) && FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL)
uint64_t result = 0U;
#else
uint32_t result = 0U;
#endif
do
{
/* Get Current FlexCAN Module Error and Status. */
result = FLEXCAN_GetStatusFlags(base);
/* To handle FlexCAN Error and Status Interrupt first. */
if (0U != (result & FLEXCAN_ERROR_AND_STATUS_INIT_FLAG))
{
status = kStatus_FLEXCAN_ErrorStatus;
/* Clear FlexCAN Error and Status Interrupt. */
FLEXCAN_ClearStatusFlags(base, FLEXCAN_ERROR_AND_STATUS_INIT_FLAG);
}
else if (0U != (result & FLEXCAN_WAKE_UP_FLAG))
{
status = kStatus_FLEXCAN_WakeUp;
FLEXCAN_ClearStatusFlags(base, FLEXCAN_WAKE_UP_FLAG);
}
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
else if ((0U != (result & FLEXCAN_MEMORY_ENHANCED_RX_FIFO_INIT_FLAG)) &&
(0u != (base->ERFIER & FLEXCAN_MEMORY_ENHANCED_RX_FIFO_INIT_MASK)))
{
status = FLEXCAN_SubHandlerForEhancedRxFifo(base, handle, result);
}
#endif
else
{
/* To handle Message Buffer or Legacy Rx FIFO transfer. */
status = FLEXCAN_SubHandlerForDataTransfered(base, handle, &mbNum);
result = mbNum;
}
/* Calling Callback Function if has one. */
if (handle->callback != NULL)
{
handle->callback(base, handle, status, result, handle->userData);//这里触发了回调函数
}
} while (FLEXCAN_CheckUnhandleInterruptEvents(base));
}
step6:调用回调函数
static FLEXCAN_CALLBACK(flexcan_callback)
{
/* Process FlexCAN Tx event. */
if ((kStatus_FLEXCAN_TxIdle == status) && (HAL_FLEXCAN_TX_MESSAGE_BUFFER_NUM == result))
{
txComplete = true;
}
}