Hallo Leute, ich rufe eine Funktion in zwei unterschiedlichen Funktionen auf. In dem einen Fall verhält sich die Funktion wie erwartet, in dem anderen Fall nicht. Das äußert sich in undefinierten Verhalten des Programms einschließlich Reset. ... ziemlich ratlos ... Malte --- file.h --- void LiPoOptions(struct sMenu* pMenu); void func2(void); --- use1.c --- main(){ printf("%p", &LiPoOptions); // --> 0x3694 LiPoOptions(); // geht func2(); } func2(){ printf("%p", &LiPoOptions); // --> 0x3694 LiPoOptions(); // geht nicht (s.u.) .... bla bla ... } void LiPoOptions() { lcd_clr(); // geht LCDSoftChar('a', 0, 0); // geht printf("\nOptions\n"); // geht nicht }
Malte wrote: > void LiPoOptions(struct sMenu* pMenu); > > main(){ > printf("%p", &LiPoOptions); // --> 0x3694 > LiPoOptions(); // geht Wundert mich, dass das geht. Es fehlt doch das Funktionsargument aus dem Funktionsprototypen.
Bitte poste dein wirkliches Programm und nicht ein extra für dieses Forum zurechtgestricktes Beispiel. Zu deinem Problem gibt es 100-erte Möglichkeiten was da schief gelaufen sein kann. Da brauchen wir nicht auch noch Fehler die du beim Tippen in diesem Forum eingefügt hast. Wenn du denkst, dass dein Programm zu lang ist, dann specke es ab. Stell aber sicher, dass der Fehler noch im Programm ist. Aber: Auf keinen Fall, auf gar keinen Fall solltest du ein Programm hier eintippen sondern immer den tatsächlichen Quelltext veröffentlichen. Entweder indem du die Dateien anhängst, oder indem du mittels Cut&Paste den Code einstellst.
Die erste Vermutung dabei wäre übrigens ein Stacküberlauf.
Erst mal sorry, ich wollte euch nicht mit dem gesamtem Code belästigen. Habe den Beitrag dann beim Testen gestern mehrfach überarbeitet und offenbar Fehler eingebaut... Das mit dem Stacküberlauf kam mir dann auch heute Nacht. Ich habe eben mal den freien Speicher bestimmt. Dieser liegt zunächst bei 438 Byte. Was mir dabei auffällt ist das der Funtktionsaufruf (jeweile) eine Menge Stack verbraucht. Soviel das dabei (sehr wahrscheinlich) ein Stack overflow auftritt. Der Stackverbrauch für den Funktionsaufruf ( Funktion s.u. ) liegt so bei 65 Byte wobei mir die Quelle dafür unklar ist. (Die Funktion ist etwas gestripped und enhält normalerweise mehrere Menuelemente. Jedes scheint auf dem Stack zu landen - d.h. der Speicherverbrauch ist im Regelfall höher) Verwendet habe ich folgende Methode um den freien Speicher zu bestimmen. http://www.roboternetz.de/wissen/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Dynamischer_RAM-Verbrauch Codeschnipsel (kopiert) typedef struct { enum eElementType ElementType; } tElement; typedef struct sMenu { int v; int numEl; tElement** el; } tMenu; typedef struct { enum eElementType ElementType; char text[LCD_DISP_LENGTH]; float v; float min; float max; float gran; } tFloatParameter; void LiPoOptions (void) { uint8_t mmEntries = 0; tElement* MenuElements[MAX_OPT_MENU_ENTRIES]; tFloatParameter DisChgCellVlim = {FLOAT_PARAM, "Entl. Sp. %4.1f V", 2.5, 4.2, 3.0}; MenuElements[mmEntries++] = (tElement*)&DisChgCellVlim; tMenu Menu = {0, mmEntries, MenuElements}; sub_menu(&Menu); }
Huch da ist noch ein Fehler tFloatParameter DisChgCellVlim = {FLOAT_PARAM, "Entl. Sp. %4.1f V", 2.5, 4.2, 3.0}; muss heißen: tFloatParameter DisChgCellVlim = {FLOAT_PARAM, "Entl. Sp. %4.1f V",3.0, 2.5, 4.2, 0.1};
> 65 Byte wobei mir die Quelle dafür unklar ist Wie gross ist LCD_DISP_LENGTH und wieviele Texte hast du so in etwa pro Funktion. Stack Overflow könnte sein. Als erstes würde ich mal die Texte komplett aus dem SRAM verbannen und im Flash belassen. Das sollte dann schon einiges an SRAM zurückbringen. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vereinfachung_f.C3.BCr_Zeichenketten_.28Strings.29_im_Flash Deine Struktur sieht dann so aus
1 | typedef struct { |
2 | enum eElementType ElementType; |
3 | const char* text; |
4 | float v; |
5 | float min; |
6 | float max; |
7 | float gran; |
8 | } tFloatParameter; |
9 | |
10 | char DisChgCellVlimTxt[] PROGMEM = "Entl. Sp. %4.1fV"; |
11 | tFloatParameter DisChgCellVlim = {FLOAT_PARAM, DisChgCellVlimTxt, 3.0, 2.5, 4.2, 0.1}; |
Beim Zugriff auf den Text dann die pgm_readxxxx bzw. (der Text sieht mir danach aus, als ob er direkt für printf benutzt wird) printf_p benutzen. printf_p erwartet den Formatstring im Flash.
LCD_DISP_LENGTH ist 21 sizeof(tFloatParameter) ist 39. Mir ist klar das ich mit dem SRAM sehr "großzügig" umgehe und das es bessere Methoden gibt hier solche Daten zu speichern. Nicht klar ist mir warum die Struktur DisChgCellVlim auf dem Stack zu landen scheint. Die Funktion hat normalerweise 3 Menuelemente und verbraucht dann 147 bytes auf dem Stack. Das ganze geht in dem Programm bis 10 Menuelemente. Das sind dann >390byte auf dem Stack. Dazu kommt das es Untermenus gibt, sich das ganze also addiert. Warum?
Noch ein Nachtrag: Mache ich die struktur tFloatParameter DisChgCellVlim global dann schrumpft der Stack um eine zu erwartende Grösse. Die Section .data wird um 38 Byte grösser. Könnte also passen. Das würde, mein Verständniss vorausgesetzt, bedeuten das das struct DisChgCellVlim wirklich im Stack liegt. Klingt fast wie die Verwendung von __builtin_alloca Ich habe mir das Assemblerlisting angesehen, bin aber da zu wenig bewandert um das wirklich zu verstehen. Gruß Malte
Noch ein Nachtrag, dann geh ich ins Bett: so siehts im Assemblerlisting aus, wenn mich nicht alles täuscht wird da Platz vom Stack abgezogen und dann für das Struct verwendet. Also Platz im SRAM schaffen. Naja morgen gehts weiter. 150 /* prologue: frame size=71 */ 151 0000 CF93 push r28 152 0002 DF93 push r29 153 0004 CDB7 in r28,__SP_L__ 154 0006 DEB7 in r29,__SP_H__ 155 0008 C754 subi r28,lo8(71) 156 000a D040 sbci r29,hi8(71) 157 000c 0FB6 in _tmp_reg_,__SREG__ 158 000e F894 cli 159 0010 DEBF out _SP_H_,r29 160 0012 0FBE out _SREG_,__tmp_reg__ 161 0014 CDBF out _SP_L_,r28 162 /* prologue end (size=11) */ 20:xtc_src/BattOptions.c **** uint8_t mmEntries = 0; 163 .stabn 68,0,20,.LM1-.LFBB1 164 .LM1: 165 0016 1B82 std Y+3,__zero_reg__ 21:xtc_src/BattOptions.c **** 22:xtc_src/BattOptions.c **** tElement* MenuElements[MAX_OPT_MENU_ENTRIES]; 23:xtc_src/BattOptions.c **** 24:xtc_src/BattOptions.c **** tBatteryOptions* pBatteryOptions = Battery[LI37].pBatteryOptions; 166 .stabn 68,0,24,.LM2-.LFBB1 167 .LM2: 168 0018 8091 0000 lds r24,Battery+32 169 001c 9091 0000 lds r25,(Battery+32)+1 170 0020 9A83 std Y+2,r25 171 0022 8983 std Y+1,r24 25:xtc_src/BattOptions.c **** 26:xtc_src/BattOptions.c **** 27:xtc_src/BattOptions.c **** tFloatParameter DisChgCellVlim = {FLOAT_PARAM, "Entl. Sp. %4.1f V", pBatteryOptions->DisChgC 172 .stabn 68,0,27,.LM3-.LFBB1 173 .LM3: 174 0024 E981 ldd r30,Y+1 175 0026 FA81 ldd r31,Y+2 176 0028 8081 ld r24,Z 177 002a 9181 ldd r25,Z+1 178 002c A281 ldd r26,Z+2 179 002e B381 ldd r27,Z+3 180 0030 2396 adiw r28,63-60 181 0032 8CAF std Y+60,r24 182 0034 9DAF std Y+61,r25 183 0036 AEAF std Y+62,r26 184 0038 BFAF std Y+63,r27 185 003a 2397 sbiw r28,63-60 186 003c 87E2 ldi r24,lo8(39) 187 003e FE01 movw r30,r28 188 0040 7296 adiw r30,18 189 0042 DF01 movw r26,r30 190 0044 982F mov r25,r24 191 0046 1D92 st X+,__zero_reg__ 192 0048 9A95 dec r25 193 004a 01F4 brne .-6 194 004c 82E0 ldi r24,lo8(2) 195 004e 90E0 ldi r25,hi8(2) 196 0050 9B8B std Y+19,r25 197 0052 8A8B std Y+18,r24 ... 337 /* epilogue: frame size=71 */ 338 015a C95B subi r28,lo8(-71) 339 015c DF4F sbci r29,hi8(-71) 340 015e 0FB6 in _tmp_reg_,__SREG__ 341 0160 F894 cli 342 0162 DEBF out _SP_H_,r29 343 0164 0FBE out _SREG_,__tmp_reg__ 344 0166 CDBF out _SP_L_,r28 345 0168 DF91 pop r29 346 016a CF91 pop r28 347 016c 0895 ret 348 /* epilogue end (size=10) */
> Erst mal sorry, ich wollte euch nicht mit dem gesamtem Code belästigen. Das ist ja im Prinzip eine gute Idee, aber man sollte nie als Teil der Fehlerbeschreibung Code angeben, der nur für das Posting neu eingetippt wurde. Der enthält erfahrungsgemäß oft nicht den Fehler, um den es geht, dafür aber jede Menge andere Fehler. Also immer Code posten, den du auch tatsächlich mal so durch den Compiler hast laufen lassen. > Nicht klar ist mir warum die Struktur DisChgCellVlim auf dem Stack zu > landen scheint. Lokale Variablen werden eben (so sie zu groß für Register sind) im Stack angelegt. Wo hättest du sie erwartet?
Eigentlich ist es auch egal, ob die Variablen auf dem Stack oder sonstwo im SRAM landen - es gibt nur ein SRAM, und ob das nun von oben nach unten, oder von unten nach oben überläuft, ändert am Ergebnis nichts. Oliver
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.