tags:

views:

67

answers:

3

Hi, 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.

A: 

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
dmckee
A: 

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);
}
James
James,That's almost identical to what I did with XML to describe the metadata. The embedded code does not need access to the metadata so IMO it's easier to do it in XML or something similar because its easier to describe nested structures etc. than with C.Anyway, in either case, the problem I end up at is specifying inter-dependence between fields. From the responses so far it seems as though to have a truly generic solution to this problem I'd have to come up with some technique to identify structure fields and write a parser for some simple arithmetic checks.
Praetorian
+1  A: 

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.

jamesv