Unterschiede AssignFile und fpOpen?

Rund um die LCL und andere Komponenten
Antworten
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

Unterschiede AssignFile und fpOpen?

Beitrag von Timm Thaler »

Ich benutze für normale Dateizugriffe die File-Funktionen aus den SysUtils wie AssignFile, Rewrite, Reset mit Write und Read.

Für die GPIO-Zugriffe auf dem Raspberry habe ich mir aus einer Anleitung etwas mit den Filezugriffen aus der BaseUnix gebastelt, das benutzt fpOpen, fpWrite, fpRead, fpClose und sieht dann so aus:

Code: Alles auswählen

function Tgpio.PinGetValue(apin : string):integer;
var
  fhnd : integer;
  fname : string;
  aval : string[5] = '0';
begin
  fname := cgpio_pin + apin + cgpio_val;
  try
    fhnd := FpOpen(fname, O_RdOnly);        // Value Pin
    FpRead(fhnd, aval[1], 1)// Value in Buffer
  finally
    FpClose(fhnd);
  end;
  result := StrToInt(aval);
end;   


Mal abgesehen von der Syntax: Was sind die grundlegenden Unterschiede zwischen den beiden Zugriffsarten? Kann ich auf die GPIOs auch mit Write / Read zugreifen, oder geht das nur bei "richtigen" Dateien?

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

Re: Unterschiede AssignFile und fpOpen?

Beitrag von Mathias »

Unterschiede AssignFile und fpOpen?

AssignFile, geht auf allen Plattformen, fpOpen, ist auf Linux beschränkt.

Kann ich auf die GPIOs auch mit Write / Read zugreifen, oder geht das nur bei "richtigen" Dateien?

Dies müsste im Prinzip auch gehen, mit diesen beiden Befehlen kann man zB. auf auf die COM-Schnittstellen zugreifen, nur hat man keine Möglichkeit, die Parameter zu verstellen.
Unter DOS musste man dann die Parameter mit "Mode" verstellen. Oder unter Windows über den Geräte-Manager.

Wen man mit FpOpen arbeiten, kann man mit FpIOCtrl Parameter verstellen, zB. bei I²C die Adresse des End-Gerätes.

Schlussendlich gehen bei Linux alle Datei/Geräte - Zugriffe über FpOpen etc. Gucke mal Memo1.SaveToFile genauer an, du wirst unter Linux auch fpOpen finden.
Gucke mal den Ordner /dev genauer an.

Noch eine Frage zu deinem Code, wird der Pin-Status beim Raspi als String zurück geliefert, das du ein StrToInt verwenden musst ? 8)
Ich dachte sowas käme als Binär-Code zurück.
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: Unterschiede AssignFile und fpOpen?

Beitrag von Timm Thaler »

Mathias hat geschrieben:AssignFile, geht auf allen Plattformen, fpOpen, ist auf Linux beschränkt.


Ja ok, das ist klar.

Wen man mit FpOpen arbeiten, kann man mit FpIOCtrl Parameter verstellen, zB. bei I²C die Adresse des End-Gerätes.


Das ist interessant, I2C will ich mir demnächst mal vornehmen.

Noch eine Frage zu deinem Code, wird der Pin-Status beim Raspi als String zurück geliefert, das du ein StrToInt verwenden musst ? 8)
Ich dachte sowas käme als Binär-Code zurück.


Ich übergebe einen String und die Länge, bzw. lese in einen String. Und in der "Datei" stehen ASCII-Zeichen, man kann z.B. im Verzeichnis /sys/class/gpio/gpio12 die "Datei" direction aufmachen, da steht dann "in" oder die "Datei" value mit "0" oder "1". Man kann sogar die Datei im Editor öffnen, den entsprechenden Text reinschreiben und beim Speichern wird der GPIO gesetzt. Der GPIO muss natürlich vorher mit export aktiviert worden sein.

Ich müsste da kein StrToInt verwenden, ich könnte das auch über eine Case machen und dann True oder False rausbekommen. Ich denke die Verwendung von Ascii ist hier keine schlechte Idee, weil man dann aus vielen Sprachen (Python, Perl, C und sogar mittels Bash-Script) auf die GPIOs zugreifen kann.

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

Re: Unterschiede AssignFile und fpOpen?

Beitrag von Mathias »

Und in der "Datei" stehen ASCII-Zeichen, man kann z.B. im Verzeichnis /sys/class/gpio/gpio12 die "Datei" direction aufmachen, da steht dann "in" oder die "Datei" value mit "0" oder "1". Man kann sogar die Datei im Editor öffnen, den entsprechenden Text reinschreiben und beim Speichern wird der GPIO gesetzt.

Das habe ich nicht gewusst, aber dies ist sicher nicht so Ressourcensparend, wie wen man es Binär setzt. Ich weis nur, der Raspi ist sehr begrenzt in der Leistung.
Mit den GPIO habne ich mich auf dem Raspi noch nicht befasst, aber dafür mit I²C.

Dafür habe ich eine kleine Klasse geschrieben, habe sie aber nur auf dem PC getestet, aber müsste auf dem Raspi auch laufen.

Code: Alles auswählen

unit I2C;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, Dialogs, BaseUnix;
 
type
 
  { TI2C }
 
  TI2C = class(TObject)
  private
    fI2C_Device: cint;
  public
    property I2C_Device: cint read fI2C_Device;
    constructor Create(Adevice: string);
    destructor Destroy; override;
 
    procedure SetDevice(addr:cint);
    procedure writeBuf(buf: array of byte);
    procedure readBuf(var buf: array of byte);
  end;
 
implementation
 
{ TI2C }
 
const
  I2C_SLAVE = $0703;
 
constructor TI2C.Create(Adevice: string);
begin
  inherited Create;
 
  fI2C_Device := FpOpen(Adevice, O_RDWR);
  if fI2C_Device = -1 then begin
    ShowMessage('Kann I²C nicht öffnen, Error:' + IntToStr(fI2C_Device));
  end;
end;
 
destructor TI2C.Destroy;
begin
  FpClose(fI2C_Device);
 
  inherited Destroy;
end;
 
procedure TI2C.SetDevice(addr: cint);
begin
  fpIOCtl(fI2C_Device, I2C_SLAVE, pointer(addr));
end;
 
procedure TI2C.writeBuf(buf: array of byte);
begin
  FpWrite(fI2C_Device, buf, Length(buf));
end;
 
procedure TI2C.readBuf(var buf: array of byte);
begin
    FpRead(fI2C_Device, buf, Length(buf));
end;
 
end.
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: Unterschiede AssignFile und fpOpen?

Beitrag von Timm Thaler »

Mathias hat geschrieben:Das habe ich nicht gewusst, aber dies ist sicher nicht so Ressourcensparend, wie wen man es Binär setzt. Ich weis nur, der Raspi ist sehr begrenzt in der Leistung.


Naja, wir fragen hier eine virtuelle Datei ab und lesen ein paar Bytes aus. Da immer ein ganzes Byte gelesen wird, ist es ziemlich egal, ob da eine "1" als ASCII oder eine $01 als Datenwert drinsteht.

Ich hab hier ein Programm, welches alle 10msec 10 GPIO einliest, diese entprellt und bei einem Ereignis ein Relais schaltet oder einen Eintrag in eine Logdatei schreibt. Dann geht es wieder für 10msec schlafen.

Das läuft im Taskmanager mit genau 0% CPU-Last und braucht 1.6MB Speicher. Vorher hatte ich die gleichen Funktionen in node-red abgebildet, das rödelte dann ständig bei 8-10% CPU-Last und 150 bis 200MB Speicher. Ich glaube das File-IO auf die GPIOs ist hier nicht das Problem. ;-)

Allerdings habe ich festgestellt, dass das Aktivieren eines GPIO mit "export" durchaus 50msec dauern kann, bis der GPIO zur Verfügung steht, also man Direction und Value setzen kann:

Code: Alles auswählen

function Tgpio.PinEnable(apin : string) : integer;
var
  fhnd, kd : integer;
  fname : string;
begin
  try
    fhnd := FpOpen(cgpio_exp, O_WrOnly);   // Export Pin
    FpWrite(fhnd, apin[1], Length(apin));   // Export Pin Nummer
  finally
    FpClose(fhnd);
  end;
  if fhnd > 0 then
  begin
    fname := cgpio_pin + apin + cgpio_dir;   // Direction Pin prüfen
    for kd := 1 to 20 do
    begin
      try
        fhnd := FpOpen(fname, O_WrOnly);   // prüfen auf erstellt
      finally
        FpClose(fhnd);
      end;
      if fhnd > 0 then   // wenn erfolgreich, raus
        break;
      sleep(5);
    end;
  end;
  result := fhnd;
end;


Das geht vielleicht auch noch eleganter...

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

Re: Unterschiede AssignFile und fpOpen?

Beitrag von Mathias »

Ich denke, über /dev... geht es effizienter.
Ich habe da eine Ausschnitt aus C++.
http://raspberrypi.stackexchange.com/qu ... -rpi/55601

Code: Alles auswählen

fd = open("/dev/gpiomem", O_RDWR | O_SYNC) ;


Allerdings habe ich festgestellt, dass das Aktivieren eines GPIO mit "export" durchaus 50msec dauern kann, bis der GPIO zur Verfügung steht, also man Direction und Value setzen kann:

Ein LED-Cube wird man so kaum ansteuern können,

Was sicher noch recht Zeit braucht, ist das man bei jedem Zugriff ein Open und Close hat.

Ob der Raspi überhaupt schnellen GPIO-Zugriff hat kann ich nicht sagen.
Den Versuch den ich mal mit I²C gemacht habe, war einiges langsamer, als ein Arduino, 8)
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten