Как определить размер 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]);