AVR - Strings direkt aus Flash lesen

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

AVR - Strings direkt aus Flash lesen

Beitrag von Timm Thaler »

Ich möchte beim Programmieren mit FPC für den AVR Controller Strings direkt aus dem Flash lesen.

In Assembler macht man das so, dass man den Z-Pointer auf den Flash setzt, an die Stelle wo der String liegt, und dann mit LPM ausliest.

In AVR-GCC gibt es dafür PSTR("MeinText") und pgm_read_byte(Adresse), was dem Compiler sagt, dass er hier direkt aus dem Flash lesen soll.

In Pascal habe ich das jetzt mit

Code: Alles auswählen

  buffer : array[0..16] of char;
  buffer := pchar('MeinTextMeinText');
  for i := 0 to 15 do
    sendezeichen(buffer[i]);

versucht.

Was auch soweit funktioniert, ich kann verschiedenen Zeichenketten in den Buffer geben und die Zeichen auslesen.

Dummerweise werden die Zeichenketten zwar im Flash gespeichert - wo auch sonst -, aber dann nicht beim Aufruf buffer := pchar aus dem Flash gelesen, sondern aus dem RAM, wie das Listing zeigt.

Code: Alles auswählen

   ldi   r19,lo8(_sGH_DISPLAYs_Ld3)
   ldi   r18,hi8(_sGH_DISPLAYs_Ld3)  <= Ram-Adresse holen
   ldi   r26,17  <= Anzahl Zeichen
   mov   r20,r26
   mov   r30,r19
   mov   r31,r18  <= Ram-Adresse in Z-Pointer
   ldi   r18,lo8(U_sGH_DEFINE_ss_BUFFER)
   ldi   r19,hi8(U_sGH_DEFINE_ss_BUFFER) <= Adresse Buffer
# Peephole PushPushPopPop2Movw performed
   movw   r26,r18  <= Buffer in X-Pointer
.Lj33:
   ld   r0,Z+  <= aus Ram lesen
   st   X+,r0  <= in Buffer schreiben
   dec   r20
   brne   .Lj33


Jetzt bin ich der Sache mal nachgegangen und finde im Disassembling des kompletten Hexfiles gleich am Anfang:

Code: Alles auswählen

  72:   a0 e0          ldi   r26, 0x00   ; 0
  74:   b1 e0          ldi   r27, 0x01   ; 1
  76:   d1 e0          ldi   r29, 0x01   ; 1
  78:   ee ee          ldi   r30, 0xEE   ; 238  <= Z-Pointer auf Flash Adresse, wo die Zeichenketten stehen
  7a:   f8 e0          ldi   r31, 0x08   ; 8
  7c:   02 c0          rjmp   .+4         ;  0x82
  7e:   05 90          lpm   r0, Z+  <= Daten aus Flash laden
  80:   0d 92          st   X+, r0  <= und in Ram ablegen
  82:   a6 34          cpi   r26, 0x46   ; 70
  84:   bd 07          cpc   r27, r29
  86:   d9 f7          brne   .-10        ;  0x7e


Da werden also gleich am Anfang alle Zeichenketten in den Ram umkopiert. Ist nur bedingt eine gute Idee, weil der Ram des AVR Controllers begrenzt ist und ich da noch paar Messwerte speichern wollte.

Gibt es eine Möglichkeit dem Compiler zu sagen, dass er bei buffer := pchar('MeinTextMeinText'); bitte direkt aus dem Flash in buffer kopieren soll?

Leider findet man zur AVR Programmierung unter Lazarus / FPC nur sehr wenige Informationen.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Socke »

Timm Thaler hat geschrieben:Gibt es eine Möglichkeit dem Compiler zu sagen, dass er bei buffer := pchar('MeinTextMeinText'); bitte direkt aus dem Flash in buffer kopieren soll?

Ich denke, du willst dem Compiler sagen, er möge die Strings nicht direkt zu Programmstart sondern erst bei Verwendung aus dem Flash lesen. Ansonsten läge der String bereits im RAM, würde aber unnötigerweise nochmals in den RAM geladen. Damit würde das Programm sogar noch mehr Speicher benötigen als jetzt.

DAs Thema ist am besten im Bugtracker und ggf. auf der Mailingliste FPC-Devel aufgehoben. Der Programm-Startup-Code wird schließlich direkt vom Compiler erzeugt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Timm Thaler »

Im Prinzip würde es mir sogar reichen, wenn der Compiler das Programm gar nicht aus dem Flash in den Ram kopiert, ich eine Adresse für den String im Flash bekomme, und dann kann ich das selbst mittels Inline-Assembler auslesen. Wenn es denn gar nicht anders geht.

Ich weiss, dass das ein Problem ist, weil sich die AVRs hier anders verhalten als ein PC, aber da das recht häufig gebraucht wird sollte es eigentlich im Compiler für Embedded AVR berücksichtigt sein. Ich hab bestimmt nur noch nicht die richtige Funktion dafür gefunden.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Socke »

Timm Thaler hat geschrieben:Ich weiss, dass das ein Problem ist, weil sich die AVRs hier anders verhalten als ein PC, aber da das recht häufig gebraucht wird sollte es eigentlich im Compiler für Embedded AVR berücksichtigt sein. Ich hab bestimmt nur noch nicht die richtige Funktion dafür gefunden.

Der Free Pascal Compiler kann verglichen mit der GCC erst seit recht kurzer Zeit Programme für das embedded-Target bzw. den AVR-Prozessor erstellen. Daher gibt es für diese Plattformen noch viel zu tun.

Daher lege ich dir nochmals einen Bug-Tracker-Eintrag nahe; wenn du keinen erstellen möchtest, kann ich den auch gerne anlegen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Timm Thaler »

Ich hab mal ein paar Versionen zur Stringübergabe getestet. Erstaunlicherweise ist da vieles kombatibel:

Code: Alles auswählen

program test;
 
const
  tconst1 = 'AAAAAAAAA'// braucht 11 bytes
  tconst2 = 'CCCCCCCCC'// braucht 18 bytes
 
var
  tvar1 : shortstring = 'VVVVVVVVV'// braucht 256 bytes
  tarray1 : array[0..16] of char = 'VVVVVVVVVVVVVVVV'// braucht 17 bytes
  tbuf1 : shortstring;
  tbuf2 : array[0..16] of char;
 
procedure teststring;
 
begin
  tbuf1 := tconst1;  // fpc_shortstr_to_shortstr
  tbuf2 := tconst2;  // loop ram2ram
  tbuf1 := tvar1;    // fpc_shortstr_to_shortstr
  tbuf2 := tvar1;    // fpc_shortstr_to_chararray + loop ram2ram
  tbuf1 := tarray1;  // fpc_chararray_to_shortstr + fpc_shortstr_to_shortstr
  tbuf2 := pchar(tarray1)// loop ram2ram
  tbuf1 := 'DDDDDDDDD'// fpc_shortstr_to_shortstr // String braucht 11 bytes
  tbuf2 := 'EEEEEEEEE'// loop ram2ram // String braucht 18 bytes
end;
 
begin
  while true do
  begin
    teststring;
  end;
end.                 


Es zeigt sich, dass shortstring am Verschwenderischsten mit dem Speicher umgeht. Auch bei einem kurzen String werden 256 Bytes verwendet. Leider geht kein shortstring[16] wie sonst auch.

Im Disassembling wird auch klar, dass alle Varianten den String am Anfang in den Ram schreiben und dann aus dem Ram wieder auslesen.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Mathias »

Ich möchte beim Programmieren mit FPC für den AVR Controller Strings direkt aus dem Flash lesen.

Versteht ich dich richtig, du willst das selbe machen wie bei diesem Link, welcher dies mit C++ macht ?
http://shelvin.de/string-im-programmspe ... -ausgeben/

Der Free Pascal Compiler kann verglichen mit der GCC erst seit recht kurzer Zeit Programme für das embedded-Target bzw. den AVR-Prozessor erstellen.

Wen ich diese Wiki angucke, gibt es FPC schon mindestens 9 Jahre für den AVR. http://wiki.freepascal.org/index.php?ti ... on=history
Oder habe ich da etwas übersehen ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Socke »

Mathias hat geschrieben:Wen ich diese Wiki angucke, gibt es FPC schon mindestens 9 Jahre für den AVR. http://wiki.freepascal.org/index.php?ti ... on=history
Oder habe ich da etwas übersehen ?

An der Wikiseite hat sich nur in den ersten sieben Jahren nicht viel geändert; das Target mag meintewegen schon so lange vorhanden sein, aber wirklich genutzt wird es noch nicht so lange.

Edit:
Timm Thaler hat geschrieben:Es zeigt sich, dass shortstring am Verschwenderischsten mit dem Speicher umgeht. Auch bei einem kurzen String werden 256 Bytes verwendet. Leider geht kein shortstring[16] wie sonst auch.

Das so dokumentiert: ShortString ist immer 255 Zeichen + 1 Längenbyte groß. Eine String bestimmter Länge kannst du mit String[5] (nicht mit Shortstring[5]) anlegen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Timm Thaler »

Mathias hat geschrieben:Versteht ich dich richtig, du willst das selbe machen wie bei diesem Link, welcher dies mit C++ macht ?


Ja, genau so mache ich das in C.

Dabei bleibt der String im Flash und wird direkt während des Zugriffs mit LPM Byte für Byte aus dem Flash gelesen und an den Uart oder das Display ausgegeben.

Socke hat geschrieben:Das so dokumentiert: ShortString ist immer 255 Zeichen + 1 Längenbyte groß. Eine String bestimmter Länge kannst du mit String[5] (nicht mit Shortstring[5]) anlegen.


Ups, das geht tatsächlich. In http://wiki.freepascal.org/AVR_Programming steht noch, dass nur Shortstrings gehen. Mal sehen was sich daraus machen läßt.

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Mathias »

An der Wikiseite hat sich nur in den ersten sieben Jahren nicht viel geändert; das Target mag meintewegen schon so lange vorhanden sein, aber wirklich genutzt wird es noch nicht so lange.

Meinst du damit, das AVR und Lazarus in nächster Zeit noch recht interessant werden kann ?

Eine String bestimmter Länge kannst du mit String[5] (nicht mit Shortstring[5]) anlegen.

Als alter Turbo-Pascaler kommt dies sehr bekannt vor. :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Socke »

Timm Thaler hat geschrieben:Ups, das geht tatsächlich. In http://wiki.freepascal.org/AVR_Programming steht noch, dass nur Shortstrings gehen. Mal sehen was sich daraus machen läßt.

Nicht mehr :), ich habe gerade den Absatz ein wenig ergänzt.

Mathias hat geschrieben:Meinst du damit, das AVR und Lazarus in nächster Zeit noch recht interessant werden kann ?

Für C bzw. C++ gibt es eine etablierte Community; auch andere Sprachen wie Python und JavaScript breiten sich auf Microcontroller aus. Inwiefern Free Pascl interessant wird, hängt davon ab, ob es der Community gelingt, die vorhanden Tools (insbesondere MCU-Programmierer, Debugger; Assembler und Linker sind bereits weitestgehend in den Compiler integrierbar) in eine IDE (z.B. Lazarus) zu integrieren und viele Bibliotheken in guter Qualität zu erstellen. Ich träume hier von einm plattformübergreifenden Standard ähnlich der LCL für grafische Oberflächen - nur eben für Microcontroller und deren Peripherie. Für C bzw. C++ gibt es von beiden Unzählige.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Mathias »

viele Bibliotheken in guter Qualität zu erstellen.

Da würde man am besten mit dem Arduino/Atmega328 anfangen, dies ist der meist verbreitete AVR, vor allem bei den Anfängern.
Ich denke mal, man müsste mit digitalWrite und digitalRead anfangen.

Aber die grösste Arbeit wird wohl sein, Lazarus dazu bringen, da man bei F9 direkt kompiliert und in den AVR hochladen kann. ( Der grüne Pfeil bei der Arduino-IDE, im Kreis, welcher nach rechts zeigt. ) :wink:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Timm Thaler »

Mathias hat geschrieben:Ich denke mal, man müsste mit digitalWrite und digitalRead anfangen.


IO Pins sind easy, das macht der Compiler schon richtig. PortA := PortA or (1 shl 2); macht der Compiler zu sbi PortA, PA2. Auch Timer, Uart und so funktionieren, da kann man vielleicht noch bisschen Wrapper drumbasteln, aber im Prinzip geht das.

Aber mit AVR eigenen Programmierstilen hat der Compiler echt Probleme. Zum Beispiel Strings direkt aus dem Flash lesen, oder Wertetabellen im Flash ablegen. Ich hab das mal auf die Spitze getrieben, mit 64 verschiedenen Strings zu je 16 Chars schmeisst der Compiler ein out of memory, weil er die Strings partout erstmal alle in den Ram kopieren will. Das macht man beim Avr eben nicht.

Man müsste beim Anlegen von Konstanten angeben können, dass die im Flash liegen.

Ich hab 15+ Jahre Erfahrung mit Assembler auf Avr. Ich würd auch zur Portierung von fpc beitragen wollen. Aber ich finde keinen Einsprungpunkt, und im englischen Forum scheint bezüglich Avr auch tote Hose zu sein.

Vielleicht besteht auch kein Bedarf, wer C nicht will kann ja auch Ada für Avr nehmen.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Socke »

Timm Thaler hat geschrieben:Ich hab 15+ Jahre Erfahrung mit Assembler auf Avr. Ich würd auch zur Portierung von fpc beitragen wollen. Aber ich finde keinen Einsprungpunkt, und im englischen Forum scheint bezüglich Avr auch tote Hose zu sein.

Wenn du direkt zum Compiler beitragen möchtest, ist die Mailing-List fpc-devel die richtig - oder eben der Bugtracker.
Im wesentlich ist da so wenig los, weil alle vor sich hin basteln. Es gibt schon einige User und auf Fragen auf der Mailing-Liste gibt es auch zum Thema AVR Antworten ;-)

Edit: es gibt bereits einen Bug-Eintrag dazu: https://bugs.freepascal.org/view.php?id=32074
Zuletzt geändert von Socke am Mo 2. Okt 2017, 18:09, insgesamt 1-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6160
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Mathias »

Nochmal zu Hauptthema zurück, hast du folgendes auch schon probiert ?
Normalerweise behandelt FPC eine solche Const wie eine var.
Mit dem Schalter J- kann man dies unterbinden.

Code: Alles auswählen

{$J-}
const
  s: string = '1234';
begin
  s := 'Hello world'// geht nicht mehr

Vielleicht hat dies auch einen Einfluss beim AVR.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: AVR - Strings direkt aus Flash lesen

Beitrag von Timm Thaler »

Mathias hat geschrieben:Mit dem Schalter J- kann man dies unterbinden.


Bringt anscheinend nichts.

Code: Alles auswählen

program test;
 
{$J-}
 
const
  tconst1 : string[16] = 'AAAAAAAAAAAAAAAA';
  tconst2 = 'CCCCCCCCCCCCCCCC';
 
var
  tbuf1 : string[16];
 
procedure teststring;
 
begin
  asm nop end;
  tbuf1 := tconst1;  //
  asm nop end;
  tbuf1 := tconst2;  //
  asm nop end;
end;
 
begin
  while true do
  begin
    teststring;
  end;
end.


enthält im decompilierten Hexfile am Programmstart

Code: Alles auswählen

  74:   b1 e0          ldi   r27, 0x01   ; 1
  76:   d1 e0          ldi   r29, 0x01   ; 1
  78:   e0 ea          ldi   r30, 0xA0   ; 160
  7a:   f1 e0          ldi   r31, 0x01   ; 1
  7c:   02 c0          rjmp   .+4         ;  0x82
  7e:   05 90          lpm   r0, Z+ <= schreibt die ab Adresse 01A0 stehenden Strings in den Ram
  80:   0d 92          st   X+, r0
  82:   a4 32          cpi   r26, 0x24   ; 36
  84:   bd 07          cpc   r27, r29
  86:   d9 f7          brne   .-10        ;  0x7e
 


und irgendwann den Prozeduraufruf mit

Code: Alles auswählen

  a0:   24 e2          ldi   r18, 0x24   ; 36
  a2:   91 e0          ldi   r25, 0x01   ; 1
  a4:   40 e0          ldi   r20, 0x00   ; 0
  a6:   51 e0          ldi   r21, 0x01   ; 1
  a8:   60 e1          ldi   r22, 0x10   ; 16
  aa:   71 2d          mov   r23, r1
  ac:   82 2f          mov   r24, r18
  ae:   0e 94 b5 00    call   0x16a   ;  0x16a <= ruft fpc_shortstr_to_shortstr auf, welche den String im Ram umkopiert
 

Antworten