CAN发送的底层逻辑:CANwrite函数机制介绍

电子说

1.3w人已加入

描述

1.前言:AUTOSAR通信系列介绍

这个系列是全新的系列,整个系列会通过实际操作,调试实际的代码,以CAN为例,完整的解析AUTOSAR的从底层MCAL 到COM等上层模块的通信链路层。重点讲述数据的流向,以及各个模块的作用,配置方法。

通过这个系列,将会以代码的视角,了解如IPDU LPDU SDU HOH HTH HRH MB等AUTOSAR抽象概念的实际实现及其数据结构,以及在真实的AUTOSAR 架构软件中,CAN CANIF PDUR COM CANTP 等模块中数据的传输,配置参数,函数的调用等各个方面。让我们在使用AUTOSAR配置通信的同时,不被其架空,不当只会配置的工具人。

系列将会从MCAL自底向上,一步步分析各个模块,搞清楚整个通信的发送机制,和通信的接收机制。

2.Can_write函数介绍,以及HOH抽象的实施 MessgeBuffer介绍

整个的CAN发送,实际上是由Can模块里面的Can_write实现的。我们先以S32K14x MCAL代码为实例,介绍Can_write函数的发送机制,以对L_PDU HOH HTH Message Buffer这些抽象建立起基本的概念。

ECU执行完必要的初始化函数和设置controller模式后,我们就可以调用Can_Write函数来发送报文了。

Can_Write函数的传入参数有两个:

  1. hth:hardware transmit handle 硬件传输句柄。这个的详细讲解在后面。
  2. PduInfo(此即LPDU Data link Layer protocol)结构体成员如下:
    id:CAN报文ID
    swPduHandle:LPDU 句柄,此句柄在Canif层定义。每个句柄表示的是1个LPDU.用来在发送的最后时刻触发PDU的tx_confirmation.
    length:LPDU数据长度,即报文的长度。
    sdu:LPDU的数据指针。

实例:Can_write函数介绍,以及HOH抽象的实施 MessgeBuffer介绍

我们以一个简单的例子说明:

如下是代码:

PDU

如下是报文:

PDU

这个例子介绍了AUTOSAR发送报文的最底层接口的使用方法,可以先建立一个直观的印象。

can_write的第一个参数hth是AUTOSAR标准里面的一个概念,接下来的内容的讲解目的是为了透彻的理解hth。

AUTOSAR从MCAL开始 就对CAN进行抽象了,抽象出HOH Hardware object handle 硬件处理对象,HOH以发送和接收的不同,分为了HTH,HRH,这俩可以统称为HOH。

HOH对象包括很多属性,如

Can Implementation Type(FULL/BASIC)

Can ID Message Type(STANDARD/MIXED/EXTEND)

Can Controller Reference (使用哪个can controler)

Number of Hw objects used to implement one HOH

等等属性。

当我们用其中的一个HOH作为对象来发送报文时,这个报文的发送属性会继承这个HOH对象的所有属性。

举例说明:

EB(S32K148)中配置了如下几个HOH:

PDU

这里的配置实际会影响的是Can_PBcfg中的MessgeBuffer的配置结构体,MessgeBuffer结构体数组是HOH的具体实施,它的含义下文详细描述。Can Object ID即为HOH的ID。

在Can_write例子中我们传入HTH的是4,即利用HOH_3_EcuTestNode_CanCluster这个HOH作为对象,进行发送。

深入Can_write中,调用的是Can_FlexCan_Write的这个函数:

PDU

他会先搜索Messge Buffer配置结构体中u32HWObjID为hth,即为4的这个配置。

Messge Buffer的配置结构体的部分成员:

static CONST(Can_MBConfigObjectType, CAN_CONST) MessageBufferConfigs0_PB[CAN_MAXMBCOUNT_PB] =
{
    /* HOH_0_EcuTestNode_CanCluster Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)0x0U, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_RECEIVE, /* Receive/Transmit MB configuration */
        (Can_IdType)0x0U, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x0U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U, /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x0080U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)0U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(boolean)FALSE
        #endif
    },


    /* HOH_3_UDSTX_Node Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)CAN_MAXMASKCOUNT, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_TRANSMIT, /* Receive/Transmit MB configuration */
        (Can_IdType)0x7eaU, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x1U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U,   /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x0180U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)16U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(uint8)FALSE
        #endif
    },


    /* HOH_3_NMTX_Node Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)CAN_MAXMASKCOUNT, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_TRANSMIT, /* Receive/Transmit MB configuration */
        (Can_IdType)0x424U, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x2U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U,   /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x0190U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)17U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(uint8)FALSE
        #endif
    },


    /* HOH_3_XCPTX_Node Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)CAN_MAXMASKCOUNT, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_TRANSMIT, /* Receive/Transmit MB configuration */
        (Can_IdType)0x667U, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x3U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U,   /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x01a0U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)18U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(uint8)FALSE
        #endif
    },


    /* HOH_3_EcuTestNode_CanCluster Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)CAN_MAXMASKCOUNT, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_TRANSMIT, /* Receive/Transmit MB configuration */
        (Can_IdType)0x110U, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x4U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U,   /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x01b0U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)19U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(uint8)FALSE
        #endif
    },
    /* HOH_3_EcuTestNode_CanCluster Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)CAN_MAXMASKCOUNT, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_TRANSMIT, /* Receive/Transmit MB configuration */
        (Can_IdType)0x110U, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x4U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U,   /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x01c0U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)20U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(uint8)FALSE
        #endif
    },........

所以上文函数搜索到的第一个结构体成员一定是第一个Hardware Object ID为4的这个MB 结构体:

/* HOH_3_EcuTestNode_CanCluster Message Buffer of Can Controller ID = 0U*/
    {
        (Can_HwHandleType)CAN_MAXMASKCOUNT, /* uIdMaskIndex */
        (uint8)0U, /* ControllerId  - based on the order from CanController list */
        (CanIdType)CAN_STANDARD, /* ID type: EXTENDED, STANDARD, MIXED */
        (Can_ObjType)CAN_TRANSMIT, /* Receive/Transmit MB configuration */
        (Can_IdType)0x110U, /* MessageId */
        (uint8)0x0U, /* Local priority bits used for arbitration */
        (Can_HwHandleType)0x4U, /* Hardware Object ID */
        #if (CAN_FD_MODE_ENABLE == STD_ON)
        (uint8)0U,
        #endif
        /* Read/Write period reference used when POLLING mode is selected for the controller */
        (uint8)0U,   /* HOH configured for INTERRUPT mode, reference not used */

        (uint16)0x01b0U,       /* Address of Message Buffer  */
        (uint8)8U,    /* Payload lenth of Message Buffer */
        (uint8)19U    /* The index of MB in message buffer memory */
        #if (CAN_TRIGGER_TRANSMIT_EN == STD_ON)
        /* The parameter is used to detect the MB which run with trigger transmit feature */
        ,(uint8)FALSE
        #endif
    },

以这个成员的配置去改变对应的寄存器,从而让发送的报文继承这里面的属性。

我们现在需要搞明白的就剩这个MessgeBuffer配置结构体。

结构体里面的属性的含义,这些看EB的CAN模块的配置手册可以搞明白,我想介绍的是MessgeBuffer这个机制。这是S32K Flex CAN的机制

PDU

这是 Flex CAN的报文缓冲。报文缓冲有很多,配置好相关寄存器,最后将报文数据写入报文缓冲,可完成发送。

我们注意到MessageBufferConfigs0_PB中的每个结构体成员都有表示Address of Message Buffer的属性和表示The index of MB in message buffer memory的属性。这属性各个成员全不同并且是序号,地址按顺序递增的现象。所以这些结构体成员就是一个一个不同的Messagebuffer。再注意到之前提到的Can_Write中传入的Hth即是这里的Hardware Object ID。最后两个结构体,你发现他们虽然Message Buffer的地址不同,但是共用一个Hth号4.实际上完整的Messagebuffer的定义,有十个结构体成员都是共用4号Hth.

这是由EB配置项Number of Hw objects used to implement one HOH配为10决定的。这里 Hw objects即不同的MessageBuffer。但是他们关联了同个Hth。换言之1个Hth中可以包括多个MessageBuffer。即HTH是比MessageBuffer是更高层的抽象,例子中向Can_Write传入这个ID为4的hth,可以有10个MessageBuffer供选择写入数据,一个MessgeBuffer被占了我再找下个MessageBuffer。这样的配置作用就是使用这个HTH,可以在极短时间同时支持最多10个报文的发送。

以上例子Can_write函数的底层实现的逻辑简化说明如下:
1.轮询Messge Buffer配置结构体中u32HWObjID为hth是4的MB结构体成员。

2找到第一个hth为4的MessageBuffer。传入LPDU数据,尝试更新MessageBuffer发送,再判断是否是CAN_BUSY状态。假如是,找下一个Hth为4的MB继续尝试发送,直到成功发送出去一次,返回CAN_OK。

这期的介绍就到这里,本期我们可以搞清楚什么是LPDU,什么是HOH和HTH。从HOH的实际实施可以看出,所谓的AUTOSAR抽象,即将某个对象的所有配置,用结构体数组打包在一起,然后给他们编号。这个编号和各个对象的配置一一对应。后面需要使用这个对象的时候即使用编号去索引对应的结构体数组即可。这个思路会贯穿整个的AUTOSAR实现。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分