0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

冬至子 来源:汽车电子过山车 作者:欢乐皮皮峰 2023-07-17 15:47 次阅读

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介绍

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

如下是代码:

图片

如下是报文:

图片

这个例子介绍了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:

图片

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

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

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

图片

他会先搜索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的机制

图片

这是 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实现。

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

    关注

    31

    文章

    5317

    浏览量

    120001
  • CAN通信
    +关注

    关注

    5

    文章

    93

    浏览量

    17810
  • 缓冲器
    +关注

    关注

    6

    文章

    1917

    浏览量

    45449
  • AUTOSAR
    +关注

    关注

    10

    文章

    350

    浏览量

    21468
  • PDU
    PDU
    +关注

    关注

    0

    文章

    93

    浏览量

    16963
收藏 人收藏

    评论

    相关推荐

    逻辑函数逻辑问题的介绍

    本帖最后由 gk320830 于 2015-3-9 22:17 编辑 逻辑函数逻辑问题的描述  在讨论了与、或、非三种基本逻辑运算后,下面将从工程实际出发,提出
    发表于 04-06 23:57

    ESM6802 Android版支持双CAN通信

    libCanControl.so文件的C/C++源码做参考。这样,对于Android应用开发的客户来说,只需要专注于Java层的应用逻辑开发。  CanControl类的四个native函数简单介绍如下
    发表于 10-20 11:32

    请问CAN接收中断DSP底层会怎么样?

    请教:正常流程:CAN设置成中断接收方式,通过CAN调试助手,发送一帧数据,产生一个CAN接收中断,并进行数据处理;异常流程:如果我发送
    发表于 10-17 14:37

    EPP逻辑接口WinDriver底层驱动的可视化

    取自外部CAN总线系统的+5V电源;发光二极管用做电源和主、备节点的收发指示。2 EPP和SJAl000之间的接口逻辑设计 在EPP接口和SJAl000之间加入适当的逻辑接口,可以避免传统设计中对EPP
    发表于 11-29 14:51

    iTOP-iMX6开发板-Android-can测试例程介绍

    Java_can_hardware_hardwareControl_canWrite这是 can发送接口。JNIEXPORT jobject JNICALL
    发表于 03-11 10:24

    can底层驱动配置好的前提下,向DSP发送任何数据,can就能接收到数据吗

    我想问下在can底层驱动配置好的前提下,我向DSP发送任何数据,can就能接收到数据吗,然后将RMP=1即ECanaShadow.CANRMP.bit.RMP1 = 1;还是说必须
    发表于 07-08 15:39

    逻辑代数与逻辑函数

    逻辑代数与逻辑函数:本章主要讨论分析和设计数字逻辑功能的数学。首先介绍逻辑代数中的基本运算、基本
    发表于 09-01 09:11 0次下载

    逻辑函数逻辑问题的描述

    逻辑函数逻辑问题的描述   在讨论了与、或、非三种基本逻辑运算后,下面将从工程实际出发,提出逻辑命题,然后用真值表加以描述,从真值表可以
    发表于 04-06 23:56 1347次阅读
    <b class='flag-5'>逻辑</b><b class='flag-5'>函数</b>与<b class='flag-5'>逻辑</b>问题的描述

    STM32_CAN发送和接收过滤原理

    STM32_CAN发送和接收过滤原理介绍
    发表于 07-22 17:04 9次下载

    CAN为什么会发送失败

    CAN总线调试过程中出现报文发送失败,很多工程师都对此只知其一不知其二,这里就CAN报文发送失败的问题我们来做一次探讨。在了解CAN报文为什
    发表于 07-19 18:47 1.9w次阅读
    <b class='flag-5'>CAN</b>为什么会<b class='flag-5'>发送</b>失败

    03 底层函数

    03 底层函数
    发表于 10-11 09:29 7次下载
    03 <b class='flag-5'>底层</b>库<b class='flag-5'>函数</b>

    逻辑NOT函数功能介绍

    逻辑NOT函数输出在其单个输入为false时为true,在单个输入为true时为false逻辑NOT函数仅为单个输入反相器将逻辑电平“1”的
    的头像 发表于 06-23 05:48 9050次阅读
    <b class='flag-5'>逻辑</b>NOT<b class='flag-5'>函数</b>功能<b class='flag-5'>介绍</b>

    CAN底层驱动数据的传输需要注意什么

    ,但经典CAN还是使用最多和最频繁的,在底层驱动中,我们要注意数据的传输。 如我们在读取CAN数据帧的时候需要做调整,我们以NXP的 Kinetis系列为例子, 同样在发送传输的时候,
    的头像 发表于 06-04 14:49 1893次阅读
    <b class='flag-5'>CAN</b><b class='flag-5'>底层</b>驱动数据的传输需要注意什么

    IGBT驱动优化的底层逻辑是什么

    ——驱动优化的底层逻辑是什么?
    的头像 发表于 04-29 16:15 2816次阅读

    PduR模块的发送机制 PduR这个模块对什么进行了抽象呢?

    前两期,我们讲了CAN模块的发送逻辑,Canif模块的发送逻辑发送确认
    的头像 发表于 07-17 15:54 3066次阅读
    PduR模块的<b class='flag-5'>发送机制</b> PduR这个模块对什么进行了抽象呢?