嵌入式结构的描述格式

发布于 2024-08-25 09:02:18 字数 719 浏览 4 评论 0原文

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

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

预先感谢您的想法和建议。

编辑:

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

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

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

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

希望这更清楚。

I have a C structure that allow users to configure options in an embedded system. Currently the GUI we use for this is custom written for every different version of this configuration structure. What I'd like for is to be able to describe the structure members in some format that can be read by the client configuration application, making it universal across all of our systems.

I've experimented with describing the structure in XML and having the client read the file; this works in most cases except those where some of the fields have inter-dependencies. So the format that I use needs to have a way to specify these; for instance, member A must always be less than or equal to half of member B.

Thanks in advance for your thoughts and suggestions.

EDIT:

After reading the first reply I realized that my question is indeed a little too vague, so here's another attempt:

The embedded system needs to have access to the data as a C struct, running any other language on the processor is not an option. Basically, all I need is a way to define metadata with the structure, this metadata will be downloaded onto flash along with firmware. The client configuration utility will then read the metadata file over RS-232, CAN etc. and populate a window (a tree-view) that the user can then use to edit options.

The XML file that I mentioned tinkering with was doing exactly that, it contained the structure member name, data type, number of elements etc. The location of the member within the XML file implicitly defined its position in the C struct. This file resides on flash and is read by the configuration program; the only thing lacking is a way to define dependencies between structure fields.

The code is generated automatically using MATLAB / Simulink so I do have access to a scripting language to help with the structure creation. For example, if I do end up using XML the structure will only be defined in the XML format and I'll use a script to create the C structure during code generation.

Hope this is clearer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

剩余の解释 2024-09-01 09:02:18

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

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

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

For the simple case where there is either no relationship or a relationship with a single other field, you could add two fields to the structure: the "other" field number and a pointer to a function that compares the two. Then you'd need to create functions that compared two values and return true or false depending upon whether or not the relationship is met. Well, guess you'd need to create two functions that tested the relationship and the inverse of the relationship (i.e. if field 1 needs to be greater than field 2, then field 2 needs to be less than or equal to field 1). If you need to place more than one restriction on the range, you can store a pointer to a list of function/field pairs.

An alternative is to create a validation function for every field and call it when the field is changed. Obviously this function could be as complex as you wanted but might require more hand coding.

In theory you could generate the validation functions for either of the above techniques from the XML description that you described.

梦一生花开无言 2024-09-01 09:02:18

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

您的问题有点模糊,但听起来您想要以下之一:

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

代码生成

您说,每次更改此配置代码时,您当前都在手动处理配置代码。我敢打赌,这是一项高度重复的任务,因此您没有理由不能编写程序来为您完成它。您的生成器应该使用一些特定于域的语言并发出 C 代码和头文件,您随后将它们构建到应用程序中。我在这里讨论的一个例子是 GNU gengetopt。使用 xml 作为输入语言的想法没有任何问题。

优点:

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

缺点:

  • 你必须编写生成器,
  • 更改内容需要重新编译

扩展语言

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

优点:

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

缺点:

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

迷你语言

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

优点:

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

缺点:

  • 你必须自己写

I would have expected you to get some answers by now, but let me see what I can do.

Your question is a bit vague, but it sounds like you want one of

  • Code generation
  • An embedded extension language
  • A hand coded run-time mini language

Code Generation

You say that you are currently hand tooling the configuration code each time you change this. I'm willing to bet that this is a highly repetitive task, so there is no reason that you can't write program to do it for you. Your generator should consume some domain specific language and emit c code and header files which you subsequently build into you application. An example of what I'm talking about here would be GNU gengetopt. There is nothing wrong with the idea of using xml for the input language.

Advantages:

  • the resulting code can be both fast and compact
  • there is no need for an interpreter running on the target platform

Disadvantages:

  • you have to write the generator
  • changing things requires a recompile

Extension Language

Tcl, python and other languages work well in conjunction with c code, and will allow you to specify the configuration behavior in a dynamic language rather than mucking around with c typing and strings and and and...

Advantages:

  • dynamic language probably means the configuration code is simpler
  • change configuration options without recompiling

Disadvantages:

  • you need the dynamic language running on the target platform

Mini language

You could write your own embedded mini-language.

Advantages:

  • No need to recompile
  • Because you write it it will run on your target

Disadvantages:

  • You have to write it yourself
尽揽少女心 2024-09-01 09:02:18

不同版本的结构有多少变化?当我做这种事情时,我将其硬编码到 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);
}

How much does the struct change from version to version? When I did this kind of thing I hardcoded it into the PC app, which then worked out what the packet meant from the firmware version - but the only changes were usually an extra field added onto the end every couple of months.

I suppose I would use something like the following if I wanted to go down the metadata route.

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文