Forum: Mikrocontroller und Digitale Elektronik Möglicherweise rjmp-Grenze überschritten?


von Stefan L. (avlbger)


Lesenswert?

Hallo,

Leider bin ich heute auf ein für mich nicht so ganz erklärbares und 
deshalb auch nicht behebbares Problem gestossen.

Ich programmiere gerade ein etwas umfangreicheres Programm in C auf 
einem Atmega16. Es hat derzeit ca. 1000 Bytes.

Heute habe ich lediglich zwei Funktionen hinzugefügt welche ein paar 
Variablen per utoa über die hardwareuart ausgeben. Seit ich diese 
Funktionen eingefügt habe, funktioniert aber die softuart-schnittstelle 
welche gps-daten empfängt nicht mehr richtig.

Ich konnte aber inzwischen durch probieren ausschließen dass es mit den 
Funktionen selbst zu tun hat, es liegt an der Codelänge. Sobald ich eine 
bestimmte Anzahl an Codezeilen in einer der Funktionen (vermutlich auch 
in anderen.. das habe ich jetzt aber nicht getestet) hinzufüge, tritt 
das Problem auf. (es kommt kein korrekter Text mehr an..)

Ich bin Anfänger und kann leider noch nicht auf viele Erfahrungswerte 
zurückgreifen, ich meine mich aber zu erinnern dass es bei den 
Sprungmarken etc. gewisse Grenzen gab.. wie aber kann ich das 
kontrollieren ob das bei mir das Problem ist? Dieses Problem ist derzeit 
das einzige mir bekannte was zu meinem Phänomen irgendwie passt..

Vielleicht kann mir jemand einen Tipp geben, auf was ich hier achten 
muss oder was sonst noch die Ursache für ein solches komisches Verhalten 
ist?

Vielen Dank im vorraus,
avlbger

von H.Joachim S. (crazyhorse)


Lesenswert?

Brauchst dich nicht drum kümmern (falls nicht der Compiler buggy ist). 
Solche primitiven Fehler macht aber kein Compiler. Ausserdem geht rjmp 
bis 2kB.
Das Problem liegt mit ziemlicher Sicherheit an deinem Programm.

von Stefan L. (avlbger)


Lesenswert?

Hmm ok.. danke.. hab ja erstmal auch mein Programm vermutet da ich 
derzeit sicher noch Fehleranfälliger bin als alles andere drum herum :)

Das Ganze ist aber sehr strange.. es geht um folgende 2 Funktionen:
1
void submit_runtime_vars()
2
{
3
  huart_puts("\r\n#VAR@");
4
  utoa(pwm_g_startval,tbuff,10);
5
  huart_puts(tbuff);
6
  huart_putc(',');
7
  utoa(manual_override,tbuff,10);
8
  huart_puts(tbuff);
9
  huart_puts("\r\n");
10
}
11
12
void submit_countjob_status()
13
{
14
  huart_puts("\r\n#CNT@");
15
  utoa(cj1_d1,tbuff,10);
16
  huart_puts(tbuff);
17
  huart_putc(',');
18
  utoa(cj1_d2,tbuff,10);
19
  huart_puts(tbuff);
20
  huart_putc(',');
21
  utoa(cj1_d3,tbuff,10);
22
  huart_puts(tbuff);
23
  huart_putc(',');
24
  utoa(cj2_d1,tbuff,10);
25
  huart_puts(tbuff);
26
  huart_putc(',');
27
  utoa(cj2_d2,tbuff,10);
28
  huart_puts(tbuff);
29
  huart_putc(',');
30
  utoa(cj2_d3,tbuff,10);
31
  huart_puts(tbuff);
32
  huart_putc(',');
33
  utoa(cj_active,10);
34
  huart_puts(tbuff);
35
  huart_puts("\r\n");
36
}

Die beiden Funktionen funktionieren auch wie gewünscht, nur funktioniert 
die SoftUART eben nicht mehr richtig wenn beide so wie hier gezeigt 
eingebaut sind. Kommentiere ich die Befehle in den Funktionen aus, 
gehts, kommentiere ich nur die Befehle einer Funktion aus und zwar egal 
welcher, gehts auch. Kommtentiere ich ein paar Zeilen, ebenfalls egal 
welche, aus, funktionierts ebenfalls.. es funktioniert NUR NICHT wenn 
ich die beiden Funktionen komplett drin habe..

Das gibt doch keinen Sinn, oder?? Und in den Funktionen passiert ja auch 
ncihts was die SoftUART beeinflussen sollte.. ich checks nicht :(

Ahja.. hab mich vorhin vertan.. mein Programm ist nicht 1000 sondern 
10000 Bytes lang..

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Was heißt den "geht nicht"... so wie ich das sehen nutzt du in den 
Funktionen eine ganze Menge globaler Variablen-->vieles das schief gehen 
kann ;)

von (prx) A. K. (prx)


Lesenswert?

Stefan L. schrieb:

> Das gibt doch keinen Sinn, oder?? Und in den Funktionen passiert ja auch
> ncihts was die SoftUART beeinflussen sollte.. ich checks nicht :(

Werden diese Funktionen wohlmöglich in einem Interrupt aufgerufen??

SoftUART => zeitkritische Interrupts.
Viel Aktivität in anderen Interrupts => Zeitfehler in SoftUART.

von Stefan L. (avlbger)


Lesenswert?

Guten Morgen zusammen :)

Die einzige globale Variable die in den Funktionen überschrieben wird, 
ist tbuff und die wird definiv nicht zeitgleich woanders verwendet und 
schon gar nicht von der Softuart.

Die Funktionen werden auch in einem Interrupt ausgeführt -> weiß dass 
das Zeitkritisch ist und so evtl. stören könnte.. ABER :) Es ist ja so 
dass diese Funktionen überhaupt gar nicht ausgeführt werden! Die werden 
nur aufgerufen wenn ich über die HardwareUART ein bestimmtes Kommando 
sende, was ich aber momentan nicht mache... Alleine die Tatsache dass 
die Funktionen "da" sind, stört offenbar die SoftUART und das ist was 
ich nicht verstehe und weshalb ich zum Schluss gekommen bin dass es 
irgendwie mit der Codelänge zu tun haben muss.

Compiler ist avr-gcc, der sollte mich da warnen falls irgendwelche 
Sprungmarken zu "weit" entfernt sind?

Neuer Tag neues Glück.. ich werd jetzt mal weiterprobieren und komme der 
Sache hoffentlich noch auf die Schliche.. echt sehr eigenartig :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stefan L. schrieb:
> Compiler ist avr-gcc, der sollte mich da warnen falls irgendwelche
> Sprungmarken zu "weit" entfernt sind?
In C kümmerst du dich nicht um Sprungmarken. Und der Compiler kann das 
ausreichend gut. Du hast ein anderes Problem.

> Alleine die Tatsache dass
> die Funktionen "da" sind, stört offenbar die SoftUART und das ist was
> ich nicht verstehe und weshalb ich zum Schluss gekommen bin dass es
> irgendwie mit der Codelänge zu tun haben muss.
Nein.
Es ist ganz einfach: du hast einen amoklaufenden Pointer.
Kurz: irgendein Array wird über das Arrayende hinaus beschrieben. 
Strings werden gern für solche Fehler verwendet...
Es könnte auch ganz einfach der Stack überlaufen (das ist auch wieder 
ein amoklaufender (Stack-)Pointer)...

von Stefan L. (avlbger)


Lesenswert?

Hmm.. OK, bin dahingehend eh schon am probieren. Die SoftUART empfängt 
ja Zeichen vom GPS und schreibt die in einen Puffer welcher dann am 
Schluss ein GPS-Datensatz enthalten sollte und der wird dann über die 
HardwareUART ausgegeben. Möglicherweise läuft da beim befüllen des 
Puffers was schief, (sehr gut möglich da ich leider noch nicht alles was 
ich mir da aus anderen Codeschnipseln zusammengebastelt habe 100% 
verstehe)

Aber was mir einfach überhaupt nicht einleuchten will ist, WARUM zum 
Henker hat das bisher tadellos funktioniert und nur weil ich ein paar 
Zeilen Code an komplett anderer Stelle, die derzeit ncoh nicht mal 
aufgerufen werden, hinzugefügt habe, läuft das Ganze Amok :D

Das zweite, der möglicherweise überlaufende Stackpointer, wie kann ich 
denn das überprüfen ob es daran liegt?

Vielen Dank :)

von Stefan E. (sternst)


Lesenswert?

Stefan L. schrieb:
> Aber was mir einfach überhaupt nicht einleuchten will ist, WARUM zum
> Henker hat das bisher tadellos funktioniert und nur weil ich ein paar
> Zeilen Code an komplett anderer Stelle, die derzeit ncoh nicht mal
> aufgerufen werden, hinzugefügt habe, läuft das Ganze Amok :D

Z.B. darum, weil du wegen dieser Code-Zeilen (auch ohne dass sie 
aufgerufen werden) mehr RAM verbrauchst (wegen der Strings). Lass die 
Strings einfach mal weg (huart_puts(0);), und schaue, was dann passiert.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Stefan L. schrieb:
> Die einzige globale Variable die in den Funktionen überschrieben wird,
> ist tbuff und die wird definiv nicht zeitgleich woanders verwendet und
> schon gar nicht von der Softuart.

Wenn das so ist dann mach sie Funktionslokal oder Funktionsstatisch!
Ein Blick auf den Speichervervrauch wäre auch nicht verkehrt.

von Christian W. (chrisw84)


Lesenswert?

Zum Bleistift könnte es daran liegen, dass dein tBuff zu "klein" ist.

In der Doku zu der Funktion utoa findet man:
"The size of buffer must be at least (8 * sizeof(int) + 1) bytes when 
converting values in base 2. That makes the size 17 bytes on 16-bit 
machines, and 33 bytes on 32-bit machines."

Viele Grüße

von Stefan L. (avlbger)


Lesenswert?

Hallo Leute!

Vielen Dank für eure Hilfe, ich habs nun :)

Tatsächlich hatte ich den SRAM wohl ausgereizt :)
Die Strings warens... Bin nun meinen ganzen Code durchgegangen und habe 
ein wenig optimiert so dass der Compiler noch besser optimieren konnte.

Zb: solche Zeilen:
1
huart_puts("XYZ\r\n");

durch
1
huart_puts("XYZ");
2
huart_puts("\r\n");

ersetzt. Auch den Puffer für die GPS Datensätze habe ich etwas reduziert 
und somit einige Bytes gespart. Nun funzt alles wieder wie gewünscht :)

Zum Glück ist das Programm nun so gut wie fertig und ich hoffe ich muss 
nichts großes mehr hinzufügen sonst hab ich ein SRAM Problem.. mein Code 
hat aber sicher noch mehr Optimierungspotential.

Vielen Dank nochmal für eure Tipps die mir auf die richtige Spur 
geholfen haben!

avlbger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Du könntest die Konstanten Strings auch in den Flash oder EEPROM 
auslagern dann gibt es auch keine Probleme mit dem SRAM.

von Stefan L. (avlbger)


Lesenswert?

Ja, hab ich mir auch schon überlegt, aber ich wollte alles erstmal so 
einfach wie möglich machen.. was in dem Fall wohl kurz nach hinten 
losgegangen ist ;)

Wie ich was im Flash speichere und zur Laufzeit auslese muss ich mir 
erstnoch aneignen, das würde ja auch von der Geschwindigkeit her gehen, 
EEPROM ist ja relativ langsam und dann könnte ich mir wieder Probleme 
aufreissen wenn ich evtl. sogar noch in einer INterrupt-Routine einen 
String ausgeben will der im EEPROM gespeichert ist.(oder betrifft die 
langsame Geschwindigkeit nur den Schreibvorgang beim EEPROM?)

Das EEPROM verwende ich bisher dafür dass ich diverse Einstellungen die 
nach Stromausfall oder Reset wieder verfügbar sein sollen, speichere und 
diese bei Programmstart dann auslese.

Viele Grüße,
avlbger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Stefan L. schrieb:
> oder betrifft die langsame Geschwindigkeit
> nur den Schreibvorgang beim EEPROM
Das Datenblatt kann dir sicher mehr verraten ;)
Lesen dauert nicht sooo Lange, ich würde mich jedoch erstmal um das 
auslagern in den Flash bemühen, da stehen die Texte nämlich schon drinn 
und werden nur nochmal ins SRAM kopiert...

--> 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vereinfachung_f.C3.BCr_Zeichenketten_.28Strings.29_im_Flash

von Stefan L. (avlbger)


Lesenswert?

Für heut mach ich erstmal Schluss :) Danke für den Link, ja das Tutorial 
ist echt hilfreich.. wäre nie so weit gekommen ohne das Ding.

Aber alles ist halt noch nicht hängengeblieben :) aber ich Arbeite dran 
:)

Schönen Sonntag noch,
avlbger

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
Noch kein Account? Hier anmelden.