Hallo zusammen,
Ich glaube,ich muss mal wieder auf eure Fachkompetenz zurückgreifen.
Ich habe auf einem ATMega328P ein größeres Projekt, in dem ich auch die
Linsin Bibliothek von Johann L. (gjlayde) nutze
(http://www.mikrocontroller.net/articles/AVR_Arithmetik/Sinus_und_Cosinus_%28Lineare_Interpolation%29).
Außerdem nutze ich ein LCD Display, das über I2C angesprochen wird,
dafür habe ich die GLCDL-AVR Bibliothek von Christophe Lorenz
(https://sites.google.com/site/donutscience/programming-hacks/graphic-lcd-library-for-avr-barton-and-other).
Die GLCDL Bibliothek nutzt ASCII Tabellen, die im Flash abgelegt werden
für die String Ausgabe auf dem LCD. Die Linsin Bibliothek nutzt Lookup
Tables, die ebenfalls im Flash abgelegt werden, um die
Stütztstelleninterpolation zu rechnen.
Mein Problem ist, sobald ich die Linsin Bib einbinde, bekomme ich
anstatt der Buchstaben auf dem LCD nur zufällig verteilt aussehende
Pixelbereiche (keinerlei Buchstaben erkennbar), die widerum aber immer
konstant sind, d.h. es sind nicht zufällige Muster, sondern konstant
erzeugte Muster. Grafische Elemente, wie Kreise und Rechtecke, können
mit und ohne Linsin Bib immer einwandfrei angezeigt werden.
Entferne ich die Linsin Bib wieder, funktioniert die String Darstellung
auf dem LCD einwandfrei.
Ich vermute daher, dass es ein Problem mit den Daten im Flash gibt.
Allerdings reicht über das Speichern und Lesen, wie es bspw. hier
beschrieben ist
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38003&start=all&postdays=0&postorder=asc)
mein Wissen nicht hinaus. Atmel Studio sagt zur Speicherbelegung
folgendes nach dem Kompilieren:
1
Program Memory Usage : 18546 bytes 56.6 % Full
2
Data Memory Usage : 901 bytes 44.0 % Full
Ich hoffe, ihr habt noch einen Tipp für mich.
Danke und
Grüße
Stefan
Helfen kann ich dir so nicht, weil dein konkreter Code bzw. das Projekt
nicht vorliegt.
Aber ich weiß, was ich tun würde.
Nichts gegen Johann, aber als erstes würde ich mal von der linsin die
Funktionen rauswerfen und nachsehen ob der Effekt auch dann noch
besteht, wenn ich nur die Sin/Cos Tabelle im Programm hab.
Wenn geklärt ist, das die Tabelle alleine das Programm nicht
beeinflusst, würde ich mal die Assembler-Versionen der Funktionen durch
normale C-Funktionen ersetzen.
Wenn allerdings das blosse Vorhandensein der Tabelle die Font-Ausgabe
schon durcheinander bringt, dann muss man eben die Graphic-Funktionen
auseinander nehmen.
Bevor man Assembler in einem C-Programm benutzt, sollte man sich diese 3
Fragen stellen:
Ist es wirklich wirklich wirklich nötig?
Ist es wirklich wirklich wirklich nötig?
Ist es wirklich wirklich wirklich nötig?
Und sie auch wahrheitsgemäß beantworten!
Peter
Hihi, Peter das gefällt mir.
Naja, Johann hat die Bibliothek nun mal so geschrieben und sie (allein)
funktioniert auch hervorragend, vor allem schnell...worauf ich
angewiesen bin, da ich in einem iterativen Algoritmus ständig sin/cos
rechnen muss.
Habe schon in erwägung gezogen CORDIC zu nutzen, allerdings war mir das
für quick'n'dirty etwas zu umständlich gestern.
Bin jetzt dabei Karl Heinz' Ratschläge zu testen und bekomme merkwürdige
Ergebnisse. Anscheinend ist die bloße Anwesenheit der Lookup Table schon
nicht erwünscht. Mehr später...
Danke euch für eure Meinungen.
Grüße
Stefan
Inline Assembler wurde eh vom Dunkellord personlich erfunden.
Wenns schon asm sein muss, dann in ein extra File packen und sich an die
konventionen halten.
Martin Wende schrieb:> Inline Assembler wurde eh vom Dunkellord personlich erfunden.
Na dann passts ja.
Johann könnte man durchaus als den DuWeißtSchonWer beim AVR-gcc ansehen
:-)
(Soll heißen: Johann weiß schon was er tut - dem vertrau ich
normalerweise blind. Aber im vorliegenden Fall ist sein Code nun mal der
kürzere gegenüber dieser GLCD-Lib)
Hallo zusammen,
also meinen bisherigen Versuchen zufolge liegt unter anderem es an
folgendem Makro aus linsin.c:
1
// Ein Word per post-Increment aus dem Flash lesen.
2
// Dies ist besser als pgm_read_word (p++)
3
#define pgm_read_word_inc(addr) \
4
(__extension__({ \
5
uint16_t __result; \
6
__asm__ \
7
( \
8
"lpm %A0, Z+" "\n\t" \
9
"lpm %B0, Z+" \
10
: "=r" (__result), "+z" (addr) \
11
); \
12
__result; \
13
}))
Der gesamte restliche Code aus linsin.h und linsin.c kann eingebunden
werden, ohne das es Probleme bei den LCD Routinen gibt. Sobald ich
allerdings dieses pgm_read_word_inc Makro und auch das pgm_read_word aus
pgmspace.h Makro einbinde, bekomme ich Müll auf dem Display.
Mein aktuelles Workaround ist die Auskommentierung dieses Blocks und
folgende Defines
1
#define pgm_read_word_inc(a) 1
2
#define pgm_read_word(a) 1
Damit lässt sich alles einwandfrei kompillieren, allerdings macht dies
natürlich die sin/cos Funktionen unbrauchbar...
// Ein Word per post-Increment aus dem Flash lesen.
2
// Dies ist besser als pgm_read_word (p++)
Dann sollte die wieder laufen, nur eben etwas langsamer.
Oder du exportierst diese Funktion in ein extra Assemblerfile.
Inlineassembler macht jeder Compiler nen bissel anders.
Man kennt ja Dein Programm nicht, ob es wirklich auf 2 Zyklen mehr
ankommt.
In der Regel sollte man bei nem RISC nicht so pingelig sein müssen, da
sind 2 Zyklen Pinats.
Erst wenns um >=100 Zyklen geht, dann kann man mal versuchen, dran zu
drehen.
Man darf auch nicht vergessen, daß der AVR keine Interruptlevel hat. Es
nützt also nichts, einen Interrupt mit viel Mühe auf 50 Zyklen
einzudampfen, wenn eine anderer 500 Zyklen dauert. Die worst case Latenz
ist immer der das Maximum, also die 500 Zyklen.
Am besten, man schreibt erstmal alles komplett in C. Und erst, wenn es
klemmt, kann man analysieren, ob Assembler überhaupt was rausreißen
würde.
Peter
Werde euren Tipp wahrnehmen und das Ganze in C implementieren...
Allerdings was mir grad auffällt, auch der Aufruf des Makros
pgm_read_word führt ja schon zum Problem. Und dieses ist ja in
pgmspace.h, also einer generischen Header Datei definiert. Die Nutzung
von pgmspace.h ist die einzige Möglichkeit, die ich kenne für Flash
Zugriff. Dort wird auch alles mit inline Assembler gemacht...
Gibt es Alternativen?
Grüße
und viel Spaß im Schnee
S. G. schrieb:> Werde euren Tipp wahrnehmen und das Ganze in C implementieren...> Allerdings was mir grad auffällt, auch der Aufruf des Makros> pgm_read_word führt ja schon zum Problem.
Das kann/sollte allerdings nicht sein.
Wie hast du denn die pgm_read_word_inc ersetzt?
Ein ...
... anstelle der ursprünglichen Definition sollte eigentlich das Kind
geschaukelt haben.
wobei.
So ganz klar ist mir ehrlich gesagt nicht, wie da die Zusammenhänge
sind/sein sollen, die zum Fehler führen. Ich denke eher, wir sind auf
einer ganz kalten Spur. Wir versuchen hier Symptome zu behandeln und
nicht Ursachen.
S. G. schrieb:> Und dieses ist ja in> pgmspace.h, also einer generischen Header Datei definiert.
Die Compiler-Libs sollten eigentlich kugelsicher sein.
Daß sich ein Fehler auswirkt, wenn man sie benutzt, muß ja nicht heißen,
daß sie fehlerhaft sind. Der Fehler wird wohl woanders sein.
Peter
Hallo zusammen,
jetzt habe ich gleich keine Lust mehr. Wollte euch gerade ein
Minimalbsp. zusammenstöpseln, da lege ich mir ein neues Projekt an in
ATmelStudio 6.0 und füge meine kopierten Dateien (aus dem
Originalprojekt) hinzu, kompiliere direkt und alles funktioniert
einwandfrei mit inkludierter Linsin und GLCDL Bilbiothek. Versuche ich
daraufhin wiederholt das gleiche mit den Originaldateien im
Originalprojekt entstehen wieder die Fehler auf dem Display. Abhilfe
schafft immer noch der Verzicht auf pgm_read_byte() und Konsorten.
Ich habe mir die erzeugten Makefiles angeschaut, sind identisch, wie
auch die erzeiten cproj Dateien. Löschen alle erstellter *.o Dateien und
wiederholtes Erzeugen brachte im originalprojekt auch keine Änderung.
Das Originalprojekt wurde mit AtmelStudio 5.1 angelegt und dann in
AtmelStudio 6.0 importiert. Bisher gab es keinerlei Probleme, bis auf
dieses merkwürdige Verhalten.
Am Code scheint es wohl demnach nciht zu liegen...
Kennt ihr diesen Effekt von AtmelStudio?
Viele Grüße
Stefan
Hab den Thread eben erst gefunden...
Hat sich ds Problem eigentlich gelöst? Ich kann mit kaum vorstellen, daß
das Macro pgm_read_byte_inc aus dem linsin Modul Schuld an den Problemen
sein soll — zumal das Problem nach Kopieren des gesamten Projekts
verschwindet.
Hey,
das Problem hat sich insofern erledigt, als dass es ja mit dem
angelegten AtmelStudio 6.0 Projekt verschwundenn war und insofern, als
dass ich mittlerweile zwecks besserer Performance auf einen STM32F0
umgestiegen bin (Kann das DevKit für 7€ nur empfehlen :-) ) und eine
RTOS darauf laufen habe (ChibiOS). Alles funktioniert schnell und
einwandfrei.
Also wiegesagt, letzlich klären ließ sich das Ganze nicht. Mit Anlegen
eines neuen Projektes in AtmelStudio war es behoben, aber eben nicht
geklärt...
Grüße