嵌入式结构的描述格式

时间:2010-03-15 16:00:41

标签: embedded

我有一个C结构,允许用户在嵌入式系统中配置选项。目前,我们使用的GUI是针对此配置结构的每个不同版本自定义编写的。我想要的是能够以某种格式描述可由客户端配置应用程序读取的结构成员,使其在我们所有系统中都是通用的。

我已尝试用XML描述结构并让客户端读取文件;这在大多数情况下都有效,除了某些字段具有相互依赖性的情况。所以我使用的格式需要有一种方法来指定这些;例如,成员A必须始终小于或等于成员B的一半。

提前感谢您的想法和建议。

修改

在阅读完第一个回复后,我意识到我的问题确实有点过于模糊,所以这是另一个尝试:

嵌入式系统需要以C结构的形式访问数据,在处理器上运行任何其他语言都不是一种选择。基本上,我只需要一种用结构定义元数据的方法,这些元数据将与固件一起下载到闪存上。然后,客户端配置实用程序将通过RS-232,CAN等读取元数据文件,并填充用户可以用来编辑选项的窗口(树视图)。

我提到的XML文件正是这样做的,它包含结构成员名称,数据类型,元素数量等。XML文件中成员的位置隐式定义了它在C结构中的位置。该文件驻留在闪存上,由配置程序读取;缺少的唯一方法是定义结构字段之间的依赖关系。

使用MATLAB / Simulink自动生成代码,因此我可以访问脚本语言来帮助创建结构。例如,如果我最终使用XML,则结构将仅以XML格式定义,并且我将使用脚本在代码生成期间创建C结构。

希望这更清楚。

3 个答案:

答案 0 :(得分:1)

对于与其他字段没有关系或关系的简单情况,可以在结构中添加两个字段:“other”字段编号和指向比较两者的函数的指针。然后,您需要创建比较两个值的函数,并根据是否满足关系返回true或false。好吧,猜测你需要创建两个测试关系和关系倒数的函数(即如果字段1需要大于字段2,那么字段2需要小于或等于字段1)。如果您需要对范围设置多个限制,则可以存储指向功能/字段对列表的指针。

另一种方法是为每个字段创建验证函数,并在字段更改时调用它。显然,这个功能可能很复杂,但可能需要更多的手动编码。

理论上,您可以根据您描述的XML描述为上述任一技术生成验证函数。

答案 1 :(得分:0)

我希望你现在能得到一些答案,但让我看看我能做些什么。

你的问题有点模糊,但听起来你想要一个

  • 代码生成
  • 嵌入式扩展语言
  • 手动编码的运行时迷你语言

代码生成

您说当前每次更改配置代码时都会使用工具。我愿意打赌这是一个高度重复的任务,所以你没有理由不能编写程序来为你做这件事。您的生成器应该使用某些特定于域的语言并发出随后构建到您的应用程序中的c代码和头文件。我在这里谈论的一个例子是GNU gengetopt。将xml用于输入语言的想法没有错。

优点:

  • 生成的代码可以快速而紧凑
  • 不需要在目标平台上运行解释器

缺点:

  • 你必须写发电机
  • 更改内容需要重新编译

扩展语言

Tcl,python和其他语言与c代码配合使用效果很好,并且允许您使用动态语言指定配置行为,而不是使用c输入和字符串以及和... ...

优点:

  • 动态语言可能意味着配置代码更简单
  • 更改配置选项而不重新编译

缺点:

  • 您需要在目标平台上运行动态语言

迷你语言

您可以编写自己的嵌入式迷你语言。

优点:

  • 无需重新编译
  • 因为你写它会在目标上运行

缺点:

  • 你必须自己写

答案 2 :(得分:0)

结构从版本变为多少版本?当我做这种事情时,我将其硬编码到PC应用程序中,然后计算出固件版本中数据包的含义 - 但是唯一的变化通常是每隔几个月添加一个额外的字段。

如果我想沿着元数据路线走下去,我想我会使用类似下面的内容。

typedef struct
{
    unsigned char field1;
    unsigned short field2;
    unsigned char a_string[4];
} data;

typedef struct
{
    unsigned char name[16];
    unsigned char type;
    unsigned char min;
    unsigned char max;
} field_info;

field_info fields[3];

void init_meta(void)
{
    strcpy(fields[0].name, "field1");
    fields[0].type = TYPE_UCHAR;
    fields[0].min = 1;
    fields[0].max = 250;

    strcpy(fields[1].name, "field2");
    fields[1].type = TYPE_USHORT;
    fields[1].min = 0;
    fields[1].max = 0xffff;

    strcpy(fields[2].name, "a_string");
    fields[2].type = TYPE_STRING;
    fields[2].min = 0 // n/a
    fields[2].max = 0 // n/a
}

void send_meta(void)
{
    rs232_packet packet;

    memcpy(packet.payload, fields, sizeof(fields));

    packet.length = sizeof(fields);

    send_packet(packet);
}