Как определить размер PIM в пределах AUTOSAR Runnable?

Как определить размер PIM (памяти на экземпляр) в c из Runnable (не просматривая его в сгенерированном RTE и не добавляя значение исправления)?

Ситуация: Runnable Foo имеет доступ к двум PIMs Pim1 и Pim2. В этом примере данные из Pim1 должны быть скопированы в Pim2.

Не только из-за безопасности и защищенности мне нужно проверять размер обоих PIM, чтобы НЕ перезаписывать незаконные области данных. Я знаю, что размер PIM настраивается в описании SW-C (SWCD). Но поскольку SWCD может быть изменен после реализации кода и для того, чтобы сделать код Runnable более универсальным, проверка размера не должна основываться на фиксированных значениях.

Я также рассмотрел проблему size of для массива: как найти size of (указатель на массив)?

Для PIM следующий генератор генерируется RTE-генератором:

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

2 ответа

У меня нет здесь среды AUTOSAR, чтобы проверить это, поэтому, пожалуйста, если вы попробуете что-то из этого, просто дайте мне знать, если это работает. Кроме того, я не эксперт, и довольно долго я не пишу код AUTOSAR, поэтому я, вероятно, что-то упущу. Я также не хочу публиковать какой-либо генератор RTE от какого-либо поставщика, поэтому приведу только стандарт.

использование sizeof(DtImplAry1)

Вы определяете этот тип и даете его в качестве входных данных для генератора RTE, чтобы вы знали имя. Если ваш SWC явно не использует этот тип, генератор RTE не может включить его в ваш .h, но вы можете добавить его вручную к вам SWC arxml. Я думаю, что все инструменты позволяют делать это без необходимости редактировать arxml вручную, просто найдите возможность включить дополнительные типы SWC в ваш инструмент.

Используйте API-интерфейс для доступа к данным SWC

Стандарт определяет переменную типа Rte_CDS_FOO хранить все указатели на PIMs SWC (среди прочего), если вы активируете API (ищите его в своем инструменте). Кроме того, переменная Rte_Inst_FOO должен быть доступен для вас, объявлен как extern в вашем заголовке. Вы могли бы сделать sizeof(*Rte_Inst_FOO->Pim_Pim2),

РЕДАКТИРОВАТЬ: ответить на некоторые из ваших комментариев

Я предполагаю, что причина, по которой вы не находите CDS, заключается в следующем (из спецификации RTE, 4.2.2, 5.4 структур данных RTE):

Определения [CDS and Instance handler] применяются только к генераторам RTE, работающим в режиме совместимости - в этом режиме должны быть определены дескриптор экземпляра и структура данных компонента даже для тех (объектно-кодовых) программных компонентов, для которых множественное создание экземпляров запрещено обеспечить совместимость.

Также,

[SWS_Rte_03793] Если программный компонент не поддерживает множественное создание экземпляров, имя экземпляра данных компонента должно быть Rte_Inst_cts, где cts - символ типа компонента AtomicSwComponentType. (SRS_Rte_00011)

Таким образом, когда RTE-генератор придерживается этого режима совместимости, эти переменные должны быть там. Если вы используете решение для конкретного поставщика, попробуйте пометить вопрос также именем этого поставщика, надеюсь, кто-нибудь ответит.

Утверждать во время компиляции

Я не собираюсь спрашивать, почему вы это делаете, но ИМХО, я думаю, это звучит неправильно, имеет ли смысл для буфера приема быть меньше, чем копируемые данные? Может быть, лучше утверждать во время компиляции, если буфер меньше, чем ваш struct, Или вы можете вместо этого определить свой массив как структуру и привести его к необходимости (если вы следуете правилам MISRA, возможно, у вас возникнут проблемы с ним, просто проверьте). Просто для справки, утверждения времени компиляции можно использоватьsizeof,

У вас есть несколько проблем: a) ваш sizeof(*pim1) возвращает 6 из-за заполнения, потому что вы начинаете с uint8, вторая - с uint16, и я думаю, что третий ist также uint16.

Вот почему вы должны скорее отсортировать их по размеру шрифта / выравниванию.. по возрастанию

uint32
uint16
uint8

Несмотря на то, что элементы могут быть не упорядочены больше, но это также уменьшает разрывы в памяти, создаваемые компоновщиком.

б) pim2 является массивом, вы не можете получить массив len/size из указателя. Но у вас должно быть Rte-определение DtImplAry1.

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]);
Другие вопросы по тегам