Mit der memory map habe ich immer wieder Probleme. Jetzt fängt es bei meinem ATmega128 schon wieder an. So bald ich neue Dinge einbaue läuft kaum noch was, obwohl das unabhängig von den vorhandenen Funktionen ist. Ich nehme mal an, da wird wieder was im Speicher überschrieben. Vielleicht könnte mir jemand helfen die Memory map zu verstehen, die erzeugt wird. Hier aus dem map-file: Memory Configuration Name Origin Length Attributes text 0x00000000 0x00020000 xr data 0x00800060 0x0000ffa0 rw !x eeprom 0x00810000 0x00010000 rw !x default 0x00000000 0xffffffff und hier nach dem kompilieren beim Output: Size after: syscontrol.elf : section size addr .data 80 8388864 .text 4782 0 .bss 24 8388944 .noinit 0 8388968 .eeprom 0 8454144 .debug_aranges 220 0 .debug_pubnames 1209 0 .debug_info 4829 0 .debug_abbrev 1916 0 .debug_line 4608 0 .debug_str 1404 0 Total 19072 Der ".data" und ".bss" sollte doch das einzige Problem sein, denke ich mal. Nur sind bis zu den 4K SRAM noch ne Menge Luft nach oben. Wo könnte de Fehler liegen?`
Die Speicherauslastung sieht wirklich so aus, als solltest du da selbst bei exorbitanter Stackbenutzung keine Probleme bekommen. Entweder hast du irgendwo eine endlose Rekursion, oder aber irgendeine Interruptroutine frisst alle Rechenzeit auf und ,,holt sich selbst ein''.
Danke! Also habe ich das oben auch mit den Daten so richtig verstanden. Ich lege auch alle Strings im Flash ab und hole die dann mit den entsprechenden Funktionen raus, um Hauptspeicher zu sparen. Wobei noch 100 Bytes für meine fifo-Buffer (in/out) zur seriellen Schnittstelle weggehen. Die werden mittels malloc() allokiert. Und können natürlich vom Compiler nicht vorausgesagt werden. Aber unterm Strich heißt das, ich muss nochmal genau schauen, wo der Programmfehler liegt. Rechnenzeit it weniger das Problem. Das sind so gravierende Fehler, wie im Terminal würd Datenmüll ausgegeben und falsche Strings usw., da ich mir da ein Kommandozeileninterface gebastelt habe. Das hängt aber eben direkt von der Programmgröße ab. Kürze ich irgendwo völlig unabhängige Funktionen, dann läuft das.
>Ich lege auch alle Strings im Flash ab und hole die dann[..] >Aber unterm Strich heißt das, ich muss nochmal genau schauen, wo >der Programmfehler liegt. Vielleicht machst Du ja einen Fehler in der Verwendung der Program Space Utilities. Poste Doch mal einen Ausschnitt aus Deinem Terminal, in dem ganz sicher falsche Daten gesendet werden.
Hi wenn du die 100 Byte für den FIFO eh immer brauchst wprde ich die an deiner Stelle nicht dynamisch per malloc() besorgen sondern statisch mittels unsigned char fifo_in[100]; Dynamische Speicherverwaltung auf µC sollte man nur da einsetzen wo man die Größe des benötigten Speichers zur Compilezeit nocht nicht kennt. Matthias
>Dynamische Speicherverwaltung auf µC sollte man nur da einsetzen[..]
Ich würde das "auf µC" weglassen. Auf anderen Maschinen macht das
nämlich auch keinen Sinn :-)
Hi ich hab das zuerst auch nicht drin gehabt aber wollte dann irgendwelchen Diskussionen aus dem Weg gehen. Warscheinlich ists wurst wie mans macht. Allen kann man es nicht recht machen. Matthias
Der Code ist vielleicht noch nicht so ganz übersichtlich. Aber ich nehme mal an zum anschauen reicht es. Ist eben noch im "Bastelstadium": Hier wird alles mit der Kommandozeile gemacht: http://mitglied.lycos.de/projectsilence/syscontrol/source/cli.c http://mitglied.lycos.de/projectsilence/syscontrol/source/cli.h Die Steuerung der seriellen Schnittstelle: http://mitglied.lycos.de/projectsilence/syscontrol/source/fifo.c http://mitglied.lycos.de/projectsilence/syscontrol/source/fifo.h http://mitglied.lycos.de/projectsilence/syscontrol/source/serial.c http://mitglied.lycos.de/projectsilence/syscontrol/source/serial.h Und zu guter letzt das eigentliche Hauptprogramm: http://mitglied.lycos.de/projectsilence/syscontrol/source/syscontrol.c
Die dynamische Speicherverwaltung hatte ich im übrigen eingesetzt, damit man die fifo-Größe direkt als Parameter übergeben kann. Sollte ich das unterbinden und das wirklich fix anlegen?
Im übrigen noch ein Nachtrag. Ich bekomme ein paar GCC-Warnungen, die vielleicht mit einspielen. Meiner Meinung nach aber keinen Sinn machen: Compiling: fan.c avr-gcc -c -mmcu=atmega128 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=fan.lst -std=gnu99 fan.c -o fan.o fan.c: In function `fan_set': fan.c:68: warning: comparison is always false due to limited range of data type Geht um die Zeile in "fan_set()": if (value < 0) value = 0; Die Meldung ist Schwachfug, da value vom Typ char ist und somit auch < als 0 sein darf. Compiling: cli.c avr-gcc -c -mmcu=atmega128 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=cli.lst -std=gnu99 cli.c -o cli.o cli.c: In function `cli_docmd': cli.c:113: warning: 'ptr' might be used uninitialized in this function Geht um die Zeile in "cli_docmd()": char *ptr; Ist auch Unsinn, da die Variable in der Funktion initialisiert wird.
>avr-gcc -c -mmcu=atmega128 -I. -g -Os -funsigned-char [..] >fan.c:68: warning: comparison is always false [..] >Die Meldung ist Schwachfug, da value vom Typ char ist [..] Fast richtig ;-) Mit der Option '-funsigned-char' wird eine definition wie 'char cChar;' so behandelt, als würde dort explizit 'unsigned char cChar;' stehen. Also musst Du entweder diese Option aus dem Compileraufruf 'rausnehmen, oder explizit 'signed char cChar;' verwenden.
Hi BTW: Ob char signed oder unsigend ist ist "implementation defined". Darf also bei jedem C-Compiler unterschiedlich sein. Matthias
> cli.c: In function `cli_docmd': > cli.c:113: warning: 'ptr' might be used uninitialized in this function > Geht um die Zeile in "cli_docmd()": char *ptr; > Ist auch Unsinn, da die Variable in der Funktion initialisiert wird. Der Compiler erkennt nicht notwendig jeden möglichen Verarbeitungszweig, in dem eine Initialsierung vorgenommen wird. Wenn es nur rein semantisch sichergestellt ist, dass die Variable vor der Benutzung auch initialisiert ist, dann ist das natürlich trotzdem OK. Aber man sollte die Warnung ernst nehmen und nochmal hingucken. Ich habe es schon oft genug erlebt, dass der Compiler doch Recht hatte. ;-)
@Matthias: Naja wieder was dazugelernt. Dann nehme ich das "-funsigned-char" einfach raus. Oder änderes das in "signed-char". Wenn ich was unsigned haben will, definiere ich mir das selbst. @Jörg: Ja ich bin den Codeschnipsel schon mehrfach durchgegangen. Aber das scheint so schon korrekt zu sein. Entweder lasse ich das so oder setze *ptr einfach auf NULL.
>Dynamische Speicherverwaltung auf µC sollte man nur da einsetzen wo man >die Größe des benötigten Speichers zur Compilezeit nocht nicht kennt. >Ich würde das "auf µC" weglassen. Auf anderen Maschinen macht das >nämlich auch keinen Sinn :-) Das interessiert mich jetzt aber mal. Ich habe in einem Programm welches ich gerade schreibe ein Array mit einer Größe von 256 Byte. Dieses Array wird bei mir nur von einem Unterprogramm+weiterer Unteraufrufe verwendet, andere Unterprogramme sollen die 256 Byte auch als RAM zu Verfügung stehen, was eine globale Variable ausschließt. Ich habe mich dazu entschieden die 256 Byte mit malloc zu reservieren und beim Verlassen des Unterprogramms wieder freizugeben. Nach dem was ihr oben schreibt wäre ein lokales 256 Byte Array aber das "richtige" gewesen. Die 256 Byte müssen nicht initialisiert sein (leerer FIFO). Was wäre nun effizienter/sinnvoller ?
Hi du könntest die 256 Byte beim Eintritt in die Funktion als lokale Variable (also auf dem Stack) anlegen. An deine weiteren Unterfunktionen übergibst du dann, wie bisher ja auch, einen Pointer auf eben diese Variable. Beim verlassen der Unterfunktion wird diese dann automatisch aufgeräumt. Matthias
Ich denke ich habe den Fehler eingegrenzt. Wenn auch ich das Problem nach mehreren Stunden bisher nicht beheben konnte. Der Fehler liegt in den FIFO-Puffern. Da liegt es mit Sicherheit daran, dass der FIFO-Puffer per IRQ gefüllt wird, aber immer wieder so lange gelesen wird, bis ein Byte da ist. Da wird es wohl Konflikte zwischen den einzelnen Funktionen geben. Das der da einen falschen Text anzeigt hat eine andere Ursache, die ich allerdings noch nicht finden konnte. Den Starttext zeigt er ja richtig an, also scheint zumindest der Zugriff auf mit pgmspace funktionieren. Aber vielleicht liegt es ja auch da an den FIFO-Puffern. Die benötige ich ja in beiden Richtungen.
überprüf mal deine fifo.c, wenn während du ein Zeichen versuchst auszulesen ein Zeichen ankommt kann es crashen. Bedenke bitte das Zeiger mindestens 2 Byte lang sind und dadurch bei einem 8 Bit-Bus ZWEI Zugriffe gemacht werden müßen. Wenn jetzt zwischen dem Lesen des ersten Bytes und dem Lesen des 2.Bytes dieser Zeiger geändert wird... Außerdem darfst du eigentlich ja nie (bufread - buffer) > bufsize sein !! anscheinen passiert das aber doch (Siehe Source) Gruss
Mit 16bit Pointern geht das natürlich nicht, jedenfalls nicht ohne um die Pointerzugriffe herum die Interrupts abzuschalten. Was jedoch geht: Pointer durch Index ersetzen. Ok bis effektiver Puffergrösse von 255 Bytes, meist reicht das aber. 8bit incr/decr sind i.d.R. atomar. Epmfehlenswerte Vorlage: Der UART-Code von Peter Fleury. Kommt komplett ohne Abschalten des Interrupts aus.
@TStütz: Genau das ist auch meine Vermutung. Nun will ich den Code nochmal besser überarbeiten, dass der erstens nicht so murksig aussieht und dann kann ich auch eine kleine Loop machen, indem ich da ein Busy-Bit setze. Allzu lang muss ich da ja nicht warten. Das mit dem "(bufread - buffer) > bufsize" kann durchaus sein. Wie gesagt verwende ich einen Ringpuffer und wenn der zu Ende ist, muss ich wieder von vorn anfangen und auf "buffer" zurücksetzen. Das Gleiche passiert bei "bufwrite" genauso. @A.K.: Ja mit indexen habe ich auch überlegt zu arbeiten. Aber da müsste ich mir direkt merken, wo ich im index stehe und wie viele Bytes im puffer stehen. Das Prinzip ist eigentlich auch das gleiche. Der Code von Peter Fleury .. wo kann man da mal schauen?
Hätte ich mir die ganze Arbeit ja sparen können und gleich das Teil von Peter Fleury nehmen können. Naja nun ist egal und ich weiß, was ich getan habe. Ich habe meine Funktionen nochmals überarbeitet. Dennoch habe ich noch nicht so recht Schimmer, wie ich das mit dem IRQs handeln soll. Ich habe zwar inzwischen einen BUSY-Check drin, aber der ist Unsinn. Sobald ein IRQ kommt bleibt das Ganze stehen. Wie kann ich das in der vorhandenen Konstellation denn eigentlich am Besten lösen, da ja die IRQs für eingehende als auch für ausgehende Zeichen ausgelöst werden.
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.