Hallo zusammen, ich habe mir für mein LCD eine Menüstruktur aufgebaut, die (Unter-)kategorien, Attribute, Auswahlgruppen (Radiogroups) und Funktionen enthalten kann. Die jeweiligen Typen sind dabei in Structs mit ihren jeweiligen Attributen gekapselt (unten folgt gleich ein Bsp). Um nun diese Typen in beliebiger Reihenfolge auflisten zu können habe ich einen Wrapper (ebenfalls ein Struct) geschrieben, in welchem der Typ angegeben wird, sowie ein Pointer zu dem entsprechenden Eintrag. Das ganze hat bislang auch super funktioniert. Hier mal ein Bsp für solch einen Eintrag: //Struct-Definition zu einem Menü-Attribut struct attr { char name[20]; struct entry *parent; char unit[4]; long int lbound; long int ubound; unsigned long int *value;}; typedef struct attr attrib; // // // attrib at1 = { "Temperatur1", //Name &root, //Parent "\x01\x43", //Einheit 0, //Min-Value 50000, //Max-Value &temperatur1}; //Speicher wrapper wr1 = {ATTRIBUTE,NULL,&at1,NULL,NULL}; // Momentan kämpfe ich jedoch an einem sehr seltsamen Phänomen. Ich habe wie oben beschrieben auch Radiogroups auf diese Weise realisiert, die dann je nach Auswahl Menüeinträge ein- bzw. ausblenden. Demzufolge habe ich in die zugehörige Struct ein zweidimensionales Array aus Pointern auf die zugehörigen Wrapperknoten gelegt: //Struct-Definition zur Radiogroup struct select { char name[20]; struct entry *parent; char selections[20][20]; struct subnode *pWr[20][20]; uint8_t *active;}; typedef struct select selection; Je nach Auswahl (*active) wird dann also die entsprechende "Zeile" dieses 2D-Arrays referenziert und die dort hinterlegten Wrapper werden ausgeblendet. Hier ein Beispiel für solch eine Radiogroup: selection s1 = { "Auswahl1", //Name &root, //Parent {"Aus","T-Gesteuert","Z-Gesteiert"}, //Bezeichner der RGroup {{&wr9},{&wr1,&wr4},{&wr11}}, //Zugehörige Wrapper &selection1}; //Aktuelle Auswahl So viel zu dem Szenario. Jetzt das Problem. Wenn eine oder zwei solche Selections in das Menü mit eingebunden werden funktioniert alles tiptop - nur wenn mann mehrere Einträge dieser Art hinzufügt geht plötzlich gar nichts mehr. Nicht mal mehr die Main() wird aufgerufen? Ich habe nun schon Stunden lang den Code durchgesehen und werde einfach nicht fündig wo der Fehler sein könnte. Das Phänomen tritt nur bei diesen Selections auf. Ich kann also z.B. 4, 5 Attribute hinzufügen ohne Probleme. Da sich die Selection eigentlich nur durch dieses 2D-Array grundlegend von den anderen Eintragstypen unterscheidet wollte ich nun fragen, ob es vielleicht daran liegen könnte? Ich muss dazu gestehen, ich bin noch nicht so lange AVRler. Viele Dank schon mal :-)
Bau mal ein komplettes, minimales Programm und poste dieses. Dann lässt sich leichter nachvollziehen was du da eigentlich gemacht hast. Und im Debugger ausprobieren kann man das dann auch.
Hallo, anbei mal ein kleines Programm zur Veranschaulichung (ps ich arbeite mit einem Mega644 / AVR Studio Service Pack 4 (build 498)). Ich hab in der Datei den Block angegeben, ab welchem der Fehler auftritt: Im Debugger lautet die Meldung wie folgt: AVR Simulator: Invalid opcode 0xffff at address 0x0078f9 AVR Simulator: Uninitialized stack pointer used at 0x0075 Viele Grüße Peter
Du überläufst deinen Stack. Für jedes 'selection' Objekt sind 1224 Bytes fällig. Da sind die 4K, die du im SRAM hast, schnell aufgebraucht. struct select { char name[20]; struct entry *father; char selections[20][20]; struct subnode *pWr[20][20]; uint8_t *active; }; selections 20*20 400 Bytes pwr 20*20*2 800 Bytes ---- 1200 Bytes Du wirst dir da was anderes überlegen müssen.
Hallo Karl-Heinz, vielen Dank für die aufschlussreiche Antwort. Wäre es sinnvoll/denkbar das ganze über PROGMEM zu lösen? Viele Grüße Peter
PROGMEM könnte gehen. Die Frage die ich allerdings stellen würde ist: Wie voll werden denn deine Arrays werden? Sind in den Arrays 90% der Positionen mit anderen Werten als 0 besetzt? Wenn ja: Dann sind 2D Arrays eine vernünftige Lösung. Du musst jetzt nur noch einen Weg finden, die in den AVR zu quetschen. PROGMEM könnte da helfen. Wenn nicht: Durchsuche mal das Web nach 'sparse Arrays'. Es gibt Techniken wie man bei konzeptionellen 2D Arrays die nur 'spärlich besetzt' sind, den nicht benutzten Speicher auf Kosten von mehr Verwaltungsinformation einsparen kann. Ich hab jetzt nicht im Detail durchdacht, was du da vor hast. Da die Arrays aber quadratisch sind: Kann es sein, dass sie um die Diagonale spiegelsymetrisch sind? Dass also selections[i][j] == selections[j][i] Auch in dem Fall könnte man noch ein bischen einsparen. Sowohl in dem Fall als auch bei sparse Arrays kommt man aber um dynamische Speicherallokierung nicht mehr rum.
Hallo, also, ich hab mir jetzt folgendes überlegt: Ich lege ein weiteres Struct mit den Pointern auf die jeweiligen Wrapper sowie die Auswahlbezeichner an, welches komplett im Flash liegt. Das ganze habe ich mal so auscodiert: ########### struct select { char name[20]; struct entry *father; struct invisib *fadeout; //Pointer auf Struct im Flash uint8_t *active;}; typedef struct select selection; struct invisib { char selections[20][20]; //Auswahlbezeichner struct subnode *pWr[20][20];}; //Wrapper die ausgeblendet werden typedef const PROGMEM struct invisib invisible; ########### Ein Menüeintrag einer solchen Auswahl könnte folglich so aussehen: ########### node conf = {"Konfiguration",&root,{}}; wrapper wr1 = {CATEGORY,&conf,NULL,NULL,NULL}; const PROGMEM invisible isel1 = {{"Test1","Test2"},{{&wr1},{}}}; selection sel1 = {"Auswahl",&root,&isel1,&selection1}; wrapper wr2 = {SELECTION,NULL,NULL,NULL,&sel1}; ########### Ich habe jetzt jedoch noch folgendes Problem. Wie lese ich dieses Struct wieder aus dem Flash aus, bzw. greife auf die Indizes der Arrays in diesem Struct zu? Wenn ich das richtig gesehen habe gibt es in <pgmspace.h> keine "pgm_read_block" o.ä. wie es bei eeprom.h der Fall ist. Viele Grüße Peter
> Wenn ich das richtig gesehen habe gibt es in > <pgmspace.h> keine "pgm_read_block" o.ä. wie es bei eeprom.h der Fall > ist. Kann man aber leicht selbst machen.
Hallo, ich hab das ganze jetzt über memcpy_P gelöst. Allerdings funktioniert der Zugriff auf das Pointer-Array nicht. Mit den Strings gehts im Debugger? char flashstring[20]; wrapper* flashwrapper; void getFlash(uint8_t mode, uint8_t i, uint8_t j, invisible *readable) { if (mode == 0) memcpy_P(flashstring, readable->selections[i], sizeof(readable->selections[i])); if (mode == 1) memcpy_P(flashwrapper, readable->pWr[i][j], sizeof(readable->pWr[i][j])); } Außerdem kommt beim Kompilieren noch folgender Warnhinweis: ... initialization discards qualifiers from pointer target type! für die oben stehende Zeile: selection sel1 = {"Auswahl",&root,&isel1,&selection1};
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.