AVR - Strings direkt aus Flash lesen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

AVR - Strings direkt aus Flash lesen

Beitragvon Timm Thaler » 25. Sep 2017, 02:36 AVR - Strings direkt aus Flash lesen

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.
Timm Thaler
 
Beiträge: 338
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Socke » 25. Sep 2017, 08:25 Re: AVR - Strings direkt aus Flash lesen

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
Socke
 
Beiträge: 2373
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon Timm Thaler » 25. Sep 2017, 11:55 Re: AVR - Strings direkt aus Flash lesen

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.
Timm Thaler
 
Beiträge: 338
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Socke » 25. Sep 2017, 15:25 Re: AVR - Strings direkt aus Flash lesen

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
Socke
 
Beiträge: 2373
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon Timm Thaler » 25. Sep 2017, 16:34 Re: AVR - Strings direkt aus Flash lesen

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.
Timm Thaler
 
Beiträge: 338
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 25. Sep 2017, 17:19 Re: AVR - Strings direkt aus Flash lesen

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3019
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Socke » 25. Sep 2017, 18:32 Re: AVR - Strings direkt aus Flash lesen

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
Socke
 
Beiträge: 2373
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon Timm Thaler » 25. Sep 2017, 19:42 Re: AVR - Strings direkt aus Flash lesen

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.
Timm Thaler
 
Beiträge: 338
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Mathias » 26. Sep 2017, 16:31 Re: AVR - Strings direkt aus Flash lesen

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3019
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Socke » 26. Sep 2017, 18:33 Re: AVR - Strings direkt aus Flash lesen

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
Socke
 
Beiträge: 2373
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon Mathias » 26. Sep 2017, 19:03 Re: AVR - Strings direkt aus Flash lesen

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3019
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 26. Sep 2017, 22:19 Re: AVR - Strings direkt aus Flash lesen

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.
Timm Thaler
 
Beiträge: 338
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Socke » 27. Sep 2017, 11:30 Re: AVR - Strings direkt aus Flash lesen

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 2. Okt 2017, 17:09, insgesamt 1-mal geändert.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Socke
 
Beiträge: 2373
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon Mathias » 27. Sep 2017, 16:34 Re: AVR - Strings direkt aus Flash lesen

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 gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3019
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Timm Thaler » 29. Sep 2017, 00:26 Re: AVR - Strings direkt aus Flash lesen

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
 
Timm Thaler
 
Beiträge: 338
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried