getmem funktioniert nicht
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1647
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
getmem funktioniert nicht
Hallo,
Wenn ich in einem AVR Pascalprogramm getmem aufrufe, so kehrt dieser nie wieder zum Aufrufer zurück.
Gibt es hier irgendwie einen workaround um dynamisch Speicherplatz zu reservieren?
Wenn ich in einem AVR Pascalprogramm getmem aufrufe, so kehrt dieser nie wieder zum Aufrufer zurück.
Gibt es hier irgendwie einen workaround um dynamisch Speicherplatz zu reservieren?
- af0815
- Lazarusforum e. V.
- Beiträge: 6791
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: getmem funktioniert nicht
Gegenfrage, gehen dynamische Objekte überhaupt am AVR ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1647
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: getmem funktioniert nicht
Nein dynamische Objekte gehen nicht. Nur statische. Aber es funktioniert auch ohne Objekte nicht.af0815 hat geschrieben: Mo 8. Feb 2021, 12:42 Gegenfrage, gehen dynamische Objekte überhaupt am AVR ?
Code: Alles auswählen
program test;
var p : PByte;
begin
getmem(p, 1024);
freemem(p, 1024);
end.
Ich hatte FPC stable 3.2 und wollte es jetzt mal mit Trunk ausprobieren. Da läßt sich aktuell aber der Compiler nicht übersetzen.
-
- Beiträge: 958
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: getmem funktioniert nicht
Die Embedded Platform hat standardmäßig keinen Heap Manager installiert. Dazu musst du die Unit heapmgr einbinden und ihr mittels eines oder mehreren Aufrufen von RegisterHeapBlock(AAddress: Pointer; ASize: PtrUInt) mitteilen in welchen Speicherbereichen sich der Heap Manager austoben darf.fliegermichl hat geschrieben: Mo 8. Feb 2021, 09:49 Wenn ich in einem AVR Pascalprogramm getmem aufrufe, so kehrt dieser nie wieder zum Aufrufer zurück.
Gibt es hier irgendwie einen workaround um dynamisch Speicherplatz zu reservieren?
FPC Compiler Entwickler
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1647
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: getmem funktioniert nicht
Vielen Dank für die Info.
Ich hätte mir zwei Tage Suche erspart, wenn da vielleicht wenigstens eine Warnung ausgegeben worden wäre.
laut Datenblatt beginnt das SRAM bei dem ATMega328P bei 0x02FF. Kann ich einfach diese Adresse angeben?
Ich hätte mir zwei Tage Suche erspart, wenn da vielleicht wenigstens eine Warnung ausgegeben worden wäre.
laut Datenblatt beginnt das SRAM bei dem ATMega328P bei 0x02FF. Kann ich einfach diese Adresse angeben?
-
- 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: getmem funktioniert nicht
Im SRAM tummeln sich ja noch Deine anderen Variablen, der Stack, Strings...
Und: Warum? Was bringt Dir die dynamische Zuweisung? Globale Variablen, Arrays, Strings werden unverrückbar im SRAM angelegt. Lokale Variablen werden temporär im Stack oder in Registern angelegt.
Selbst wenn Du einen SRAM-Bereich wieder freigibst - er wird nicht dynamisch von Variablen belegt. Er wird nur verwendet, wenn DU ihn wieder zuweist.
Und dann kannst Du gleich ein globales Array dauerhaft festlegen.
Und: Warum? Was bringt Dir die dynamische Zuweisung? Globale Variablen, Arrays, Strings werden unverrückbar im SRAM angelegt. Lokale Variablen werden temporär im Stack oder in Registern angelegt.
Selbst wenn Du einen SRAM-Bereich wieder freigibst - er wird nicht dynamisch von Variablen belegt. Er wird nur verwendet, wenn DU ihn wieder zuweist.
Und dann kannst Du gleich ein globales Array dauerhaft festlegen.
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1647
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: getmem funktioniert nicht
Ja eben, da bin ich mir nicht sicher.
Momentan brauche ich das für die Verwaltung der Neopixel.
Für jedes Pixel werden abhängig vom Typ 36 (RGB) oder 42 (RGBW) Bytes benötigt und zwar abhängig von der Anzahl der Pixel.
In einem normalen Programm muss man sich da keinen Kopf drum machen. Man reserviert Speicher via getmem, weist den einer Variablen zu und um den Rest kümmert sich der Compiler. Hier soll ich jetzt dem Heapmanager sagen, wo der zu verwaltende Speicherbereich liegt und wie groß der sein soll und das ohne Kenntnis darüber was der Compiler so im Hintergrund da noch alles treibt.
Momentan brauche ich das für die Verwaltung der Neopixel.
Für jedes Pixel werden abhängig vom Typ 36 (RGB) oder 42 (RGBW) Bytes benötigt und zwar abhängig von der Anzahl der Pixel.
In einem normalen Programm muss man sich da keinen Kopf drum machen. Man reserviert Speicher via getmem, weist den einer Variablen zu und um den Rest kümmert sich der Compiler. Hier soll ich jetzt dem Heapmanager sagen, wo der zu verwaltende Speicherbereich liegt und wie groß der sein soll und das ohne Kenntnis darüber was der Compiler so im Hintergrund da noch alles treibt.
-
- Beiträge: 958
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: getmem funktioniert nicht
Der Compiler hat keine Ahnung was mit den Heapfunktionen angestellt wird, da diese keine wirkliche Compilermagic beinhalten.fliegermichl hat geschrieben: Mo 8. Feb 2021, 17:41 Ich hätte mir zwei Tage Suche erspart, wenn da vielleicht wenigstens eine Warnung ausgegeben worden wäre.
Wobei es durchaus sinnvoll wäre irgendwo prominenter im Wiki zu erwähnen, dass dynamische Allokationen entweder vermieden werden sollen, oder man sich zumindest etwas selbst darum kümmern muss...
Das ist eben mit ein Grund, warum du im Embedded Bereich weniger dynamische Allokationen verwenden solltest. Und wenn doch, dann musst du eben die entsprechenden involvierten Typen studieren und dementsprechend wissen, was für eine Größe sie brauchen.fliegermichl hat geschrieben: Mo 8. Feb 2021, 21:34 In einem normalen Programm muss man sich da keinen Kopf drum machen. Man reserviert Speicher via getmem, weist den einer Variablen zu und um den Rest kümmert sich der Compiler. Hier soll ich jetzt dem Heapmanager sagen, wo der zu verwaltende Speicherbereich liegt und wie groß der sein soll und das ohne Kenntnis darüber was der Compiler so im Hintergrund da noch alles treibt.
FPC Compiler Entwickler
-
- 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: getmem funktioniert nicht
Und die sollen plug&play angestöpselt werden und Du weißt vorher nicht welche und wieviele oder was?fliegermichl hat geschrieben: Mo 8. Feb 2021, 21:34 Für jedes Pixel werden abhängig vom Typ 36 (RGB) oder 42 (RGBW) Bytes benötigt und zwar abhängig von der Anzahl der Pixel.
Dann legst Du ein globales Array mit der maximalen Anzahl an, welches Du als Buffer verwendest.
Mem dynamisch anfordern fliegt Dir spätestens um die Ohren, wenn Du ein Neo mehr anstöpselst als Speicher dafür vorhanden ist.
So ein AVR ist halt kein PC oder Raspberry.
- kupferstecher
- Beiträge: 434
- Registriert: Do 17. Nov 2016, 11:52
Re: getmem funktioniert nicht
D.h. man kann eine statische Variable als Heap-Block definieren, bei der Initialisierung zuweisen, und der Compiler kümmert sich dann um den ganzen Rest?PascalDragon hat geschrieben: Mo 8. Feb 2021, 13:28 Dazu musst du die Unit heapmgr einbinden und ihr mittels eines oder mehreren Aufrufen von RegisterHeapBlock(AAddress: Pointer; ASize: PtrUInt) mitteilen in welchen Speicherbereichen sich der Heap Manager austoben darf.
So etwa:
Code: Alles auswählen
uses
heapmgr;
Const
HeapSize = 1024; //Byte
var
HeapArea: Array[1..HeapSize] of Byte;
begin
RegisterHeapBlock(@HeapArea, HeapSize);
...
- af0815
- Lazarusforum e. V.
- Beiträge: 6791
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: getmem funktioniert nicht
Grundlegende Frage, bringt der Heapmanager wirklich soviel, das man den braucht. Der wird ja von der Codegröße auch nicht umsonst sein. Und das am AVR.
Schon mal den Speicherverbrauch des Heapmanagers im Codebereich in Erfahrung gebracht, der Overhead würde mich interessieren.
Schon mal den Speicherverbrauch des Heapmanagers im Codebereich in Erfahrung gebracht, der Overhead würde mich interessieren.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
-
- Beiträge: 958
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: getmem funktioniert nicht
Nicht der Compiler, sondern die RTL. Aber ansonsten ja, nur dass der hier verwendete Heapmanager einfacher gestrickt ist als der auf „großen” Systemen. (Und siehe meine Anmerkung weiter unten, dass RegisterHeapBlock normalerweise sogar gar nicht nötig ist)kupferstecher hat geschrieben: Di 9. Feb 2021, 23:07D.h. man kann eine statische Variable als Heap-Block definieren, bei der Initialisierung zuweisen, und der Compiler kümmert sich dann um den ganzen Rest?PascalDragon hat geschrieben: Mo 8. Feb 2021, 13:28 Dazu musst du die Unit heapmgr einbinden und ihr mittels eines oder mehreren Aufrufen von RegisterHeapBlock(AAddress: Pointer; ASize: PtrUInt) mitteilen in welchen Speicherbereichen sich der Heap Manager austoben darf.
Das muss man glaub ich selbst wissen, ob einem der Einsatz des Heapmanagers wert ist. Vielleicht nicht gerade auf dem kleinsten AVR, aber auf den etwas größeren ARM Microcontrollern oder den ESPs könnte es Einsatzzwecke dafür geben. FreeRTOS unterstützt ja glaube ich auch dynamische Allokation.af0815 hat geschrieben: Mi 10. Feb 2021, 06:47 Grundlegende Frage, bringt der Heapmanager wirklich soviel, das man den braucht. Der wird ja von der Codegröße auch nicht umsonst sein. Und das am AVR.
Probier's einfach aus. Du musst nur die Unit einbinden, du brauchst noch nichtmal was mit RegisterHeapBlock registrieren, da der Compiler einen initialen Heapbereich vorsieht (kann mit -ChXXX oder {$memory stacksize,heapsize} geändert werden), der nur eben normalerweise nicht mitgelinkt wird, da keine Unit ihn referenziert.af0815 hat geschrieben: Mi 10. Feb 2021, 06:47 Schon mal den Speicherverbrauch des Heapmanagers im Codebereich in Erfahrung gebracht, der Overhead würde mich interessieren.
FPC Compiler Entwickler
-
- Beiträge: 2122
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: getmem funktioniert nicht
Einen Heap Manager zu verwenden fügt overhead hinzu den man normalerweise auf Microcontrollern vermeiden will.
Wenn du Polymorphismen brauchst ist es meist einfacher statisch genug platz zu alloziieren und den dann abhängig von dem pixel typen drauf zugreifen.
Pascal bietet dafür bereits schon das syntaktische Feature der varianten Records an:
Der Record TPixelArray ist dann so groß das entweder RGBPixels oder RGBWPixels komplett reinpassen. Die größe die vom Compiler alloziiert wird ist also max(SizeOf(RGBPixels), SizeOF(RGBWPixels). Wenn du das extra byte für pixeltype nicht brauchst, geht das auch so:
Wenn du Polymorphismen brauchst ist es meist einfacher statisch genug platz zu alloziieren und den dann abhängig von dem pixel typen drauf zugreifen.
Pascal bietet dafür bereits schon das syntaktische Feature der varianten Records an:
Code: Alles auswählen
TPixelType = (ptRGB, ptRGBW);
TRGBRec = packed record
r, g, b: Byte;
end;
TRGBWRec = packed record
r, g, b, w: Byte;
end;
generic TPixelArray<const Size: SizeInt> = record
PixelType: TPixelType;
case PixelType of
ptRGB: (RGBPixels: Array[0..Size-1] of TRGBRec);
ptRGBW: (RGBWPixels: Array[0..Size-1] of TRGBWRec);
end;
var
pixels: specialize TPixelArray<1024>;
begin
pixels := GeneratePixels;
if pixels.PixelType = ptRGB;
PrintRGB(Pixels.RGBPixels)
else
PrintRGBW(Pixels.RGBWPixels);
end.
Code: Alles auswählen
generic TPixelArray<const Size: SizeInt> = record
case TPixelType of
ptRGB: (RGBPixels: Array[0..Size-1] of TRGBRec);
ptRGBW: (RGBWPixels: Array[0..Size-1] of TRGBWRec);
end;
-
- Beiträge: 761
- Registriert: Di 23. Aug 2016, 14:25
- OS, Lazarus, FPC: Windows 11
- CPU-Target: 64Bit
- Wohnort: Berlin
Re: getmem funktioniert nicht
Bei diesen kleinen Controllern würde ich niemals dynamische Speicherverwaltung nutzen.
Der hat ja eh nur 2 KByte RAM.
Wenn der RAM knapp ist, kannst Du auch den RAM mehrfach benutzen.
Den Speicher für die NeoPixel kannst Du dann evtl. auch für andere Dinge nutzen.
Also Du bastelst deine Daten für die NeoPixel und schiebst sie dann aus.
Diese Daten bleiben ja in den LEDs erhalten und gehen nicht verloren.
Nun kannst Du den Speicher vorrübergehend auch für was anderes benutzen.
Danach must Du natürlich wieder die Daten für die NeoPixels aufbereiten
Im Prinzip funktioniert das wie ein Varianten Record.
Siro
Der hat ja eh nur 2 KByte RAM.
Wenn der RAM knapp ist, kannst Du auch den RAM mehrfach benutzen.
Den Speicher für die NeoPixel kannst Du dann evtl. auch für andere Dinge nutzen.
Also Du bastelst deine Daten für die NeoPixel und schiebst sie dann aus.
Diese Daten bleiben ja in den LEDs erhalten und gehen nicht verloren.
Nun kannst Du den Speicher vorrübergehend auch für was anderes benutzen.
Danach must Du natürlich wieder die Daten für die NeoPixels aufbereiten
Im Prinzip funktioniert das wie ein Varianten Record.
Code: Alles auswählen
var UniRam : Array[0..1023] of Byte; // 1 KByte für diverse Zwecke irgendwo im RAM
var NeoPixel:Array[0..43] of record
r,g,b:Byte;
end absolute UniRam; // Die Daten befinden sich an der Adresse UniRam, wo genau legt der Compiler bzw. Linker fest.
var Diverses:Array[0..16] of Integer absolute UniRam; // Dieses Array liegt an gleicher Speicherstelle wie die NeoPixels
procedure Test;
begin
NeoPixel[0].r:=$7f;
Diverses[0]:=123;
end;
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1647
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: getmem funktioniert nicht
Hört sich nach brauchbaren Lösungen an.
Ich hab zwar den ATMega328P mit 8Kb RAM aber verRAMschen muss man den trotzdem nicht.
Ich hab zwar den ATMega328P mit 8Kb RAM aber verRAMschen muss man den trotzdem nicht.