Hallo,
ich hab ein Programm für den Arduino geschrieben, welches ich jetzt noch
einmal in "normalem" C schreiben will.
Im Grunde gibt es nur eine Codestelle, die nicht funktionieren will, der
folgende Code ist vom Arduino und funktioniert tadellos:
1
voidEineFunktion()
2
{
3
unsignedcharbuf[512];
4
mmc_read_sector(0,buf);
5
}
(Zum Auslesen der SD Karte wir diese Library verwendet:
http://www.mikrocontroller.net/articles/AVR_FAT32)
Wenn ich diesen Code jetzt in C kompiliere, kompiliert dies wunderbar,
nur leider hängt sich das Programm dann beim Aufruf der Funktion
1
mmc_read_sector(0,buf);
auf.
Wenn ich nun hingegen statt
1
unsignedcharbuf[512];
1
unsignedchar*buf;
verwende, läuft das Programm, hängt sich dann aber bei einer späteren
Leseoperation auf. Ansonsten läuft das Programm ordentlich durch, nur
wenn es zum Auslesen und Speichern in einem Array kommt, geht nichts
mehr.
Vielen herzlichen Dank im Voraus und einen schönen Sonntag noch.
> Wenn ich nun hingegen statt>> unsigned char buf[512];>> unsigned char* buf;>> verwende, läuft das Programm, hängt sich dann aber bei einer späteren> Leseoperation auf.
Logisch, weil du im 2. Fall mit buf einen nicht initialisierten Zeiger
hast. Der GCC sollte dafür auch eine Warnung gebracht haben. Die
Schreiboperation in mmc_read_sector(0,buf) zerschreibt im
Speicherbereich ab buf halt was...
Vielen Dank für die Antwort.
Aber es funktioniert ja zwei mal, wenn ich
1
unsignedchar*buf;
verwende, ich springe dann aus der Funktion raus (dann müsste der
Speicher ja wieder freigegeben werden) und versuche dann das gleiche
nochmal zu tun und ab diesem Punkt geschieht dann nichts mehr.
Gehe ich richtig in der Annahme, dass ich den Zeiger richtig mit
1
unsignedchar*buf={0};
initialisiere? Wenn ja, dass hab ich auch schon versucht.
Grüße und Danke
Benni K. schrieb:> Vielen Dank für die Antwort.>> Aber es funktioniert ja zwei mal,
Nein.
Es funktioniert garantiert nicht. Es mag für dich so aussehen als ob,
aber das tut es nicht.
> wenn ich>
1
unsignedchar*buf;
verwende, ich springe dann aus der Funktion
> raus (dann müsste der Speicher ja wieder freigegeben werden
Es wurde überhaupt kein Speicher reserviert!
Deine Empfangsroutine schreibt irgendwo in den Speicher und zerschiesst
dir alles. Was genau hängt von den Details ab. Da das aber sowieso
falsch ist, ist es auch unsinnig dem jetzt nachzugehen. Mach es richtig
und du hast das Problem in erster Linie erst gar nicht.
> Gehe ich richtig in der Annahme, dass ich den Zeiger richtig mit>
1
unsignedchar*buf={0};
> initialisiere? Wenn ja, dass hab ich auch schon versucht.
Es geht nicht um den Zeiger.
Du hast in erster Linie keine SPeicherfläche, in die die Daten
geschrieben werden könnten! Egal ob du dann noch einen Zeiger darauf
einrichtest oder nicht.
Das hier
1
voidEineFunktion()
2
{
3
unsignedcharbuf[512];
4
mmc_read_sector(0,buf);
5
}
ist dir richtige Variante. Mit buf hast du dir eine Speicherfläche
erzeugt und die Funktion mmc_read_sector kann da reinschreiben. Wenn man
jetzt rausfinden will, warum mmc_read_sector bei dir abkratzt, muss man
sich diese Funktion näher ansehen, ob die zb irgendwelche Vorbedingungen
benötigt.
Unter Umständen liegt das Problem noch nicht mal in dieser Funktion,
sondern ganz woanders. Was du siehst sind die Symptome. Die müssen aber
nicht unbedingt offensichtlich mit den Ursachen korrelieren.
> unsigned char* buf = {0};
Definiert den Zeiger buf und initialisiert ihn mit der Adresse eines
Speicherbereichs in dem für 1 Byte Platz ist. Der Speicherbereich selbsr
wird mit dem Wert 0 initialisiert.
Wenn mmc_read_sector in einen 512 Bytes großen Speicherbereich schreiben
will, musst du den auch angelegt haben. Wenn du ihn zur Laufzeit lokal
anlegst, d.h. auf dem Stack, dann siehst du ggf. auch erst zur Laufzeit
Probleme.
Leg den Buffer testweise global an und achte darauf, ob der BSS/DATA
Bereich im RAM noch ausreichend ist.
Krapao schrieb:>> unsigned char* buf = {0};>> Definiert den Zeiger buf und initialisiert ihn mit der Adresse eines> Speicherbereichs in dem für 1 Byte Platz ist. Der Speicherbereich selbsr> wird mit dem Wert 0 initialisiert.
Äh. nein.
Karl Heinz Buchegger schrieb:> Nein.> Es funktioniert garantiert nicht. Es mag für dich so aussehen als ob,> aber das tut es nicht.
Ich kann mit dem Ergebnis arbeiten und bekomme alle Werte aufs Bit genau
ausgelesen, ich dachte mir aber schon, dass das der falsche Weg ist.
Nur im Unterschied zu der vollständigen Reservierung des Feldes
funktioniert diese oben genannte erst Methode mit dem Zeiger.
Wie kann es überhaupt sein, dass ein mit dem Arduino Kompilierter Code
funktioniert und exakt derselbe Code, den ich von Hand durch den avr-gcc
jage nicht?
Vielen Dank schonmal für die Hilfe.
> Wie kann es überhaupt sein, dass ein mit dem Arduino Kompilierter Code> funktioniert und exakt derselbe Code, den ich von Hand durch den avr-gcc> jage nicht?
Von welchem Arduino sprechen wir eigentlich? Wieviel RAM hat der?
Roland H. schrieb:> Von welchem Arduino sprechen wir eigentlich? Wieviel RAM hat der?
Arduino Uno, Atmega328p, also 2kByte SRAM.
Auf den gleichen Chip lade ich dann auch mein Programm mit dem ISP. Der
Speicher sollte also locker ausreichen.
Benni K. schrieb:> Wie kann es überhaupt sein, dass ein mit dem Arduino Kompilierter Code> funktioniert und exakt derselbe Code, den ich von Hand durch den avr-gcc> jage nicht?
Dann wird er nicht genau 100% identisch sein.
>> Wie kann es überhaupt sein, dass ein mit dem Arduino Kompilierter Code>> funktioniert und exakt derselbe Code, den ich von Hand durch den avr-gcc>> jage nicht?
Es wäre an der Zeit, beide Quelltexte + Makefile etc. komplett zu
zeigen.
Ich bin auch mal gespannt, wie "gleich" die Quelltexte wirklich sind :-)
Der Code wird mit dem folgenden Optionen erstellt (codeblocks):
Für den Compiler:
-mmcu=atmega328p -Wall -g
Für den Linker:
-mmcu=atmega328p
-Wl,-Map=$(TARGET_OUTPUT_FILE).map,--cref
Danach wird folgendes ausgeführt:
avr-size $(TARGET_OUTPUT_FILE)
avr-objcopy -O ihex -R .eeprom -R .eesafe $(TARGET_OUTPUT_FILE)
$(TARGET_OUTPUT_FILE).hex
avr-objcopy --no-change-warnings -j .eeprom --change-section-lma
.eeprom=0 -O ihex $(TARGET_OUTPUT_FILE) $(TARGET_OUTPUT_FILE).eep.hex
avr-objdump -h -S $(TARGET_OUTPUT_FILE) > $(TARGET_OUTPUT_FILE).lss
Vielen Dank für das Interesse und die bisherige Diskussion.
Vielleicht nochmal kurz die Funktion mmc_read_sector():
Deklariere mal den Puffer buf[512] als globale Variable, d.h. so:
1
unsignedcharbuf[512];
2
3
voidTestLesen()
4
{
5
mmc_read_sector(0,buf);
Meckert er dann über freien Speicher? Dann hattest Du einen Stack
Überlauf. AFAIK kennt der GCC keine Overlays für Daten. Da muss man dann
vorsichtig sein beim Reservieren von Speicher.
Meine Glaskugel ist gerade beim TÜV. Also sehe ich die main() Funktion
des C-Programmes unscharf, ebenso kann ich uputhex nicht erkennen. F_CPU
liegt im Dunkeln, ob uinit() auch 115k einstellt, ...
Mit "komplett" meine ich "komplett" :-)
Aaahh ... ich habe eine Vision ... ohne Kugel ... ein zip Attachment,
mit allem drin ... auspacken, make, ...
Hallo, danke für die Antworten,
uputhex kann ich auch genauso gut weglassen, die Funktion wurde noch nie
aufgerufen =), es hängt ein 16MHZ Quarz dranne und es wird eine
Symbolrate von 9600 Baud verwendet.
Ich werde versuchen morgen eine Archiv hochzuladen, muss nur erstmal ein
makefile erstellen.
Grüße