Forum: Mikrocontroller und Digitale Elektronik AVR Tutorial Frage: Lesen vom Flash


von Sina A. (sinapse)


Lesenswert?

Hallo,

gehe gerade das Tutorial hier durch... geht um lesen vom Flash

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_PROGMEM_und_pgm_read

da steht:
------------------------------
Dazu gibt es das AVR-spezifische GCC-Attribut progmem, mit dem eine 
Variablendeklaration im static storage[5] markiert werden kann:
1
const int value __attribute__((progmem)) = 1;


Effekt ist, dass die so markierte Variable nicht im RAM sondern im Flash 
angelegt wird. Wird durch "normalen" C-Code auf solch eine Variable 
zugegriffen, wird jedoch aus dem RAM gelesen und nicht aus dem Flash!
--------------------------------

Wird die variable also im Flash und im RAM angelegt? die variable 
value im RAM hat dann dieselbe Adresse wie die variable value im Flash?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sina A. schrieb:
> Effekt ist, dass die so markierte Variable nicht im RAM sondern im Flash
> angelegt wird.
Eine VARIABLE wird nicht im Flash angelegt, weil sie dort nicht GEÄNDERT 
werden kann. Nur KONSTANTE kannst du ins Flash ablegen.

> Wird die variable also im Flash und im RAM angelegt?
Nein.
Eine VARIABLE, die du ein einziges Mal (z.B. bei der Initialisierung) 
mit einem Wert beschreibst und dann nur noch liest, deren Initialwert 
wird aus dem Flash ins RAM kopiert und dann eben nur noch gelesen.

: Bearbeitet durch Moderator
von Sina A. (sinapse)


Lesenswert?

ok,

wenn dann in dem Beispiel weiter unten im tutorial
1
#include <avr/pgmspace.h>
2
3
/* Byte */
4
const uint8_t aByte PROGMEM = 123;
5
6
void foo (void)
7
{
8
  uint8_t a        = aByte;
9
  uint8_t b        = pgm_read_byte (&aByte);
10
}

dann ist aByte erstmal eine constante im RAM? d.h. in a steht dann jetzt 
der wert, der zufällig im RAM stand als die constante aByte angelegt 
wurde?

und &aByte ist die Adresse der Konstanten aByte im RAM?

aber bei pgm_read_byte(&aByte) ist &aByte die Adresse im Flash?

von Sebastian S. (amateur)


Lesenswert?

Ich habe früher (tm) mal im generierten Code herum gestochert und 
folgendes festgestellt:
Konstanten werden während der Initialisierung des Programms ins RAM 
geholt und sind somit relativ (Zugriffszeit) schnell. Brauchen also 
FLASH und RAM.
Kandidaten der Abteilung "progmem" bleiben wo sie hingehören und werden 
nur auf Anfrage geholt. Natürlich mit all den zugehörigen (zeitlich) 
Nachteilen.
Eigene Funktion, eigene Sequenzen - das kann dauern.

Mein Fazit aus dieser Erkenntnis war: FLASH nur wenn nötig 
(RAM-Ersparnis).

Keine Ahnung, ob das heute (tm) noch gilt.

von Sebastian S. (amateur)


Lesenswert?

Ich vergaß:
Bis heute habe ich nur einmal (explizit) FLASH genutzt.

Das war als ich viel zusagen hatte. Also etliche Menüs mit Texten füllen 
musste. Darstellung von kommentierten Werten. Bei der "bildhaften" 
Ausgabe ist auch die Geschwindigkeit von untergeordneter Größe.
Dabei wurde es aber im FLASH recht eng. Musste dann den großen Bruder 
verwenden.

von Falk B. (falk)


Lesenswert?

@Sebastian S. (amateur)

>Konstanten werden während der Initialisierung des Programms ins RAM
>geholt und sind somit relativ (Zugriffszeit) schnell. Brauchen also
>FLASH und RAM.

Falsch. Das sind globale oder statische VARIABLEN mit einem 
Initialisierungswert ungleich Null.

>Kandidaten der Abteilung "progmem" bleiben wo sie hingehören und werden
>nur auf Anfrage geholt. Natürlich mit all den zugehörigen (zeitlich)
>Nachteilen.

Kaum.

>Eigene Funktion, eigene Sequenzen

Ja.

>- das kann dauern.

Nein, denn ein lpm ist nur einen Takt langsamer als ein lds. Alles 
anderes ist identisch (Adressberechnung).

>Mein Fazit aus dieser Erkenntnis war: FLASH nur wenn nötig
>(RAM-Ersparnis).

Falsch. Immer wenn möglich!

>Keine Ahnung, ob das heute (tm) noch gilt.

Das "keine Ahnung" auf jeden Fall.

von Sebastian S. (amateur)


Lesenswert?

@Falk
Na dann bau' mal eine Schleife mit zwei/drei bestimmenden Konstanten aus 
dem FLASH und alternativ aus dem normalen, konstanten Pool auf und stopp 
die Zeit.

von Einer K. (Gast)


Lesenswert?

Sina A. schrieb:
> void foo (void)
> {
>   uint8_t a        = aByte;
>   uint8_t b        = pgm_read_byte (&aByte);
> }
Das ist grob Fahrlässig falsch!

Du kannst nicht die Adresse einer Ram Variablen als Adresse von DAten im 
Flash nutzen.

OK, du kannst (sehe ich ja), aber du wirst nicht das damit erreichen, 
was du dir vorstellst, was du dir wünscht.

von Falk B. (falk)


Lesenswert?

@Sina Anargo (sinapse)


>#include <avr/pgmspace.h>

>/* Byte */
>const uint8_t aByte PROGMEM = 123;

Konstante im Flash/Progmem.

>void foo (void)
>{
>  uint8_t a        = aByte;

Das geht so nicht, da kommt Unsinn raus!

>  uint8_t b        = pgm_read_byte (&aByte);

Das geht.

>dann ist aByte erstmal eine constante im RAM?

Flash.

> d.h. in a steht dann jetzt
>der wert, der zufällig im RAM stand als die constante aByte angelegt
>wurde?

Nö, aByte hat konstant 123.

>und &aByte ist die Adresse der Konstanten aByte im RAM?

Im Flash!

>aber bei pgm_read_byte(&aByte) ist &aByte die Adresse im Flash?

Eben!

von Georg G. (df2au)


Lesenswert?

Ehe ihr euch total selbst verwirrt: Es gibt im aktuellen GCC das 
Attribut FLASH. Dann kümmert ich der Compiler selbst um den passenden 
Zugriff.

von Falk B. (falk)


Lesenswert?

@Georg G. (df2au)

>Ehe ihr euch total selbst verwirrt: Es gibt im aktuellen GCC das
>Attribut FLASH. Dann kümmert ich der Compiler selbst um den passenden
>Zugriff.

Stimmt, aber das geht an einigen Stellen schief, weil man leicht glauben 
kann, daß es keinen Unterschied mehr zwischen RAM und Flash-Zugriffen 
gibt. Gibt es aber, vor allem wenn man mit Pointern in Funktionen 
hantiert. Jaja, dann gibt es die XMEM Dinger 8-0

von Joachim B. (jar)


Lesenswert?

vielleicht sehe ich das ja falsch aber steht da nicht viel Mist drin?

ich hatte es auch versucht zu korrigieren, bin aber nicht so der LaTex 
oder HTML Freak

1. Fehler Buchstabenvertauschung
bei Controllern mit mehr als 64kiB Flash auch

ELMP. das ist kein el.mag.Puls

using the LPM, ELPM sollte wohl stimmen

2. Fehler
strcmp_P
/* Liefert true zurück, wenn string_im_ram gleich "Hallo Welt" ist. */

mit Sicherheit nicht wenn gilt:
The strcmp_P() function is similar to strcmp() except that s2 is pointer 
to a string in program space.
und Mit strcmp (String Compare) können wir zwei Strings vergleichen. Der 
Rückgabewert kann hierbei folgende Werte haben:

   0 die Strings sind gleich
   >0 das erste ungleiche Zeichen in str1 ist größer als in str2
   <0 das erste ungleiche Zeichen in str1 ist kleiner als in str2


// ich musste bei strcmp immer auf Vergleich mit !true also false für 0 
prüfen

von c-hater (Gast)


Lesenswert?

Falk B. schrieb:

>>- das kann dauern.
>
> Nein, denn ein lpm ist nur einen Takt langsamer als ein lds. Alles
> anderes ist identisch (Adressberechnung).

Das ist weniger als die Hälfte der Wahrheit.

Gerade mit lds passt der Vergleich wirklich garnicht, denn dafür 
braucht's keinerlei Adressberechnungen zur Laufzeit, weil die Adresse 
als zur Build-Zeit berechnete Konstante Teil der Instruktion ist, d.h.: 
Das Laden aus dem RAM in ein Register läuft wirklich in genau zwei 
Takten vollständig ab.

Ein entsprechender Zugriff mit lpm auf den Flash ist hingegen nicht 
möglich, weil es dafür keine direkte Adressierungsart gibt, sondern nur 
indirekte. D.h.: vor dem eigentlichen Zugriff sind erstmal im Minimum 
noch zwei Adressregister zu laden. Damit sind wir schon in diesem 
optimalen Fall bei 2 (lds) vs. 5 (ldi,ldi,lpm) Takten. Dazu kommt aber 
noch, dass u.U. (Flashzugriff jenseits 64kB) auch noch das 
RAMPZ-SFIO-Register gesetzt werden muss, was mindestens weitere zwei 
Takte (ldi,out) kostet. Damit sind wir dann schon bei 2 vs. 7 Takten, 
also fast bei der vierfachen Laufzeit für den Flash-Zugriff.

Etwas besser würde deine Argumentation passen, wenn du lpm mit ld 
verglichen hättest (Zugriff auf Strings und Arrays). Das ist beides 
indirekte Adressierung, im einfachsten Fall unterscheidet sich das 
wirklich nur um einem Takt. Aber: auch hier ist ggf. für lpm die Sache 
mit dem Laden von RAMPZ nötig, das allerdings nur einmalig für mehrere 
Zugriffe in einer Schleife und fällt deswegen nicht mehr so sehr in's 
Gewicht. Viel schwerwiegender ist oft, dass bei lpm nur Postincrement 
möglich ist, in vielen Fällen aber Predecrement eine deutliche 
effizientere Umsetzung eines Algorithmus bezüglich der Prüfung einer 
Abbruchbedingung ermöglicht.

Und ganz eklig wird es beim Vergleich zwischen lpm und ldd (Zugriff auf 
Strukturen), weil es für lpm einfach nicht die Adressierungsart indirekt 
mit Displacement gibt und das Displacement (also der Offset in die 
Struktur) durch Laufzeitberechnungen gesetzt werden muss, und das u.U. 
sogar mit 24Bit Berechnungsbreite (bei Flash>64k).

Dazu kommt dann noch das Problem der eingeschränkten Wahl der 
Adressregister, denn lpm geht nur via Z, für RAM-Zugriffe kann man 
hingegen auch Y und (eingeschränkt) X verwenden. Dieser Sachverhalt kann 
durch nötige Registersicherungen u.U. weitere Perfomancenachteile 
generieren.

---

Nein: der Zugriff auf Daten im Flash kann schon ganz erhebliche 
Perfomance-Einbußen bescheren, darüber muß man sich im Klaren sein und 
das kannst auch du nicht wegdiskutieren.

Zusammenfassend könnte man vielleicht sagen: relativ unkritisch sind 
Flash-Zugriffe im Vergleich zu RAM-Zugriffen nur im Falle von 
sequentiellen Zugriffen auf eine "größere" Datenmenge, das allerdings 
auch nur dann, wenn sie mit aufsteigender Adressierung erfolgen kann.

Typische Anwendung natürlich: Strings kopieren oder vergleichen. Da ist 
der Nachteil von Flashzugriffen tatsächlich "relativ" gering. Aber auch 
hierbei sind es in einer engen Schleife immer noch:

loop:
 lpm reg,Z+ ;3
 br* loop      ;2

vs:

loop:
 ld reg,Z+  ;2
 br* loop    ;2

5 vs. 4 Takte, d.h.: 25% mehr Laufzeit für den Flash-Zugriff.

von Falk B. (falk)


Lesenswert?

@ c-hater (Gast)

>Das ist weniger als die Hälfte der Wahrheit.

Die größere Hälfte (sic!) wollte ich dir überlassen ;-)

>Nein: der Zugriff auf Daten im Flash kann schon ganz erhebliche
>Perfomance-Einbußen bescheren, darüber muß man sich im Klaren sein und
>das kannst auch du nicht wegdiskutieren.

Für dich ist selbst ein zu 90% gefülltes Glas mit deinem 
Lieblingsgetränk zu 10% leer, anstatt zu 90% voll. Mein Beileid.

>Zusammenfassend könnte man vielleicht sagen: relativ unkritisch sind
>Flash-Zugriffe im Vergleich zu RAM-Zugriffen nur im Falle von
>sequentiellen Zugriffen auf eine "größere" Datenmenge, das allerdings
>auch nur dann, wenn sie mit aufsteigender Adressierung erfolgen kann.

Nö, auch Arrayzugriffe sind nahezu gleich schnell, denn dann wird so 
oder so eine Adresse berechnet. Ob dann lpm mit 3 oder ld mit 2 Takten 
genutzt wird, fällt kaum ins Gewicht.

>hierbei sind es in einer engen Schleife immer noch:

>loop:
> lpm reg,Z+ ;3
 br* loop      ;2

>loop:
> ld reg,Z+  ;2
> br* loop    ;2

>5 vs. 4 Takte, d.h.: 25% mehr Laufzeit für den Flash-Zugriff.

Die spielen bei 90% aller C-Progamme keine Rolle und relativieren sich 
im Gesamtkontext auf bestenfalls 10% mehr CPU-Last.

Es ging mir auch gar nicht um das letzte Prozent Geschwindigkeit sondern 
darum, die schwachsinnige Panikmache bei direkter Flash-Nutzung zu 
kontern.

von Falk B. (falk)


Lesenswert?

@ Joachim B. (jar)

>vielleicht sehe ich das ja falsch aber steht da nicht viel Mist drin?

Hast du den Artikel so verunstaltet?

Ich hab es mal korrigiert.

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Flash_mit_PROGMEM_und_pgm_read

von c-hater (Gast)


Lesenswert?

Falk B. schrieb:

> Nö, auch Arrayzugriffe sind nahezu gleich schnell

Ähem, Arrayzugriffe sind ja typischerweise oft sequentielle Zugriffe auf 
eine "größere" Datenmenge. Also genau der Fall, für den ich einen 
relativ geringen Nachteil attestiert hatte.

Was also sucht das "Nö" am Anfang deines Satzes? Sprachfehler? 
Verständnisproblem?

Und nein: nicht jeder Zugriff auf Arrays ist derart unkritisch. 
Wahlfreier Zugriff auf kleine Arrays kann teuer werden bei Flash. Das 
wäre dann nämlich wieder die ldd-Situation wie beim Zugriff auf 
Strukturen. Aber so weit hast wohl schon garnicht mehr gelesen...

> Die spielen bei 90% aller C-Progamme keine Rolle

Das mag gut sein. Interessant sind eben genau die Fälle, wo es doch eine 
Rolle spielt.

> und relativieren sich
> im Gesamtkontext auf bestenfalls 10% mehr CPU-Last.

Das ist doch nun wirklich völliger Schwachsinn. Das hängt ja wohl sehr 
stark vom Kontext des Aufrufs ab. Z.B. eben das o.g., also wahlfreier 
Zugriff auf kleines Array und das dann in einer sehr häufig aufgerufenen 
ISR. Da kann der Unterschied in der Laufzeit schon sehr leicht mal den 
Unterschied zwischen "geht" und "geht nicht" für die Anwendung insgesamt 
ausmachen...

Wenn dir das nicht klar ist: schweige still und schäme dich!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ein Wort aus der Praxis: wer seinen Controller zu 90% auslastet, der 
sollte sowieso schnellstmöglich einen größeren oder schnelleren nehmen. 
Und wenn das Wohl oder Wehe einer ISR an ein paar Maschinenzyklen hängt, 
dann erst recht. Sonst fällt er spätestens bei der nächsten (beliebigen) 
Änderung auf die Nase...

von c-hater (Gast)


Lesenswert?

Lothar M. schrieb:

> Ein Wort aus der Praxis: wer seinen Controller zu 90% auslastet, der
> sollte sowieso schnellstmöglich einen größeren oder schnelleren nehmen.
> Und wenn das Wohl oder Wehe einer ISR an ein paar Maschinenzyklen hängt,
> dann erst recht. Sonst fällt er spätestens bei der nächsten (beliebigen)
> Änderung auf die Nase...

Das genau ist die Einstellung, die uns zu der Software geführt hat, die 
wir heute haben.

Also zu Software, die in den letzten 40 oder 50 Jahren trotz inzwischen 
um mehrere Größenordnungen gewachsener Leistung der Hardware genauso 
Scheiß-lahm ist wie eben vor 40 oder 50 Jahren...

Schön für den Anbieter von Software, dass er da Entwicklungsaufwand 
gespart hat, Scheisse für den Benutzer der Software. Nur gibt es eben 
viel mehr Benutzer einer Software als Anbieter derselben Software. 
Könnte gut sein, dass die sich diese Verarschung nicht endlos gefallen 
lassen...

Und, wenn man ehrlich ist: auch als Anbieter von Software ist man doch 
immer auch Benutzer von Software (nämlich den zur Entwicklung der 
eigenen Software nötigen Werkzeuge)  und ärgert sich regelmäßig darüber, 
dass deren neueste Version mal wieder deutlich fühlbar langsamer 
geworden ist, ohne einen signifikanten funktionalen Mehrwert zu bieten. 
Sie kostet nur neues Geld...

Jedem, dem sie nicht vollständig in's Hirn geschissen haben, ist klar: 
Das kann nicht endlos so weiter gehen. Irgendwann begreifen auch die 
Dümmsten, dass sie hier massiv verarscht und abgezockt werden...

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
> Hast du den Artikel so verunstaltet?
>
> Ich hab es mal korrigiert.

darauf hoffte ich, ich schrieb ja

Joachim B. schrieb:
> ich hatte es auch versucht zu korrigieren, bin aber nicht so der LaTex
> oder HTML Freak

aber hast du nicht nur halbe Arbeit geleistet?

es war falsch!
/* Liefert true zurück, wenn string_im_ram gleich "Hallo Welt" ist. */

es fehlt IMHO

entweder /* Liefert false zurück, wenn string_im_ram gleich "Hallo Welt" 
ist. */

oder wenn true bleiben soll

return !strcmp_P (string_im_ram, PSTR ("Hallo Welt"));

dann können die von mir/dir engefügten Kommentare auch raus

Die nachfolgende Funktion liefert 0 zurück, wenn string_im_ram gleich 
"Hallo Welt" ist. Mit strcmp (String Compare) können wir zwei Strings 
vergleichen. Der Rückgabewert kann hierbei folgende Werte haben:

   0 die Strings sind gleich
   >0 das erste ungleiche Zeichen in string_im_ram ist größer als in 
"Hallo Welt"
   <0 das erste ungleiche Zeichen in string_im_ram ist kleiner als in 
"Hallo Welt"

es gilt ja:
The strcmp_P() function is similar to strcmp() except that s2 is pointer 
to a string in program space.

zu
Falk B. schrieb:
> Hast du den Artikel so verunstaltet?

ja aber das kann man auch anders schreiben, egal du bist eben die 
Freundlichkeit in Person, nur warum immer so gefrustet, brauchst du das?

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Joachim B. (jar)

>> Hast du den Artikel so verunstaltet?

>ja aber das kann man auch anders schreiben, egal du bist eben die
>Freundlichkeit in Person, nur warum immer so gefrustet, brauchst du das?

Sind wir heute ein wenig empfindlich? So eine Sache klärt man besser auf 
der Diskussionsseite des Artikels. Wenn dann eine Lösung abgestimmt ist, 
bringt man sie in den Artikel. Solche Schmierzettel und Baustellen 
gehören nicht in den Artikel.

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
>>Freundlichkeit in Person, nur warum immer so gefrustet, brauchst du das?
>
> Sind wir heute ein wenig empfindlich?

nö, wollte ich nur mal anmerken, ist ja dein bevorzugter Schreibstil 
welcher schon anderen "aufgefallen" ist.
Die Frage, "brauchst du das" ist unbeantwortet!


Falk B. schrieb:
> So eine Sache klärt man besser auf
> der Diskussionsseite des Artikels.

ich schrieb ja ich bin nicht so der alles wissen Typ und fand es sollte 
korrigiert werden, wenn andere bessere Lösungen haben trete ich gerne 
zurück, aber bis dahin stand es dort falsch!

Lieber eine

Falk B. schrieb:
> verunstaltete

Korrektur als keine!

von Falk B. (falk)


Lesenswert?

@ Joachim B. (jar)

>nö, wollte ich nur mal anmerken, ist ja dein bevorzugter Schreibstil
>welcher schon anderen "aufgefallen" ist.

Ist eben so.

>Die Frage, "brauchst du das" ist unbeantwortet!

Was heißt "brauchen"? Es ist mein Stil, Dinge kurz und knapp und meist 
politisch inkorrekt auf den Punkt zu bringen. Mag sein daß das dem einen 
oder anderen Zeitgenossen zu ruppig ist.

https://de.wikipedia.org/wiki/Tacheles

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
> Was heißt "brauchen"? Es ist mein Stil, Dinge kurz und knapp

verstehe ich, mach ich auch zu oft

Falk B. schrieb:
> meist
> politisch inkorrekt auf den Punkt zu bringen

aber leider nicht nur, auch manchmal beleidigend

aber OK fachlich ist es ja meist passend!

von Falk B. (falk)


Lesenswert?

@Joachim B. (jar)

>aber leider nicht nur, auch manchmal beleidigend

War das Wort "verunstaltet" jetzt eine sooo arge Beleidigung für dich?

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
> @Joachim B. (jar)
>
>>aber leider nicht nur, auch manchmal beleidigend
>
> War das Wort "verunstaltet" jetzt eine sooo arge Beleidigung für dich?

ne für mich war es grad noch OK

du hast es genau getroffen, mir war halt wichtig das der alte Unsinn da 
nicht stehenbleibt ungeachtet von Schönheit!

aber mal unter uns, das hätte auch ohne deinen Kommentar korrigiert 
werden können ohne die direkte Ansprache an mich oder?

wolltest du damit erreichen das eher Blödsinn in den Seiten stehen 
bleibt und keiner mehr korrigieren mag um "Arbeit" zu vermeiden? :)

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Joachim B. (jar)

>du hast es genau getroffen, mir war halt wichtig das der alte Unsinn da
>nicht stehenbleibt ungeachtet von Schönheit!

Ok.

>aber mal unter uns, das hätte auch ohne deinen Kommentar korrigiert
>werden können ohne die direkte Ansprache an mich oder?

Mein Gott, leg doch mal nicht jedes Wort auf die Goldwaage!

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
> Mein Gott

mit dem habe ich es weniger : )

Falk B. schrieb:
> leg doch mal nicht jedes Wort auf die Goldwaage

OK

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
Noch kein Account? Hier anmelden.