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
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.
> 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.