中国汽车工程师之家--聚集了汽车行业80%专业人士 

论坛口号:知无不言,言无不尽!QQ:542334618 

本站手机访问:直接在浏览器中输入本站域名即可 

  • 129查看
  • 0回复

[电子架构] E2E 系统,软件,测试人员需要了解

[复制链接]

该用户从未签到

发表于 7-4-2024 17:33:48 | 显示全部楼层 |阅读模式

汽车零部件采购、销售通信录       填写你的培训需求,我们帮你找      招募汽车专业培训老师


E2E

本文不是解读规范。而是理解与场景相结合,噫在说E2E这个事情本身。可能没法直接套用,但是读完之后,你会在各种变化中都明白个大概。然后看看规范就知道怎么使用了。

从 说这么个事情,到为什么这样做,到代码简单讲解

           

1. overview

    1.1 Pdu 简单介绍

    1.2 保护路径

    1.3 Frame & pdu

        1.3.1 pdu分类

        1.3.2 Autosar定义的PDU

2. E2E  实现方式

    2.1 Callout

    2.2 Wrapper

        2.2.1 Wrapper behind SWC

        2.2.2 Wrapper within SWC - Transmission Manager

    2.3 Transformer

        2.3.1 CANFD ContainerPDU定义

        2.3.2 CANFD Signal-I-PDU定义

        2.3.3 CANFD实际数据解析

        2.3.4 总结

3. E2E 保护机制

    3.1 E2E_Profile1A 概述

    3.2 E2E_Profile1A 实现


[img=553.1400146484375,268.94000244140625]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkzRJN8t401hMGyAF9FCcYSXxAPYcj94jWJSccj8KicECzYMICBzOU9PQ/640?wx_fmt=png[/img]
   

1. overview

E2E 的保护概念是针对软件在运行时数据交换的保护。运行时数据发生问题的地方可能有很多。

数据链路,外围收发,单片机硬件,传输过程等等等等。外围电路的电池干扰等也都可能会对数据造成影响。这里End 2 End 就是为了检验出数据有没有发生问题。

从数据 发送端 到 接收端,可能是两个ECU 也可以是两个SWC, 甚至数据的上下环节都可以做E2E校验。下面以ECU之间的端到端检测例子。

[img=552.010009765625,365.010009765625]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnktWYA3aZFTGI1aBnxsQvlD1cLcZUvKWllx5m6eZicbWeLyCHoLjodpew/640?wx_fmt=png[/img]
   

Overview of E2E communication protection between a sender and a receiver         

1.1 Pdu 简单介绍

所以这个数据到底是什么?我们有必要了解一下不同位置的数据的名字。因为在保护的过程是需要有针对性的。而且不同的层级保护路径覆盖是不一样的。也就意味着安全等级是可能不一样的。

传统互联网分层的报文与autosar定义的相对比。

应用层——消息

传输层——数据段/报文段(segment) (注:TCP叫TCP报文段,UDP叫UDP数据报,也有人叫UDP段)

网络层——分组、数据包(packet)

链路层——帧(frame)

物理层——P-PDU(bit)

[img=552.010009765625,118.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkgZpzQO3xkyfsT8R4bDrUtRMiaz4wG9HJgibVyTwn0bGuSG2qVEknYs1A/640?wx_fmt=png[/img]

互联网的定义         

[img=552.010009765625,217.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkAV0bDib2164ehWLBbwq0nb2yOMNIhFicQLQgjlXVZMm4B4U4rHxMYuicw/640?wx_fmt=png[/img]

autosar的定义         
   

从上面图可以看出来,在autosar体系中,只要从驱动出来到了中间件(BSW) 统一都叫做PDU. 只是前缀可能不一致。更为具体细致的pdu了解可以见下图,不过和本文关系不大。

[img=552.010009765625,292.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnk8w4kkqd1hMTT9LWk8RKKeIfcSqcWC6JFa5tv1D3jovfzlttJic5cSEQ/640?wx_fmt=png[/img]

现在我们知道了autosar体系中,每个层级的pdu 简单定义。下面我们来从几个角度说E2E 本身的事情。

1.2 保护路径

从过上面不同位置的PDU 的介绍,我们在数据保护的角度就需要找到可能发生数据出问题的路径,然后针对性的保护。

[img=552.010009765625,304.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkEhC3VMEPPH4bzIRbIqnKoibyfQEzWGcricR2g4MOO5lRn9JvQ8bgA7cA/640?wx_fmt=png[/img]
   

可以说有很多路径都会出现问题。所以我们就需要制定“比较好”的解决方案。

这里比较好可以从成本,安全性,便捷性等方面去考虑。所以这里引出了三种保护方案

1.3 Frame & pdu

通过前面的学习,我们知道,在autosar体系的内部,所有流动的数据,都可以叫做PDU. 我们以总线报文的收发来作为例子说一下。

1.3.1 pdu分类

说到总线报文和软件内部的PDU 进行保护,那么问题来了,frame 和 pdu的关系呢?注意了 E2E 保护的是什么。保护的是PDU. 可以理解为报文(frame)的一部分。我们来详细说一下 frame, pdu

在Arxml文件中定义的有如下类型:

[img=552.010009765625,262.6700439453125]https://mmbiz.qpic.cn/sz_mmbiz_jpg/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkxH5NGl0EXytMvI0COe5Pvqxss8pNiagmDjmiaZibPtf4sJWoJBvQou4Mw/640?wx_fmt=jpeg[/img]

点击图片可查看完整电子表格

说这个好像也没啥用,我的目的是为了说  frame = pdu*n + 额外信息 这里的n >= 1.

也就是说一帧frame 里面可以包含几个pdu的话,这帧报文就可能需要多次保护,因为保护的单位是pdu.

说到这个要说一下现在autosar 里面的定义了。

1.3.2 Autosar定义的PDU   

[img=552.010009765625,132.0]https://mmbiz.qpic.cn/sz_mmbiz_jpg/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkrDn76oAqWpUv3O5E4FQRr4YdDp0TyuEduxllWWqiab6iavnlq1GLOKeQ/640?wx_fmt=jpeg[/img]

点击图片可查看完整电子表格

对于普通CAN报文来说,一个message对应一个PDU,对于CANFD报文来说,引入Container PDU和contained I-PDU实现一个message对应多组PDU。

[img=552.010009765625,248.99996948242188]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkg9MkzfB3LIooO5nRMicibiaVOC2NKYYrzuGYwx4a9ibVVttnNW7JfTiatow/640?wx_fmt=png[/img]

考虑这样做的优势:

不同的contained I-PDU可以映射到不同的Container PDU的不同位置。不仅提高了灵活性,而且也会降低总线负载率。

有了这些知识,我们来聊一下autosar提到的三种E2E 实现方式。

2. E2E  实现方式

从保护的角度来说,最终的算法无论是callout 还是 wrapper 还是transformer 都是一样的。假设用CRC8 来计算,那么最终给PDU 添加的计算算法都是CRC8, 下面三种方式不一样的指的是路径不一样,和集成方式不一样。我们详细说一说。

2.1 Callout

Callout 指的是com callout. 举个例子,我们有一个pdu从asw 发出来,经过RTE 到达了COM. COM中维护的PDU 配置 可以选择callout.     

[img=552.010009765625,488.010009765625]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkGRcthgwh5QFzlS5BmO0GDFAScLZpd7ntLjsqTCutSvasAdhbVj2qsw/640?wx_fmt=png[/img]

COM 中 PDU 配置界面         

所以就是说 PDU 的tx 的内容 需要调用一个函数,然后继续往下走。这里面调用的函数就是callout. 我们在这里面去调用E2E 的相关接口。把PDU 内部的数据进行计算,进行更新。

然后 从COM 出去之后的数据就是经过了E2E 计算,赋值的数据包了。

从链路上来看,有一段处于空白,就是ASW 到COM 的阶段,这里面是没有保护的,所以这里是有可能发生数据错误的。我们从callout的角度来说,没办法去识别出来。

从下图也可以看出来调用callout的位置。   

[img=552.010009765625,303.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnks6sWU4U59dTVQiavGajOXmRH6WopLygdruwdSTWgBW46OLNe5nMRkmA/640?wx_fmt=png[/img]

callout         

所以callout 的保护只是发送端的com 到 对等接收端的com. 如果com之上发生了错误, 这种E2E方法是无法检测到的。所以为了可靠性,我们需要更进一步的去覆盖保护范围

2.2 Wrapper

说不出来词形容wrapper. 用一个 不昏不素来形容吧。wrapper的实现有两种。目的是什么呢。目的就是 保护 pdu从swc发出的那一刻 一直到对端swc 接收到pdu的时候。

确实挺好的设计,但是为什么说不昏不素呢。autosar 给了两种方式。

2.2.1 Wrapper behind SWC

大家都知道SWC 发送 接收 pdu 走的是 RTE_Read,,,,,, 和 RTE_Write,,,,,,  两种实现方式一种是 可以说是修改了RTE 的接口,在调用RTE 的接口的时候,先走了一遍 E2ELib.  也就是说在SWC 的下方多了个Wrapper的适配层。如下图所示   

[img=552.010009765625,338.010009765625]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkbicmiaDBPBcS3jxh2ppILWnyN2dxxoARR9S3D3VrWHg8HPnzVMxngzrQ/640?wx_fmt=png[/img]

保护的内容确实挺好,但是是不是每一个SWC 都需要这样的一个适配层。而且SWC 没办法调到原生的RTE 接口了。

2.2.2 Wrapper within SWC - Transmission Manager

然后呢,又来了个不昏不素的wrapper 实现。

既然想要原生的RTE 接口,那就把这个适配层放在RTE 接口和 SWC 之间。但是问题还是一样,每个SWC 都需要有这么个适配层。如下图,

[img=552.010009765625,327.010009765625]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkdlGnzWln4rCh2j3GgcNSpGzo6BpOzo70iblg5rF7ybyh3YxtdswkpFQ/640?wx_fmt=png[/img]

所以可能就是前面提到的两个缺点,引入了一种新的方式,保护的方式,内容,路径和wrapper 是一致的。只是从系统的角度去实现。   

2.3 Transformer

为什么说是系统的角度去实现,因为transformer 在做系统描述的时候,就已经去设计好了这一点。不需要在SWC 的设计阶段去做保护。

[img=552.010009765625,198.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkySqwHPNY9Eu5FGJp2UfoJ851bmsaVKuH69ZQkiaFkicdX8PE7vicrZDTg/640?wx_fmt=png[/img]

可以看得到,在系统描述文件的角度,已经把pdu 和 相对应的E2E 都连接好了。最终的实现是在RTE 内部进行实现。

那么问题来了,系统描述怎么知道pdu呢。毕竟在系统层面还是前面提到的frame啊。这里我CSDN 找了个写的比较好的。抄一段来说明一个message 包含多个pdu的概念。-- 来自 CSDN  Autosar开发笔记

2.3.1 CANFD ContainerPDU定义

ContainerPDU并不是frame,但可以设置ContainerPDU包含frame所有的数据位。ContainerPDU是包含在frame中的。对于一个CANFD-frame,定义如下:

               

注:若CANFD报文实际只有8字节,那么就和普通报文一样,定义一个I-Signal-PDU就够了,不需要引入容器PDU。

Container-I-PDU定义如下:

               

Header Type有三种选择:

1.ShortHeader 2.LongHeader 3.NoHeader

Autosar中定义如下:

IpduM支持两种不同的动态Container Pdu的头大小(参见ECUC_IpduM_00183: IpduMContainerHeaderSize):

IPDUM_HEADERTYPE_SHORT, 24位ID, 8位长度

IPDUM_HEADERTYPE_LONG, 32位ID, 32位长度

如果是选择的ShortHeader,那么实际数据位中会有三个byte为ID,一个byte为DLC,8个byte为数据位

在Container-PDU定义页可以选择包含的PDU及设置PDU对应的ID。

2.3.2 CANFD Signal-I-PDU定义

               

这个Signal-I-PDU就类似普通的CAN报文,里面定义了具体的信号信息,及layout信息。

2.3.3 CANFD实际数据解析

           

[img=552.010009765625,90.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnk3OiaVlQkgl2nEut4BMBWrzJvySj347G0EJCiaXaIQ494mYCUAcY9mpnA/640?wx_fmt=png[/img]

CANFD带Container的报文,实际数据长度为24,包含两个Signal-I-PDU(每个12个byte)

对应的Signal-I-PDU还可以继续展开解析后的信号具体信息

[img=552.010009765625,82.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnk3g45ic20v1RCbx57DdrhTPVdzicFgK0j2cicKfVGHdwYgy1q9Enu2RiabA/640?wx_fmt=png[/img]

回归主题,有了上面的介绍,Transformer 带来的好处就是 无需手动代码。   

SWC 自己的接口实现,无需关注自己的read 和 write 是否需要 E2E, 因为他所调用的RTE 接口,已经在系统描述的阶段做好了E2E.

2.3.4 总结

好了这里三种方式说完了。说了半天也没说到具体的计算算法,其实保护算法本身没有什么含量。关键的点在于知道什么时候该用这三种方式,针对性的对我们的系统进行设计。

3. E2E 保护机制

前面系统的层面去说了E2E 的为什么,和怎么去选择,去设计。这一章我们说一下具体E2E 内部是怎么实现的。为什么不在前面说,因为实现的本身是一样的。

思路是下图这样的。

[img=552.010009765625,219.0]https://mmbiz.qpic.cn/sz_mmbiz_jpg/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkx0O8BXXjbg2FZygwfovdxGmWjk15MGQpEvdeTZBZXNwgQ8xFf5IO0Q/640?wx_fmt=jpeg[/img]

那么我们从比较书面的方式去解释。

就拿E2E_Profile1A 来举例子

3.1 E2E_Profile1A 概述

上面我手画的保护信息值得就是下图   

[img=552.010009765625,186.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnk2oGicGoLDkKOGwXLXDictRvpVp6UCMMicuqwKSp4NibU2z4cm1vPwxDnZw/640?wx_fmt=png[/img]

注意规定好了保护方式后,保护的报文的某些字节需要放什么数据,是已经确定好了的。

最终形成的PDU 如下。

[img=552.010009765625,123.0]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkFuToEG2QwyAKGIAstFXlRdTtthdO8Xk1k3ibCfN6z6rkxaiaWHpsShgQ/640?wx_fmt=png[/img]

这里问个问题,上图是存在于哪里?

答:上图是被保护的单元,可能共同属于一个frame, 也可能就是一个frame 甚至属于多个frame的集合。

好了pdu,frame 的概念后面不提了。

那么我们怎么去实现呢。

3.2 E2E_Profile1A 实现

我们以发送pdu, 来保护这个pdu 为例子说明。

C                 
Std_ReturnType E2E_P01Protect(const E2E_P01ConfigType* ConfigPtr, E2E_P01ProtectStateType* StatePtr, uint8* DataPtr)

看一下这里面的形参

C                 
/** @brief Protects the array/buffer to be transmitted using the E2E profile 1.                 
*         This includes checksum calculation, handling of counter and Data ID.                 
*                 
*  @param ConfigPtr Pointer to static configuration.                 
*  @param StatePtr Pointer to port/data communication state.                 
*  @param DataPtr Pointer to Data to be transmitted.                 
*                 
*  @return Error code (E2E_E_INPUTERR_NULL || E2E_E_INPUTERR_WRONG || E2E_E_INTERR || E2E_E_OK).                 
*/        

我们需要对pdu进行参数配置。配置的内容如下

[img=552.010009765625,370.0100402832031]https://mmbiz.qpic.cn/sz_mmbiz_png/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkGK0Mdd5ib0EdGJV6icZep8aslfiayKlaP74Jhld6icd2RXPoj41zAR96hw/640?wx_fmt=png[/img]

这些的信息如果看清楚了前面我手画的信息,就很容易明白了,实际上就是各个参数的位置,长度,以及判断失败的标准。

第二个参数 是counter. E2E 是有CRC + Counter的。这个counter 也是需要这个算法本身去维护的。

第三个就是数据本身。   

跟着源码一步一步解释

C                 
Std_ReturnType E2E_P01Protect(const E2E_P01ConfigType* ConfigPtr, E2E_P01ProtectStateType* StatePtr, uint8* DataPtr) {                 
                 
    Std_ReturnType status;                 
    status = E2E_E_OK;                 
    Std_ReturnType returnValue = checkConfigP01(ConfigPtr);                 
                 
    if (E2E_E_OK != returnValue) {                 
        status = returnValue;                 
    }                 
                 
    else if ((StatePtr == NULL_PTR) || (DataPtr == NULL_PTR)) {                 
        status = E2E_E_INPUTERR_NULL;                 
    }                 
                 
    else {                 
        /* Put counter in data*/                 
        if ((ConfigPtr->CounterOffset % 8) == 0) {                 
            DataPtr[ConfigPtr->CounterOffset/8] = (DataPtr[(ConfigPtr->CounterOffset/8)] & 0xF0u) | (StatePtr->Counter & 0x0Fu);                 
        }                 
        else {                 
            DataPtr[ConfigPtr->CounterOffset/8] = (DataPtr[ConfigPtr->CounterOffset/8] & 0x0Fu) | ((StatePtr->Counter<<4) & 0xF0u);                 
        }                 
                 
        /* Put counter in data for E2E_P01_DATAID_NIBBLE */ // ASR4.2.2                 
        if (ConfigPtr->DataIDMode == E2E_P01_DATAID_NIBBLE) {                 
            if ((ConfigPtr->DataIDNibbleOffset % 8) == 0) {                 
                DataPtr[ConfigPtr->DataIDNibbleOffset/8] = (DataPtr[(ConfigPtr->DataIDNibbleOffset/8)] & 0xF0u) | ((uint8)((ConfigPtr->DataID>>8) & 0x0Fu));                 
            }                 
            else {                 
                DataPtr[ConfigPtr->DataIDNibbleOffset/8] = (DataPtr[ConfigPtr->DataIDNibbleOffset/8] & 0x0Fu) | ((uint8)((ConfigPtr->DataID>>4) & 0xF0u));                 
            }                 
        }                 
                 
        /* Calculate CRC */                 
        DataPtr[(ConfigPtr->CRCOffset/8)] = calculateCrcP01(ConfigPtr, StatePtr->Counter, DataPtr);                 
                 
        /* Update counter */                 
        StatePtr->Counter = (StatePtr->Counter+1) % 15;                 
    }                 
                 
    return status;                 
}        

在保护数据的前面,需要对Counter进行赋值。前面介绍到了counter的位置是固定的,也是有配置信息,的所以进行了赋值。不过有个需要注意的点就是mode。

E2E_P01DataIDMode = E2E_P01_DATAID_NIBBLE

这个是什么意思呢。   

[img=552.010009765625,277.0]https://mmbiz.qpic.cn/sz_mmbiz_jpg/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnk1frVPFj5lvhv0IleyMDUTKBnicEgAbA9uCswZlAGRsB7IEmWYKREdEw/640?wx_fmt=jpeg[/img]

这里的DataID 的一部分,需要放到counter的位置里面去。所以说 在更新counter的时候。用到了一部分DataId.

其他的点都很好理解。

这里counter已经更新完毕。我们开始计算CRC

C                 
uint8 calculateCrcP01(const E2E_P01ConfigType* Config, uint8 Counter, const uint8* Data)

在计算CRC, 需要用到什么。

DataId 需要计算

Counter 需要计算

Data 需要计算。

DataId 如何计算去觉得Config->DataIDMode 的配置。

唯一的数据 ID 用于验证每个传输的安全相关数据元素的身份。

二字节Data ID计算一字节CRC有以下四种包含方式:1. E2E_P01_DATAID_BOTH:CRC中包含两个字节(双ID配置),先低字节后高字节(请参见变体 1A - PRS_E2EProtocol_00227)或 2. E2E_P01_DATAID_ALT:取决于计数器的奇偶校验(交替 ID 配置),包括高字节和低字节(参见变体 1B - PRS_E2EProtocol_00228)。对于偶数计数器值,包括低字节,对于奇数计数器值,包括高字节。3. E2E_P01_DATAID_LOW:只包含低字节,从不使用高字节。这相当于数据 ID(在给定应用进程中)只有 8 位的情况。   

[img=552.010009765625,270.0]https://mmbiz.qpic.cn/sz_mmbiz_jpg/Vgbm9ibpszia4jkZuc8OpR3I6ZUibtnRbnkibicibLyfGg2QFWnicM3cXdC4xvOnWOTGjNIHwjJotyUDMqnb0XahemyjQ/640?wx_fmt=jpeg[/img]

这就是计算过程。

那么具体怎么算的呢。这个就是比较标准的做法。不多解释,直接给码

C                 
uint8 Crc_CalculateCRC8(const uint8* Crc_DataPtr, uint32 Crc_Length, uint8 Crc_StartValue8, boolean Crc_IsFirstCall) {                 
                 
    uint8 crc = 0;    /* Default return value if NULL pointer */                 
#if Crc_8_Mode == CRC_8_TABLE                 
    static const uint8 Crc_8_Tab[256] = {0x0, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53,                 
                                     0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb,                 
                                     0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e,                 
                                     0x25, 0x38, 0x1f, 0x2, 0x51, 0x4c, 0x6b, 0x76,                 
                                     0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4,                 
                                     0x6f, 0x72, 0x55, 0x48, 0x1b, 0x6, 0x21, 0x3c,                 
                                     0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x4, 0x19,                 
                                     0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1,                 
                                     0x13, 0xe, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40,                 
                                     0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8,                 
                                     0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d,                 
                                     0x36, 0x2b, 0xc, 0x11, 0x42, 0x5f, 0x78, 0x65,                 
                                     0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7,                 
                                     0x7c, 0x61, 0x46, 0x5b, 0x8, 0x15, 0x32, 0x2f,                 
                                     0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0xa,                 
                                     0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2,                 
                                     0x26, 0x3b, 0x1c, 0x1, 0x52, 0x4f, 0x68, 0x75,                 
                                     0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d,                 
                                     0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8,                 
                                     0x3, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50,                 
                                     0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2,                 
                                     0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x7, 0x1a,                 
                                     0x6c, 0x71, 0x56, 0x4b, 0x18, 0x5, 0x22, 0x3f,                 
                                     0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7,                 
                                     0x35, 0x28, 0xf, 0x12, 0x41, 0x5c, 0x7b, 0x66,                 
                                     0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e,                 
                                     0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab,                 
                                     0x10, 0xd, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43,                 
                                     0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1,                 
                                     0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x9,                 
                                     0x7f, 0x62, 0x45, 0x58, 0xb, 0x16, 0x31, 0x2c,                 
                                     0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4};                 
#endif                 
                 
    /* @req SWS_BSW_00212 NULL pointer checking */                 
    if (Crc_DataPtr != NULL_PTR) {                 
                 
        crc = (TRUE == Crc_IsFirstCall) ? Crc_8_StartValue : (Crc_StartValue8 ^ Crc_8_Xor);                 
                 
#if Crc_8_Mode == CRC_8_RUNTIME                 
        crc = calculateCRC8(Crc_DataPtr, Crc_Length, crc, Crc_8_Polynomial);                 
#elif Crc_8_Mode == CRC_8_TABLE                 
        for (uint32 byte = 0; byte < Crc_Length; byte++) {                 
            crc = Crc_8_Tab[crc ^ *Crc_DataPtr];                 
            Crc_DataPtr++;                 
        }                 
#endif                 
                 
        /* Only XOR value if any calculation was done */                 
        crc = crc ^ Crc_8_Xor;                 
    }                 
                 
    return crc;                 
}        

快速发帖

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|手机版|小黑屋|Archiver|汽车工程师之家 ( 渝ICP备18012993号-1 )

GMT+8, 30-4-2024 17:11 , Processed in 0.247575 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2013 Comsenz Inc.