Guten Abend
Ich habe hier folgenden Aufbau:
Atmega324 @ 10MHz an dem sich ein ENC28J60 befindet.
Auf dem Mega ist Timer0 im CTC Mode konfiguriert mit einem Teiler von 64
und einem anschliessenden TopValue von 7
Dessen Interrupt wird für 3Phasen Software PWM genutzt.
Nun zum Problem:
1. Szenario, ich lasse den PWM Laufen, habe den ENC initialisiert,
lese jedoch nie den Buffer aus.
-> Die Hardware läuft einwandfrei mehrere Stunden.
2. Szenario: Ich lasse den PWM Laufen lese in meiner main() while()
schleife den Buffer aus, wenn der Controller halt grad Zeit hat :)
-> PROBLEM! Nach bisher nicht definierbaren Zeitabständen stürzt der
gesamte Controller ab. Der Code wird nicht mehr ausgeführt. (oder
zumindest geschieht nichts an den IO's. ob der intern noch was am
rechnen ist, weiss ich nicht.)
Interessanter weise, funktionieren auch Hardwarefunktionen wie der
Timer0 Interrupt nicht mehr.
Da dachte ich sogleich, dass sich da der Interrupt in die Quere kommt.
Also
3. Szenario: Interrupt des Timers deaktivieren. und den ENC in der
main() while() schleife auslesen.
-> Erneut das selbe Problem wie bei Szenario 2.
Ich habe mich als erstes auf die Suche nach while schleifen gemacht,
welche eventuell nicht beendet werden beim auslesen.
Habe leider keine gefunden. Zumal ein ewiges While nicht erklären würde,
weshalb auch der Interrupt des PWM's unterbrochen wird.
Der Besagte Codeteil sieht so aus:
Mommentan verwerfe ich den eingelesene Buffer, da es ja auch ohne
anschliessende Verarbeitung nicht funktioniert.
Zur info, im buffer steht das korrekte.
Ich kann auch mehrere hundert Pakete erfolgreich übertragen bis der
controller abstürtzt.
Ehrlich gesagt, weiss ich nicht, welche Informationen ich euch hier zur
verfügung stellen soll.
Deshalb hoffe ich, das mir hier jemand tipps gibt, oder ihr sagt was ihr
noch wissen müsst, damit wird den Fehler eingränzen können.
Danke schonmal
Claudio Hediger schrieb:> Ehrlich gesagt, weiss ich nicht, welche Informationen ich euch hier zur> verfügung stellen soll.
Kommentierten Quellcode...
Vermutung: der Controller stürzt ins Nirvana wegen Stack-Überlauf oder
Überschreitung von Array-Grenzen. Alternativ könnte natürlich auch die
Hardware schuld sein. Der ENC braucht etwas viel Strom. Wenn auf deiner
Platine ein 7805, LM317 oder ähnliches die Spannung für den ENC regelt,
dann schau mal, wie heiß der Regler wird. Hat der ein vernünftiges
Kühlblech?
Bekommt der ENC irgendwelche (sinnvollen) IP-Paktet vorgesetzt?
Claudio Hediger schrieb:> Der Besagte Codeteil sieht so aus:
Das ist kein Code. Das ist nur eine Ansammlung von unbekannten
Funktionen und unbekannten Variablen, die nirgends definiert werden.
Damit kann keiner was anfangen.
Code ist etwas, was man ohne Warnungen und Errors compilieren kann.
Wenn man dazu zusätzliche Libs oder Header braucht, dann häng sie an
(als Zip).
Wir haben keine Lust, Rätsel zu raten, wie was definiert sein könnte.
Peter
Peter Dannegger schrieb:> Wir haben keine Lust, Rätsel zu raten, wie was definiert sein könnte.
Verstehe ich voll und ganz.
Anbei nun also ein zip mit den entsprechenden C-Files und headern.
Es handelt sich dabei um den Gesamten Stack sowie dem kommunikations
code (spi) und meiner main()
Hoffe jemand hat eine idee...
Danke euch schonmal.
Bernhard Spitzer schrieb:> cli();> LED_ACT_1;> //_delay_ms(50);> LED_ACT_0;>> while((enc28j60Read(EIR) & EIR_PKTIF))> {> //uart_puts("Weiteres Paket vorhanden!\n");> process_packet(enc28j60PacketReceive(ETH_buffer_SIZE, ETH_buffer));> }>> sei();Dass bei dem Programm "seltsamerweise" keine Timer-Interrupts mehr> durchkommen, liegt vermutlich schwer daran, dass Du sie mit cli()> deaktivierst...
Ja da hast du recht, das aktuelle Programm welches ich als Zip angehängt
habe, hat das cli und sei nicht mehr drin...
Ich habe inzwischen einiges herausgefunden.
1.
Ich habe diese CodeZeilen:
// (we reduce the MAC-reported length by 4 to remove the CRC)
18
len=MIN(len,maxlen);
19
20
// copy the packet from the receive buffer
21
enc28j60ReadBuffer(len,packet);
22
23
}
Zuvor wurde das Paket ungeachtet dessen Grösse ausgelesen und in den
256Byte grossen Buffer geladen.
Dies verursachte ziemlich sicher einen Speicherüberlauf.
Durch die hinzugefügte IF abfrage wird dies verhindert.
Ich hoffe damit läuft mein Code stabiler.
Des weiteren,
habe ich beim bearbeiten des paketes nicht darauf geachtet, ob dieses
überhaupt vorhanden ist also size > 0
da die paket ausleseroutine ein return 0 im fehlerfall hat.
Nun scheint es vorerst mal zu funktionieren..
ich weiss, meine rechtschreibung lässt zu wünschen übrig, aber die
informationen welche ich euch übermitteln wollte, sind dennoch vorhanden
;)
Was meldet denn der Compiler, wieviel RAM insgesamt genutzt wird?
In main() nutzt du (eventuell, weil gerade auskommentiert) die Funktion
printinbuffer(*buffer,*text, terminate). Die macht keinerlei Prüfungen
der Bereichsgrenzen und Du rufst die so auf:
1
//printinbuffer(&buffer[UDP_DATA],"Hallo, dies ist ein Test des AVR Boardes :) Es laeuft alles perfekt hehehe",TERMINATE);
UDP_DATA ist definiert als 42 (!!), du ballerst hier über 60 Zeichen
sinnloses gequassel rein und überschreibst dir das RAM.
Davon abgesehen ist mir der Sinn von TERMINATE bei der Funktion unklar.
Du kopierst einen (hoffentlich) NULL-Terminierten Text in ein anderes
Array und lässt dabei evtl. mit TERMINATE=0 das Null-Zeichen am Ende
weg. Mit dem Ergebnis in buffer[] wieder in die Funktion und Du hast
eine Endlosschleife... Wenn der Speicher vorher Null-Terminiert war,
dann sollte er das nach dem "memcopy" auch sein.
Bernhard Spitzer schrieb:> Was meldet denn der Compiler, wieviel RAM insgesamt genutzt wird?>> In main() nutzt du (eventuell, weil gerade auskommentiert) die Funktion> printinbuffer(*buffer,*text, terminate). Die macht keinerlei Prüfungen> der Bereichsgrenzen und Du rufst die so
auf://printinbuffer(&buffer[UDP_DATA],"Hallo, dies ist ein Test des AVR Boardes :)
Es laeuft alles perfekt hehehe",TERMINATE);UDP_DATA ist definiert als 42 (!!), du
ballerst hier über 60 Zeichen
> sinnloses gequassel rein und überschreibst dir das RAM.>> Davon abgesehen ist mir der Sinn von TERMINATE bei der Funktion unklar.> Du kopierst einen (hoffentlich) NULL-Terminierten Text in ein anderes> Array und lässt dabei evtl. mit TERMINATE=0 das Null-Zeichen am Ende> weg. Mit dem Ergebnis in buffer[] wieder in die Funktion und Du hast> eine Endlosschleife... Wenn der Speicher vorher Null-Terminiert war,> dann sollte er das nach dem "memcopy" auch sein.
Es wird 20% (400 Bytes) Ram genutzt
Diese Funktion nutze ich tatsächlich nicht mehr. Diese war für Versuche.
Aber du hast recht.
Hier die besagte memcpy funktion:
Momentan habe ich das problem mit dem ENC offensichtlich gelöst.
Nun gibt es ein Problem mit der PWM Erzeugung
Hier mein RGB Code im Interrupt:
1
unsignedintuiPWMCounter;
2
volatileunsignedintuiPWMRed;
3
volatileunsignedintuiPWMGreen;
4
volatileunsignedintuiPWMBlue;
5
6
ISR(TIMER0_COMPA_vect)
7
{
8
if(uiPWMCounter==0)
9
{
10
11
uiPWMCounter=PWM_MAX_VALUE;
12
RGB_R_0;
13
RGB_G_0;
14
RGB_B_0;
15
}
16
17
if(uiPWMCounter==uiPWMRed)RGB_R_1;
18
if(uiPWMCounter==uiPWMGreen)RGB_G_1;
19
if(uiPWMCounter==uiPWMBlue)RGB_B_1;
20
21
uiPWMCounter--;
22
23
}
Ich weiss ich weiss, der Code ist nicht performance optimal.
Aber darum gehts jetzt nicht :)
Also wie gesagt, versagt jetzt die PWM-Erzeugung nach ca 1minute oder
mehr.
Der Variable für blau, wird zu beginn der main() Funktion einmalig ein
Wert zugewiesen. Dieser Wert ändert sich danach nirgendwo mehr im
Programm.
Die anderen beiden Werte werden Dynamisch aktualisiert.
Es erlischen jedoch alle 3 Farben.
Man kann danach jedoch die Variablen erneut setzen und dadurch den PWM
wieder generieren lassen.
Es scheint so, als ob die Variablen entweder grösser 300 sind, da dies
der Maximal Wert ist, oder aber 0.
Da der blau-Wert jedoch nie verändert wird, erscheint mir dies etwas
mysteriös.
Claudio Hediger schrieb:> Es scheint so, als ob die Variablen entweder grösser 300 sind, da dies> der Maximal Wert ist, oder aber 0.
Die Variable ist definitiv grösser 300
Doch die frage ist, weshalb diese auf einmal hochgezählt wird.
Es scheint fast so, als ob irgendwas den Speicherbereich überschreiben
würde.
Ich finde dieses Phänomen sehr merkwürdig und mommentan nicht erklärbar.
Ich habe auch schon alle stellen, wo die PWM Variablen gesetzt werden
(ausser zu beginn in der main() für die Startwerte) auskommentiert.
Und dennoch werden alle 3 Werte (nacheinander! deutlich sichtbar) nach
einer nicht definierbaren Zeit auf einen wert grösser 300 gesetzt.
Gleiches Problem. Irgend eine Funktion überschreibt eifrig fremden
Speicherplatz. Und wenn dann uiPWMRed, uiPWMGreen und uiPWMBlue genullt
werden, wird es zappenduster.
Pass halt auf mit Arrays und seltsamen Konstantendefinitionen. Ein
fehlerfreies Programm ist nicht, wenn es meistens oder für eine lange
Zeit korrekt läuft.