文章目录
- 前言
- Postbuild和PreCompile的概念
- MCAL中配置差异
- 总结
前言
之前一直看到MCAL配置中有这个Postbuild和PreCompile的配置,但是不太清楚这两个的区别和使用方法。最近在使用中出现了相关问题,本文介绍一下MCAL中这两种配置的区别和使用。
Postbuild和PreCompile的概念
Postbuild和PreCompile的概念来自于AUTOSAR_RS_ECUConfiguration中的需求,具体描述如下:
顾名思义,PreCompile体现在编译之前,进行一些参数的配置,例如.h中的宏定义,一般以 _cfg.h结尾,示例如下:
Example:
/* File: CanTp_Cfg.h */
/* Pre-compile time configuration */
…
#define CANTP_USE_NORMAL_ADDRESSING STD_OFF
#define CANTP_USE_NORMAL_FIXED_ADDRESSING STD_OFF
#define CANTP_USE_EXTENDED_ADDRESSING STD_ON
…
/* File: CanTp.c */
…
#include "CanTp_Cfg.h"
…
#if (CANTP_USE_NORMAL_ADDRESSING == STD_OFF)
…
#endif
使用这种方法,可以减少源码的改动量,通过修改配置来实现不同的功能的开启和关闭
Postbuild是在编译之后可以修改的配置,一般都是一些const定义,这样的话,只要知道其map中的位置,可以通过修改生成的可执行文件(hex,s19等),来修改对应的配置项,已达到不改代码不编译即可修改配置项。该文件一般以 _PBcfg.h, _PBcfg.c来命名,示例如下:
Example:
/* File: ComM_PBcfg.h */
…
/* Type declaration of the Configuration Type */
struct ComM_ConfigType_Tag {
…
};
…
/* File: ComM_PBcfg.c */
#include <ComM.h>
…
/* post-build time configurable data */
const ComM_ConfigType ComM_Config =
{
…
};
…
/* File: ComM.h */
#include <ComM_PBcfg.h>
…
/* Forward declaration: */
typedef struct ComM_ConfigType_Tag ComM_ConfigType;
extern void ComM_Init(const ComM_ConfigType *
ComMConfigPtr);
…
通过修改ComM_Config内存值即可修改对应的一些配置项。
由于Postbuild是在编译后都可以修改的,所以支持Postbuild一定是可以支持PreCompile的,而支持PreCompile的一些宏定义肯定是不能支持Postbuild的,标准中描述如下:
MCAL中配置差异
在NXP S32K324MCAL中,一般有两个相关选项,一个为Post Build Variant Used ,另一个为Config Variant。
实测第一个勾选与否对生成的代码没有影响,可能主要是为了提示开发者吧。
Config Variant配置有VariantPreCompile和VariantPostBuild。
以CAN模块为例,当配置为VariantPreCompile时,对应的宏CAN_PRECOMPILE_SUPPORT被打开,其主要使能的功能是Can_Init初始化时传递的参数是否为NULL_PTR
#if (CAN_PRECOMPILE_SUPPORT == STD_ON)
#if (CAN_MULTICORE_ENABLED == STD_ON)
if (NULL_PTR != Can_Config[u32CoreId])
{
/* Update config pointer with default configuration if precompile support on. */
Can_apxConfig[u32CoreId] = Can_Config[u32CoreId];
bValidCoreID = TRUE;
}
#else
/* Update config pointer with default configuration if precompile support on. */
Can_apxConfig[u32CoreId] = &Can_Config;
#endif
(void)Config; /* Prevent compiler warning */
#else
#if (CAN_MULTICORE_ENABLED == STD_ON)
if (u32CoreId == Config->Can_u32CoreID)
{
#endif /* (CAN_MULTICORE_ENABLED == STD_ON) */
/* Copy pointer to current Can Driver configuration. */
Can_apxConfig[u32CoreId] = Config;
#if (CAN_MULTICORE_ENABLED == STD_ON)
bValidCoreID = TRUE;
}
#endif /* (CAN_MULTICORE_ENABLED == STD_ON) */
#endif /* (CAN_PRECOMPILE_SUPPORT == STD_ON) */
当VariantPreCompile使能时,直接使用Can_Config作为输入的参数(实际还是来自于Can_PBcfg.c中),在调用Can_Init函数时必须输入参数NULL_PTR,否则会DET报错,代码如下:
#if (CAN_PRECOMPILE_SUPPORT == STD_ON)
if (NULL_PTR != Config)
#else
if (NULL_PTR == Config)
#endif
{
(void)Det_ReportError((uint16)CAN_MODULE_ID, CAN_INSTANCE, CAN_SID_INIT, CAN_E_INIT_FAILED);
}
else
{
而当使用VariantPostBuild时,Can_Init函数的输入作为配置项,默认使用Can_PBcfg.c中的Can_Config
所以,使用VariantPostBuild时,Can_Init初始化需要使用Can_Config,使用VariantPreCompile,Can_Init初始化需要使用NULL_PTR,示例如下:
#if (CAN_PRECOMPILE_SUPPORT == STD_ON)
Can_Init(NULL_PTR);
#else
Can_Init (&Can_Config);
#endif
其他的MCAL模块也是类似的,如果配置和初始化时传的参数不一致,会导致初始化报错(DET报错的API为初始化,错误码为E_INIT_FAILED)而导致模块无法实现正常功能
总结
合理使用Postbuild和PreCompile,可以减少代码的变种,也可以减少代码编译的次数。