C - struct inklusive CRC - Padding-Bytes

OP #7357096
Lesenswert?

Guten Morgen, wie würdet ihr folgendes Problem sauber in c lösen? Ich habe eine Konfigurationsstruktur die im FLASH gespeichert werden soll; sowohl beim Programmieren als auch im Betrieb. Ich möchte zur Sicherheit noch eine CRC hinzufügen. Das Problem ist, dass die Berechnung der CRC ohne den Speicherbereich für die CRC durchführen will/muss. Der erste Ansatz mit

1
typedef struct
2
{
3
  uint8_t param_1;
4
  uint16_t param_2;
5
  uint8_t param_3[9];
6
  uint16_t crc;
7
} conf_t
8
conf_t config;
9
get_default_config(&config);
10
uint8_t crc_size = sizeof(config) - sizeof(config.crc);
11
config.crc = calc_crc(&config, crc_size);

scheiterte, da auch am Ende Padding-Bytes eingefügt wurden. Die zweite Lösung empfinde ich als unsauber, funktioniert aber erstmal.

1
uint8_t crc_size = (uint8_t)(&(config.crc)) - (uint8_t)&config;

aktuell habe ich die Idee, die Struktur so aufzubauen:

1
typedef struct
2
{
3
  uint8_t param_1;
4
  uint16_t param_2;
5
  uint8_t param_3[9];
6
} conf_t;
7
typedef struct
8
{
9
  config_t conf;
10
  uint16_t crc;
11
} conf_rcr_t;

Habt ihr eine bessere und vor allem sauberere Lösung?

Simon

#7357100
Lesenswert?

1
typedef struct
2
{
3
  uint8_t param_1;
4
  uint16_t param_2;
5
  uint8_t param_3[9];
6
  uint16_t crc;
7
} conf_t;
8

9
printf("%d\n", sizeof(conf_t)); //16

Etwas nachdenken beim anordnen der Parameter:

1
typedef struct
2
{
3
  uint16_t param_2;
4
  uint8_t param_3[9];
5
  uint8_t param_1;
6
  uint16_t crc;
7
} conf_t;
8

9
printf("%d\n", sizeof(conf_t)); //14

Alternativ:

1
typedef struct __attribute__((packed))
2
{
3
  uint8_t param_1;
4
  uint16_t param_2;
5
  uint8_t param_3[9];
6
  uint16_t crc;
7
} conf_t;
8
printf("%d\n", sizeof(conf_t)); //14

Simon G. schrieb:

Das Problem ist, dass die Berechnung der CRC ohne den Speicherbereich für die CRC durchführen will/muss.

Wieso das? Rechne doch über die komplette struct (mit CRC) und vergleiche mit 0x0000/0xFFFF (je nach final)

Simon G. schrieb:

aktuell habe ich die Idee, die Struktur so aufzubauen:

Und was macht das besser?

1
printf("%d\n", sizeof(conf_rcr_t)); //16

Dann kannst du auch gleich mit offsetof(CRC) arbeiten.

OP #7357105
Lesenswert?

N. M. schrieb:

Etwas nachdenken beim anordnen der Parameter:

1
> typedef struct __attribute__((packed))
2
>

Moin und vielen Dank, stimmt, packed wäre auch noch eine gute alternative.

Wieso das? Rechne doch über die komplette struct (mit CRC) und vergleiche mit 0x0000/0xFFFF (je nach final)

Das verstehe ich leider noch nicht ganz. Ich möchte ja die gespeicherte Konfiguration mit der gespeicherten CRC überprüfen, um Fehler beim Speichern oder Lesen zu erkennen.

N. M. schrieb:

Und was macht das besser?printf("%d\n", sizeof(conf_rcr_t)); //16

Dann kannst du auch gleich mit offsetof(CRC) arbeiten.

Perfekt, das gefällt mir und war irgendwie nicht auf meinem Schirm.

#7357107
Lesenswert?

Christopher B. schrieb:

Edit: da war mani schneller :-)

Ja, ich hab noch editiert und offsetof hinzugefügt.

Simon G. schrieb:

Das verstehe ich leider noch nicht ganz. Ich möchte ja die gespeicherte Konfiguration mit der gespeicherten CRC überprüfen, um Fehler beim Speichern oder Lesen zu erkennen.

Na du hast doch irgendwann Daten die du speichern möchtest. Zu den Daten berechnest du die CRC und speicherst diese konsistent mit den Daten im Flash. Irgendwann liest du die Daten wieder aus und willst sie validieren. Wenn du nun über die komplette struct (mit CRC) die CRC rechnest muss doch 0 rauskommen.

#7357111
Lesenswert?

Simon G. schrieb:

da hätte ich dann

conf_crc_t conf;

uint_t crc_size = sizeof(conf.conf);

genommen.

conf_t ist doch das Problem. Genauer gesagt weil du auf das erste uint8_t versuchst ein uin16_t zu platzieren. Aufgrund der ungeraden Adresse macht der Compiler das aber nicht und fügt ein padding Byte ein. Später beim Übergang vom Array auf uint16_t das gleiche nochmal. Also musst du doch das Vermeiden. Das bekommst du mit der gezeigten Variante ja aber nicht hin. Also hast du wieder 2 Byte zu viel...

OP #7357113
Lesenswert?

N. M. schrieb:

Also musst du doch das Vermeiden. Das bekommst du mit der gezeigten Variante ja aber nicht hin. Also hast du wieder 2 Byte zu viel...

Die Padding-Bytes sind nicht unbedingt das Problem, da sie ja bei der CRC Berechnung berücksichtigt werden. Nur die Padding-Bytes am Ende der Struktur zusammen mit meiner fehlerhaften Berechnung des Offsets führten dazu, dass die CRC in die CRC Berechnung einfloss und damit eine andere CRC berechnet wurde als abgespeichert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren