当前位置:   article > 正文

浅析NXP_SDK_API中回调函数调用过程——基于KW45 Flexcan模块_nxp的flexcan的api

nxp的flexcan的api

1,这里我采用正序逻辑给出整个调用过程。

step1:去启动文件中找到对应的中断处理函数

     	PUBWEAK CAN0_IRQHandler
        PUBWEAK CAN0_DriverIRQHandler
        SECTION .text:CODE:REORDER:NOROOT(2)
		CAN0_IRQHandler
	        LDR     R0, =CAN0_DriverIRQHandler
	        BX      R0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以看出一旦有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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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]));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

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));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

step6:调用回调函数

static FLEXCAN_CALLBACK(flexcan_callback)
{
    /* Process FlexCAN Tx event. */
    if ((kStatus_FLEXCAN_TxIdle == status) && (HAL_FLEXCAN_TX_MESSAGE_BUFFER_NUM == result))
    {
        txComplete = true;
    }
}

                              

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/144521
推荐阅读
相关标签
  

闽ICP备14008679号