赞
踩
1,这里我采用正序逻辑给出整个调用过程。
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中的地址上。
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;
}
/* 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
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])); }
上述配置完成后,如果使能中断将会进入下述的中断处理函数。函数末尾便是回调函数的调用。
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)); }
static FLEXCAN_CALLBACK(flexcan_callback)
{
/* Process FlexCAN Tx event. */
if ((kStatus_FLEXCAN_TxIdle == status) && (HAL_FLEXCAN_TX_MESSAGE_BUFFER_NUM == result))
{
txComplete = true;
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。