0

如何从 Runnable 内部确定 c 中 PIM(每实例内存)的大小(无需在生成的 RTE 中查找并添加固定值)?

情况:Runnable Foo 可以访问两个 PIM Pim1 和 Pim2。在示例中,来自 Pim1 的数据应复制到 Pim2。

不仅因为安全性和安全性,我还需要检查两个 PIM 的大小,以免覆盖非法数据区域。我知道 PIM 的大小是在 SW-C 描述 (SWCD) 中配置的。但是由于SWCD在代码实现后可能会改变,为了保持Runnable的代码更通用,大小检查不应该基于固定值。

我还考虑了数组的sizeof问题: 如何找到'sizeof'(指向数组的指针)?

对于 PIM,RTE-Generator 生成以下代码:

在 Rte_Type.h

typedef uint8 Rte_DT_DtImplRec1_0;
typedef uint16 Rte_DT_DtImplRec1_1;

typedef struct
{
  Rte_DT_DtImplRec1_0 var1;
  Rte_DT_DtImplRec1_1 var2;
  Rte_DT_DtImplRec1_2 var3;
} DtImplRec1;

typedef uint8 Rte_DT_DtImplAry1_0;
typedef Rte_DT_DtImplAry1_0 DtImplAry1[5];

在 Rte.c

VAR(DtImplRec1, RTE_VAR_DEFAULT_RTE_PIM_GROUP) Rte_FOO_Pim1;
VAR(DtImplAry1, RTE_VAR_DEFAULT_RTE_PIM_GROUP) Rte_FOO_Pim2;

在 Rte_FOO.h

#define Rte_Pim_Pim1() (&Rte_FOO_Pim1)

#ifdef RTE_PTR2ARRAYBASETYPE_PASSING
# define Rte_Pim_Pim2() (&((*RtePim_Pim2())[0]))
#else
# define Rte_Pim_Pim2() RtePim_Pim2()
#endif

#define RtePim_Pim2() (&Rte_FOO_Pim2)

请注意,数组 PIM 的定义也可能会发生变化,具体取决于 RTE_PTR2ARRAYBASETYPE_PASSING “开关”。

为 FOO 模板生成以下“访问”:

DtImplRec1 *Rte_Pim_Pim1(void);
Rte_DT_DtImplAry1_0 *Rte_Pim_Pim2(void)

Foo-Runnable 的代码可能如下所示:

FUNC(void, FOO_CODE) Foo(void)
{
  DtImplRec1 *pim1 = Rte_Pim_Pim1();
  Rte_DT_DtImplAry1_0 *pim2 = Rte_Pim_Pim2();

  uint8 sizeOfPim1a = sizeof(Rte_Pim_Pim1());    /* always returns 4 as the size of the pointer */
  uint8 sizeOfPim1b = sizeof(*Rte_Pim_Pim1());   /* evaluates to 6 */
  uint8 sizeOfPim1c = sizeof(DtImplRec1);        /* evaluates to 6 */
  uint8 sizeOfPim1d = sizeof(Rte_FOO_Pim1);      /* evaluates to 6 */

  uint8 sizeOfPim2a = sizeof(Rte_Pim_Pim2());       /* always returns 4 as the size of the pointer */
  uint8 sizeOfPim2b = sizeof(*Rte_Pim_Pim2());      /* evaluates to 1 */
  uint8 sizeOfPim2c = sizeof(Rte_DT_DtImplAry1_0);  /* evaluates to 1: sizeof(uint8) */

  uint8 finalSize = MIN(sizeOfPim1b, sizeOfPim2b);

  memcpy( pim2, pim1, finalSize ); /* (use of) memcpy is not the topic here */
}

为了使我的问题更加“可见”,这里是一个 Callback-Runnable 示例,用于通过诊断编写 DID:

FUNC(Std_ReturnType, FOO_CODE)
  DataServices_Data_FFFF_WriteData(P2CONST(uint8, AUTOMATIC, RTE_APPL_DATA) Data, Dcm_OpStatusType OpStatus, P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, RTE_APPL_DATA) ErrorCode)
{
  Std_ReturnType ret = E_NOT_OK;

  #define sizeOfPim1     (5)   /* how to determine the PIM size here if we do not know anything about it here? (PIM structure can change without modifying the code here) */
  #define sizeOfDidFFFF  (5)   /* This is even another problem: How to determine the size of a DID. I will create another discussion thread for this question. */

  /* Instead of this if-condition, an assert during compile-time would also be appropriate */
  if( sizeOfPim1 == sizeOfDidFFFF )
  {
    /* We have to make sure that we do not copy more bytes as of the size of Pim1 */
    memcpy( Rte_Pim_Pim1(), Data, sizeOfPim1 ); /* (use of) memcpy is not the topic here */
    ret = E_OK;
  }

  return ret;
}
4

2 回答 2

0

您在这里有几个问题:a)您的 sizeof(*pim1) 由于填充而返回 6,因为您以 uint8 开头,第二个是 uint16,我猜第三个也是 uint16。

那就是为什么你应该按类型大小/对齐方式对它们进行排序......从大到小

uint32
uint16
uint8

即使元素可能不再排序,但它最终也会减少链接器创建的内存间隙。

b) pim2 是一个数组,您无法从指针中获取数组 len/size。但是,您应该具有 DtImplAry1 的 Rte 定义。

typedef uint8 Rte_DT_DtImplAry1_0;
typedef Rte_DT_DtImplAry1_0 DtImplAry1[5];  // <-- taken in through Rte_Foo_Type.h (includes Rte_Type.h

uint32 ary_len = sizeof(DtImplAry1) / sizeof(DtImplAry1[0]);
于 2017-07-19T01:21:04.513 回答
0

我这里没有任何 AUTOSAR 环境来测试这个,所以,如果你尝试任何一个,请告诉我它是否有效。此外,我不是专家,而且我已经很长时间没有编写 AUTOSAR 代码了,所以我可能会遗漏一些东西。我也不想公开来自任何供应商的任何 RTE 生成器,所以我将仅引用标准。

利用sizeof(DtImplAry1)

您定义该类型并将其作为 RTE 生成器的输入,因此您知道名称。如果您的 SWC 没有明确使用该类型,则 RTE 生成器无法将其包含在您的.h. 我认为所有工具都允许这样做,而无需手动编辑 arxml,只需寻找在您的工具中包含其他 SWC 类型的选项。

使用 Instance API 访问 SWC 数据

如果您启用 API(在您的工具中查找它),该标准指定一个类型的变量Rte_CDS_FOO来保存所有指向 SWC 的 PIM(除其他外)的指针。Rte_Inst_FOO此外,您应该可以使用一个变量,extern在您的标题中声明。你可以做sizeof(*Rte_Inst_FOO->Pim_Pim2)

编辑:回复您的一些评论

我猜您找不到 CDS 的原因是因为这个(来自RTE 规范,4.2.2,5.4 RTE 数据结构):

[CDS 和实例处理程序] 定义仅适用于在兼容模式下运行的 RTE 生成器——在这种模式下,即使对于那些禁止多次实例化的(目标代码)软件组件,也必须定义实例句柄和组件数据结构。确保兼容性。

还,

[SWS_Rte_03793] 如果软件组件不支持多重实例化,则组件数据实例的名称应为 Rte_Inst_cts ,其中cts是AtomicSwComponentType的组件类型符号。(SRS_Rte_00011)

因此,当 RTE 生成器遵循这种兼容模式时,这些变量必须存在。如果您使用的是特定于供应商的解决方案,那么请尝试使用该供应商名称来标记问题,希望有人可以回答。

在编译时断言

我不会问你为什么要这样做,但恕我直言,我认为这听起来不对,接收缓冲区比要复制的数据更小是否有意义?如果缓冲区小于您的struct. 或者您可以将数组定义为结构并在需要时进行转换(如果您遵循 MISRA 规则,也许您会遇到问题,只需检查一下)。仅供参考,编译时断言可以使用sizeof.

于 2017-05-27T18:38:17.100 回答