www.mikrocontroller.net

Forum: GCC Initialisierung großer structs mit vielen Nullen


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: flex (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

bei meinem Projekt kommt es auf jedes Byte an. Beim Optimieren habe ich 
festgestellt, dass die Initialisierung von Variablen eigentlich besser 
laufen könnte.
Ich habe z.B. einen großen struct bzw. Array davon (mit Beispielwerten):
typedef union {
  uint8_t Index[5];
  struct {
    uint8_t A, B, C, D, E;
  } Name;
} tFlex;

typedef struct {
  int8_t Alpha, Beta;
  tFlex flex;
} tData;

tData Data[COUNT_DATA] = {
  { 7,  1, {{ 23,  42,   1,   2,   3}}},
  { 2,  4, {{ 47,  11,   0,   0,   7}}},
  {47, 87, {{  0,   8,  15,   0,   0}}},
  { 9, 73, {{  3,   1,   4,   1,   5}}},
  { 5, 10, {{  1,   1,   2,   3,   5}}},
  { 2, 11, {{ 90,  60,  90,   0, 190}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}},
// ...diese "leeren" (man beachte die 1 an Stelle 1)
//   Zeilen wiederholen sich bis zum Ende des Arrays...
}

Dieses Array befindet sich im RAM und im EEPROM. Die o.g. Werte sind der 
Default, für den Fall, dass die Werte im EEPROM ungültig sind oder falls 
man einen Reset der Werte auf den Default braucht.

Mein Gedanke war nun folgender: Da im Default nur einige Zeilen Werte 
enthalten, müsste sich doch durch die Art und Weise des Init eine Menge 
Platz sparen lassen. Kann man irgendwie "in einem Rutsch" einen Struct 
aus dem ROM ins RAM kopieren?

Ich habe es so probiert, aber das frisst auch ziemlich viel Speicher:
Erst die Ganze Geschichte als noinit (im Gegensatz zu oben):
tData Data[COUNT_DATA] __attribute__((section(".noinit")));

Dann die entscheidenden ersten Zeilen ins ROM:
const tData InitData[7] PROGMEM = {
  { 7,  1, {{ 23,  42,   1,   2,   3}}},
  { 2,  4, {{ 47,  11,   0,   0,   7}}},
  {47, 87, {{  0,   8,  15,   0,   0}}},
  { 9, 73, {{  3,   1,   4,   1,   5}}},
  { 5, 10, {{  1,   1,   2,   3,   5}}},
  { 2, 11, {{ 90,  60,  90,   0, 190}}},
  { 1,  0, {{  0,   0,   0,   0,   0}}}
}

Und nun:
void copydata(const tData *source, tData *dest) {
  dest->Alpha = pgm_read_byte(&source->Alpha);
  dest->Beta = pgm_read_byte(&source->Beta);
  uint8_t i;
  for (i = 0; i < 5; i++) dest->Flex.Index[i] = pgm_read_byte(&source->Flex.Index[i]);
}

uint8_t i;
for (i = 0; i < 6; i++) copydata(&InitData[i], &Data[i]);
for (i = 6; i < COUNT_DATA; i++) copydata(&InitData[6], &Data[i]);

Ich empfinde den Zugriff auf jedes Element mit pgm_read_byte als sehr 
umständlich. Geht das nicht irgendwie in einem Rutsch bzw. mit einer 
einzigen Schleife?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Es gibt doch memcpy_P aus avr/pgmspace.h der AVR-LibC. Das spart schon 
mal copydata.

Den Array-Anfang kannst en bloc initialisieren; es sind 6*sizeof(tData) 
Bytes.

Autor: flex (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Danke! Weiß auch nicht, wie mir memcpy_P entgehen konnte. Damit klappt's 
gut und es spart mir jetzt insgesamt im fertigen Programm ca. 250 Bytes, 
was natürlich ein kleiner Jackpot ist.
uint8_t i;
memcpy_P(&Data[0], &InitData[0], COUNT_INITDATA * sizeof(tData));
for (i = COUNT_INITDATA; i < COUNT_DATA; i++) memcpy_P(&Data[i], &InitData[COUNT_INITDATA-1], sizeof(tData));

Vielleicht gibt's ja noch revolutionär andere Ideen zu dem Thema...

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Mit neuen Toolchains geht's auch komplett ohne pgm_read_ und PROGMEM, 
siehe

http://gcc.gnu.org/onlinedocs/gcc/Named-Address-Sp...

Autor: Krapao (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
> 
http://gcc.gnu.org/onlinedocs/gcc/Named-Address-Sp...

IMHO ist dort ein Bug in dem Beispiel (var != i)
     #include <avr/pgmspace.h> /* From avr-libc */
     
     const int var PROGMEM = 1;
               ^^^     
     int read_i (void)
     {
         return (int) pgm_read_word (&i);
                                     ^^
     }

Autor: flex (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hmm, das geht aber erst mit neueren Versionen, oder?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Jo, oder hast du in den alten Versionen was revolutionäres erwartet?

Autor: flex (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hätte ja sein können, dass das auch ein Feature ist, das ich übersehen 
habe. ;)
Aber mal ehrlich, spart das wirklich Platz oder ist das nur eine etwas 
eleganter aussehende Konstruktion? Ich meine, intern kocht der GCC auch 
nur mit Wasser. Und neuere Versionen neigen im Allgemeinen doch eher 
dazu, größeren Code zu erzeugen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net