Bibliotheken streiten sich um Daten im Flash / PROGMEM

OP #2945040
Lesenswert?

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
#2946620
Lesenswert?

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.
#2946668
Lesenswert?

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
OP #2946676
Lesenswert?

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
OP #2948098
Lesenswert?

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...
(Firma: fritzler-avr.de) #2948122
Lesenswert?

Na danns chreib die Lib eben um zu:
1
// 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.
#2948164
Lesenswert?

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
OP #2948304
Lesenswert?

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
#2948309
Lesenswert?

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 ...
1
#define pgm_read_word_inc(addr)   pgm_read_word (addr++)
... 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.
OP #2953404
Lesenswert?

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
OP #3250125
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren