Это из 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:
- XXX. c - impl
- XXX.h - внешний интерфейс, предоставляемый XXX
- XXX_Cfg.h - заголовок конфигурации PRECOMPILE
- XXX_LCfg.h - заголовок конфигурации LINKTIME
- XXX_LCfg. c - Конфигурация LINKTIME (например, выноски)
- XXX_PBCfg.h - Заголовок конфигурации POSTBUILD
- XXX_PBCfg. c - Конфигурация POSTBUILD impl
- 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 с другими данными без перепрошивки всего приложения. Рассмотрим пример использования шлюза, которому просто нужна новая таблица сетевой маршрутизации.