有关使用单独文件在 C 中管理依赖于硬件的配置的建议?

问题描述 投票:0回答:1

我目前正在开发一个嵌入式系统项目,该项目在三种硬件模型上使用相同的 C99 代码库。这些模型之间的主要区别封装在存储传感器映射的常量数组中。下面是一个简化的示例,说明了每个硬件型号的配置:

// Configuration example
#if defined(MODEL_A)
    // Configuration for Model A
    #define PRODUCT_CODE 1
    #define NUMBER_OF_SENSORS 5
    const int temperature_sensor_map[NUMBER_OF_SENSORS] = { 0, 1, 2, 3, 4 };
#elif defined(MODEL_B)
    // Configuration for Model B
    #define PRODUCT_CODE 2
    #define NUMBER_OF_SENSORS 3
    const int temperature_sensor_map[NUMBER_OF_SENSORS] = { 0, 2, 4 };
#define NUMBER_OF_SENSORS 3
#elif defined(MODEL_C)
    // Configuration for Model C
    // ...
#else
    #error Define MODEL_A, MODEL_B, or MODEL_C
#endif

为了改进这些配置的管理并便于跟踪 Git 中的更改,我正在考虑将配置分解为多个文件,每个文件都针对特定的硬件模型进行定制。然而,这种方法需要创建七个文件,这似乎过于复杂:

- config.h (Main configuration header)
- config_model_a.h and config_model_a.c (Configuration for Model A)
- config_model_b.h and config_model_b.c (Configuration for Model B)
- config_model_c.h and config_model_c.c (Configuration for Model C)

下面是代码示例。

注意:如下所示,全局变量的使用不是问题,因为该项目中使用的自定义调试器有一定的限制,只能检查全局变量。

// File config.h
#ifndef CONFIG_H
#define CONFIG_H

#if defined(MODEL_A)
    #include "config_model_a.h"
#elif defined(MODEL_B)
    #include "config_model_b.h"
#elif defined(MODEL_C)
    #include "config_model_c.h"
#else
    #error Define MODEL_A, MODEL_B, or MODEL_C
#endif

extern const int temperature_sensor_map[];

#endif // End of include guard
// File config_model_a.h

#define PRODUCT_CODE 1
#define NUMBER_OF_SENSORS 5
// File config_model_a.c

#if defined(MODEL_A)
    const int temperature_sensor_map[NUMBER_OF_SENSORS] = { 0, 1, 2, 3, 4 };
#endif
// File config_model_b.h

#define PRODUCT_CODE 2
#define NUMBER_OF_SENSORS 3
// File config_model_b.c

#if defined(MODEL_B)
    const int temperature_sensor_map[NUMBER_OF_SENSORS] = { 0, 2, 4 };
#endif

模型 C 的文件遵循类似的模式

但是,我正在探索不依赖构建系统并维护干净、可移植代码的替代方法。具体来说,我对无需多个包含文件或 .c 文件的解决方案感兴趣。

您有不依赖于构建系统的建议吗?

(我不想依赖构建系统,因为我们目前使用 Eclipse CDT,但计划将来过渡到 CMake,并且我希望该解决方案能够在两个系统中工作)

c build configuration embedded
1个回答
0
投票

如果您不想依赖 buid 系统,一种解决方案是在运行时进行配置。 为此,您的软件需要能够识别硬件型号(例如,为每个型号使用不同的分压器)。

这个想法是创建一个接口,供需要读取传感器的软件组件使用。然后,您创建一对 .h/.c 配置文件,在其中提供获取正确传感器的函数。

// sensor_config.h

// Enum with models
typedef enum {
    MODEL_A,
    MODEL_B,
    // ...
} model_t;

// Your interface
typedef struct {
    int (*get_product_code)(void);
    int (*get_number_of_sensors)(void);
    int (*get_sensor_map_at)(int);
} sensor_config_t ;

// Getter
sensor_config_t* get_sensor_config(model_t model);

// other models...

还有 .c 文件

// sensor_config.c

// Model A

#define N_SENSORS_A 5

static int get_product_code_model_a(void);
static int get_number_of_sensors_model_a(void);
static int get_sensor_at_model_a(int sensor_id);

static sensor_config_t sensor_a 
{
    &get_product_code_model_a,
    &get_number_of_sensors_model_a,
    &get_sensor_at_model_a
};

static int get_product_code_model_a(void)
{
    return 1;
}

static int get_number_of_sensors_model_a(void)
{
    return N_SENSORS_A;
}

static int get_sensor_at_model_a(int sensor_id)
{
    static const int mapping[N_SENSORS_A] = {0, 1, 2, 3, 4};
    
    // TODO: check index...

    return mapping[sensor_id];
}

// Model B

#define N_SENSORS_B 3

static int get_product_code_model_b(void);
static int get_number_of_sensors_model_b(void);
static int get_sensor_at_model_b(int sensor_id);

static sensor_t sensor_b 
{
    &get_product_code_model_b,
    &get_number_of_sensors_model_b,
    &get_sensor_at_model_b
};

static int get_product_code_model_b(void)
{
    return 2;
}

static int get_number_of_sensors_model_b(void)
{
    return N_SENSORS_B;
}

static int get_sensor_at_model_b(int sensor_id)
{
    static const int mapping[N_SENSORS_B] = {0, 2, 4};
    
    // TODO: check index...

    return mapping[sensor_id];
}

// other models...

// Getter    
sensor_config_t* get_sensor_config(model_t model)
{
    if (model == MODEL_A)
    {
         return &sensor_a;
    }
    else if (model == MODEL_B)
    {
        return &sensor_b;
    }
    else 
    { 
        // More models...
    } 
    return NULL;
}
        

在配置/读取传感器之前,软件会读取硬件模型并获取正确的传感器。

// main.c

#include "sensor_interface.h"
#include "sensor_config.h"

// Your sensor object
sensor_config_t* my_sensor_config = NULL;

void main(void){
 
    // Assign the right sensor config depending on the model
    model_t hw_model = read_hw_model(); // Read voltage from divider and deduct model    
    my_sensor_config = get_sensor_config(hw_model);
    // TODO : check that my_sensor_config is not NULL...    
        
    while(1)
    {
         // Do something with the sensor config
         int product_code = my_sensor_config->get_product_code();
         int n_sensors  = my_sensor_config->get_number_of_sensors();
         int first_sensor = my_sensor_config->get_sensor_at(0);
         int second_sensor = my_sensor_config->get_sensor_at(1);
         // ...
     }
}
© www.soinside.com 2019 - 2024. All rights reserved.