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

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;
    }
}

                              

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: S32SDK(S32 Software Development Kit)是一款针对NXP半导体产品的软件开发工具包。它提供了丰富的开发工具和库,用于帮助开发人员在NXP S32处理器上进行嵌入式软件开发。 can_pal(Controller Area Network Physical Abstraction Layer)是S32SDK的一个重要模块,它提供了与CAN(Controller Area Network)总线通信相关的物理抽象层。CAN总线是一种应用广泛的实时通信协议,常用于汽车电子系统、工控领域等。 can_pal提供了一系列的API和函数,用于控制和管理CAN总线的物理层。它可以实现CAN总线的初始化、帧发送和接收、过滤器设置、错误处理等功能。开发人员可以通过调用can_pal的接口函数,简化CAN总线通信的操作,并且可以实现更加高效和可靠的数据传输。 FlexCAN(Flexible Controller Area Network)是S32SDK另一个重要的模块,它是NXP S32处理器上的CAN总线控制器。FlexCAN提供了与硬件相关的低层API和功能,用于直接控制和管理S32处理器上的CAN硬件。 开发人员可以使用FlexCAN模块来配置CAN总线的各种参数,如波特率、工作模式、传输格式等。另外,FlexCAN还提供了相关的断和触发机制,用于实现实时的CAN总线数据传输和处理。通过与can_pal模块配合使用,开发人员可以更加灵活和高效地进行CAN总线的通信开发。 综上所述,S32SDK的can_pal和FlexCAN模块是针对NXP S32处理器上的CAN总线开发的重要工具。can_pal提供了与CAN总线物理层通信相关的抽象层,而FlexCAN则负责底层的CAN总线硬件控制和管理。它们的结合可以帮助开发人员更高效、可靠地进行CAN总线的开发和应用。 ### 回答2: s32sdk是一种嵌入式软件开发工具包,专门用于开发汽车电子系统的嵌入式应用程序。Can_pal和flexcan是s32sdk两个重要的模块。Can_pal模块是一个CAN总线物理抽象层,它提供了一系列针对CAN总线的函数和接口,帮助开发者轻松实现CAN总线的操作。Can_pal模块可以提供CAN总线的初始化、发送和接收数据等功能,支持现有的CAN硬件接口,方便开发者在不同的硬件平台上进行开发。 而flexcan则是一个基于CAN总线协议的控制器模块,它可以控制CAN通信的各项参数,以及CAN消息的发送和接收。flexcan模块可以配置CAN控制器的工作模式、波特率等参数,实现车载系统不同模块之间的高速通信。该模块支持多个发送和接收缓冲区,实现了多个消息的同时发送和接收。flexcan模块在s32sdk扮演了极为重要的角色,它以高性能和灵活性,为汽车电子系统的开发者提供了一个可靠而高效的解决方案。 总的来说,s32sdk的Can_pal和flexcan模块在汽车电子系统的嵌入式软件开发起到了关键作用。Can_pal模块提供了一系列CAN总线操作的函数和接口,Can_pal模块则提供了CAN控制器的控制和配置功能。这两个模块的结合使得开发者能够轻松地对CAN总线进行操作和控制,实现车辆内不同模块之间的高速通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值