Что означают два последовательных определения параметров для функции в C? - PullRequest
0 голосов
/ 17 января 2020

Я просматриваю исходный код на работе и продолжаю видеть этот стиль определения функции:

FUNC(Std_ReturnType, SMTN_CODE)SendSignalArray(uint8* NUMPTR, int size) {
}

Что это значит / делает? Спасибо

1 Ответ

2 голосов
/ 18 января 2020

Это из AUTOSAR CompilerAbstraction FUNC(rettype, memclass) определяется обычно в Compiler.h и Compiler_Cfg.h. Иерархия включения:

file.c
    Std_Types.h
        Compiler.h
            Compiler_Cfg.h

Compiler_Cfg.h обычно настраивается в инструменте конфигурирования стека AUTOSAR, а затем генерируется. Некоторые компиляторы / архитектуры все еще могут требовать использования @far и @near для доступа к данным, или некоторые компиляторы, поддерживающие #pragma section ..., в то время как другие компиляторы только __attribute__(( ... )).

Есть другая часть кода, которую вы сделали здесь не упоминается, что происходит от AUTOSAR MemoryMapping:

#define XXX_START_SEC_...
#include "XXX_MemMap.h"

...

#define XXX_STOP_SEC_...
#include "XXX_MemMap.h"

Вот пример использования, рассмотрим модуль XXX:

  1. XXX. c - impl
  2. XXX.h - внешний интерфейс, предоставляемый XXX
  3. XXX_Cfg.h - заголовок конфигурации PRECOMPILE
  4. XXX_LCfg.h - заголовок конфигурации LINKTIME
  5. XXX_LCfg. c - Конфигурация LINKTIME (например, выноски)
  6. XXX_PBCfg.h - Заголовок конфигурации POSTBUILD
  7. XXX_PBCfg. c - Конфигурация POSTBUILD impl
  8. XXX_MemMap.h - Отображение памяти для модуля XXX

Файлы 1 и 2 имеют статический код c, возможно, с дополнительным кодом, заключенным в переключатели компилятора / функций. Остальное обычно генерируется инструментом конфигурации.

XXX.h:

#include "Std_Types.h"
#include "XXX_Cfg.h"
#if (XXX_LCFG_SUPPORT == STD_ON)
#include "XXX_LCfg.h"
#endif
#if (XXX_POSTBUILD_SUPPORT == STD_ON)
#include "XXX_PBCfg.h"
#endif

#define XXX_FOO_DISABLED 0u
#define XXX_FOO_ENABLED  1u

// --- Functions
#define XXX_START_SEC_CODE
#include "XXX_MemMap.h"

FUNC(void, XXX_CODE) XXX_Init(P2CONST(XXX_ConfigType, AUTOMATIC, XXX_CONFIG_DATA) ConfigPtr);
FUNC(Std_ReturnType, XXX_CODE)  XXX_IsDetectionEnabled(void);

#define XXX_STOP_SEC_CODE
#include "XXX_MemMap.h"

XXX_PBCfg.h:

typedef struct {
    VAR(uint8, TYPEDEF) NumChn;
    VAR(uint8, TYPEDEF) FooInitStatus;
    P2CONST(uint8, TYPEDEF, TYPEDEF)  ChannelCfgPtr;
} XXX_ConfigType;

#define XXX_START_SEC_CONFIG_DATA
#include "XXX_MemMap.h"

EXTERN CONST(XXX_ConfigType, XXX_CONFIG_DATA) XXX_Config;

#define XXX_STOP_SEC_CONFIG_DATA
#include "XXX_MemMap.h"

XXX_PBCfg. c:

#include "XXX.h"
#define XXX_START_SEC_CONFIG_DATA
#include "XXX_MemMap.h"

STATIC CONST(uint8, XXX_CONFIG_DATA) XXX_InitVals[] = {
    10,
    20,
    30,
};

EXTERN CONST(XXX_ConfigType, XXX_CONFIG_DATA) XXX_FooInit = {
    sizeof(XXX_InitVals)/sizeof(XXX_InitVals[0]),
    XXX_FOO_ENABLED,
    XXX_InitVals,
};

#define XXX_STOP_SEC_CONFIG_DATA
#include "XXX_MemMap.h"

XXX. c

// --- Variables
#define XXX_START_SEC_VAR_INIT_ASILB_8
#include "XXX_MemMap.h"

VAR(uint8, XXX_DATA) XXX_DetectEnable = 0;
P2CONST(XXX_Config, XXX_DATA, XXX_CONFIG_DATA) XXX_ConfigPtr = NULL_PTR;

#define XXX_STOP_SEC_VAR_ASILB_8
#include "XXX_MemMap.h"

// --- Functions
#define XXX_START_SEC_CODE
#include "XXX_MemMap.h"

FUNC(void, XXX_CODE) XXX_Init(P2CONST(XXX_ConfigType, AUTOMATIC, XXX_CONFIG_DATA) ConfigPtr)
{
    if (ConfigPtr != NULL)
    {
        XXX_ConfigPtr = ConfigPtr;
        XXX_DetectEnable = ConfigPtr->FooInitValue;
    }
}
FUNC(Std_ReturnType, XXX_CODE)  XXX_IsDetectionEnabled(void)
{
    return XXX_DetectEnable;
}

#define XXX_STOP_SEC_CODE
#include "XXX_MemMap.h"

XXX_MemMap.h теперь генерируется в зависимости от конфигурации, например, для компилятора DIAB или TASKING, например:

#if defined(XXX_START_SEC_CODE)
#undef XXX_START_SEC_CODE
#pragma section CODE ".text_ASILB"

#elif defined(XXX_STOP_SEC_CODE)
#undef XXX_STOP_SEC_CODE
#pragma section CODE /* default section e.g. .text */

#elif defined(XXX_START_SEC_VAR_INIT_ASILB_8)
#undef XXX_START_SEC_VAR_INIT_ASILB_8
#pragma section DATA ".bss_asilb" ".data_asilb"

#elif defined(XXX_STOP_SEC_VAR_INIT_ASILB_8)
#undef XXX_STOP_SEC_VAR_INIT_ASILB_8
#pragma section DATA /* default section e.g. .data */

#elif defined(XXX_START_SEC_CONFIG_DATA)
#undef XXX_START_SEC_CONFIG_DATA
#pragma section CONST ".rodata_pbconfig"

#elif defined(XXX_STOP_SEC_CONFIG_DATA)
#undef XXX_STOP_SEC_CONFIG_DATA
#pragma section CONST

#else
    #error "MemClass not defined"
#endif

Compiler_Cfg.h должен настроить FUN C (), VAR (), CONST () следующим образом:

#define FUNC(rettype, memclass)  rettype
#define VAR(t, memclass)  t
#define CONST(t, memclass)  const t

или с компилятором, не понимающим #pragma section, как g cc, использующим __attribute__((section *section-name*)):

#if defined(XXX_START_SEC_CODE)
#undef XXX_START_SEC_CODE
#define XXX_CODE ".text_ASILB"

#elif defined(XXX_STOP_SEC_CODE)
#undef XXX_STOP_SEC_CODE
/* attribute is only on a single entity */

#elif defined(XXX_START_SEC_VAR_INIT_ASILB_8)
#undef XXX_START_SEC_VAR_INIT_ASILB_8
#define XXX_DATA ".data_asilb"

#elif defined(XXX_STOP_SEC_VAR_INIT_ASILB_8)
#undef XXX_STOP_SEC_VAR_INIT_ASILB_8
/* attribute is only on a single entity */

#elif defined(XXX_START_SEC_CONFIG_DATA)
#undef XXX_START_SEC_CONFIG_DATA
#define XXX_CONFIG_DATA ".rodata_pbconfig"

#elif defined(XXX_STOP_SEC_CONFIG_DATA)
#undef XXX_STOP_SEC_CONFIG_DATA
/* attribute is only on a single entity */

#else
    #error "MemClass not defined"
#endif

Следовательно, Compiler_Cfg.h должен определять макросы FUN C () как:

#define FUNC(rettype, memclass)   __attribute__((section memclass)) rettype
#define VAR(t, memclass)          __attribute__((section memclass)) t
#define CONST(t, memclass)        __attribute__((section memclass)) const t

Это может выглядеть странно в коде, но по крайней мере он не загромождает код:

#if __DIAB__
  #pragma section CODE ".text_asilb"
#elif __MSVC__
   /* No Mapping */
#elif __GCC__
   __attribute__((section ".text_asilb"))
#endif
  void XXX_Init(XXX_ConfigType *ConfigPtr)
  {
      ... 
  }

И часть для XXX_START/STOP_SEC_CONFIG_DATA позволяет также собирать и помещать POSTBUILD_LOADABLE данные конфигурации в определенный раздел памяти c (например, FLA * Блок * 1080), который впоследствии можно отдельно заменить инструментом donwload с другими данными без перепрошивки всего приложения. Рассмотрим пример использования шлюза, которому просто нужна новая таблица сетевой маршрутизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...