Hardware Access/sk

From Free Pascal wiki
Jump to navigationJump to search

Deutsch (de) English (en) español (es) français (fr) magyar (hu) 日本語 (ja) 한국어 (ko) polski (pl) português (pt) русский (ru) slovenčina (sk) 中文(中国大陆)‎ (zh_CN)

O čom je článok

Táto stránka je začiatkom tutoriálu venovanom prístupe k hardwarovým zariadeniam v Lazare. Medzi tieto zariadenia patria (ale nie sú jediné): ISA, PCI, paralelný sériový port.

Platformovo nezávislý prístup k zariadeniam nie je implementovaný ani freepascalovskou RTL (Runtime Library) ani LCL, takže tento článok sa venuje metódam prístupu k hardvérovým zariadeniam na rozličných platformách. Zdrojový kód však môže byť pri používaní podmienenej kompilácie preložený na rozličných systémoch. Príklad podmienenej kompilácie:

uses
 Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
{$IFDEF WIN32}
  Windows;
{$ENDIF}
{$IFDEF Linux}
  ports;
{$ENDIF}

Pomoc je vítaná, hlavne pre MacOS.

Používanie inpout32.dll na Windows

Windows používa rozličné spôsoby prístupu k hardvérovým zariadeniam na systémoch skupiny 9x a iný v skupine NT. Toto môže pôsobiť skutočne problematicky. Windows 9x (95, 98, Me) umožňujú programovať pristupovať na porty priamo, podobne ako to bolo v DOSe. Avšak Windows NT už toto vôbec nedovolí a k portom treba pristupovať cez ovládače zariadení. Je to bezpečnostný mechanizmus, ale môže byť dosť otravné, keď je ovládač zariadenia príliš komplexný pre malý projket, ktorý potrebuje pristupovať k paralelnému portu.

Našťastie existuje knižnica, ktorá v sebe nesie ovládače zariadení. Ak detekuje Windows z rodiny NT, dekomprimuje ovládač a nainštaluje pre jadro ovládač Hwinterface.sys. Keď zdetekuje Windows rodiny 9x, jednoducho použije na prístup k zariadeniam assembler.

A ako používať knižnicu? jednoducho! Pozná iba dve funkcie: Inp32 a Out32. Ich použitie je celkom intuitívne.

Knižnicu budeme načítavať dynamicky, takže najskôr potrebujeme definovať obe funkcie:

type
  TInp32 = function(Address: ShortInt): ShortInt; stdcall;
  TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;

  • Address reprezentuje adresu portu, ku ktorému chcete pristupovať.
  • Out32 odosiela dáta špecifikované v Data na port určený v Address.
  • Inp32 vracia jeden bajt z portu, ktorý ste zadali.

Teraz môžeme načítať knižnicu. Môžete to implementovať napríklad v metóde OnCreate vášho hlavného formulára.

type
  TMyForm = class(TForm)
  .........
  private
    { private declarations }
    Inpout32: THandle;
    Inp32: TInp32;
    Out32: TOut32;
  .........
implementation
  .........
procedure TMyForm.FormCreate(Sender: TObject);
begin
{$IFDEF WIN32}
  Inpout32 := LoadLibrary('inpout32.dll');
  if (Inpout32 <> 0) then
  begin
    @Inp32 := GetProcAddress(Inpout32, 'Inp32');
    if (@Inp32 = nil) then Caption := 'Error';
    @Out32 := GetProcAddress(Inpout32, 'Out32');
    if (@Out32 = nil) then Caption := 'Error';
  end
  else Caption := 'Error';
{$ENDIF}
end;

Ak ste knižnicu načítavali pri OnCreate, nezabudnite ju pri OnDestroy aj uvoľniť z pamäte:

procedure TMyForm.FormDestroy(Sender: TObject);
begin
{$IFDEF WIN32}
  FreeLibrary(Inpout32);
{$ENDIF}
end;

Toto je jednoduchý príklad, ako používať funkciu Inp32:

{$IFDEF WIN32}
  myLabel.Caption := IntToStr(Inp32($0220));
{$ENDIF}

Tento kód bol testovaný s vlastnou ISA kartou na porte $0220, Lazarom verzie 0.9.10 na Windows XP. Pre správny beh programu budete, samozrejme, potrebovať mať vo svojej uses klauzule uvedené "windows". Súbor "inpout.dll" by mal byť umiestnený v rovnakom adresári, ako vaša aplikácia.

Domovskú stránku knižnice nájdete tu: www.logix4u.net/inpout32.htm

Použitie ioperm na prístup k portom na Linuxe

Najlepší spôsob pristupovania k hardvéru na Linuxe vedie cez ovládače zariadení. Avšak, vďaka komplexnosti úloh spojených s vytváraním ovládača, bývajú rýchlejšie metódy občas veľmi užitočné.

Aby ste na LInuxe mohli používať unit "ports", váš program musí byť spustený s právami užívateľa root a pre nastavenie príslušných orpávnení prístupu k portom musí byť volaný IOPerm. Dokumentáciu vzťahujúcu sa k unitu "ports" môžete nájsť tu.

Prvá vec, ktorú musíte urobiť, je zlikovať váš program s glibc a zavolať IOPerm. Vo FreePascale existuje unit, ktorý dynamicky linkuje celé glibc; avšak sú s ním problémy, keď je používaný priamo aplikáciou. A linkovať staticky celú glibc knižnicu nie je veľmi dobrá myšlienka pre multiplatfomovú aplikáciu, pretože používanie platformovo špecifických riešení by malo byť minimálne.


{$IFDEF Linux}
function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
{$ENDIF}

  • "from" repezentuje prvý port, ktorý sa má sprístupniť, "num" je počet
  • portov, na ktoré sa ma pristupovať po prvom, takže ioperm($220, 8,
  • 1) sprístupní pre náš program všetky porty od $220 do $227 (vrátane oboch).

Po sprístupnení OIPerm môžete na porty pristupovať cez port[<adresa>].

{$IFDEF Linux}
  i := ioperm($220, 8, 1);
  port[$220] := $00;
  myLabel.Caption := 'ioperm: ' + IntToStr(i);
  i := Integer(port[$220]);
  myOtherLabel.Caption := 'response: ' + IntToStr(i);
{$ENDIF}

Tento kód bol testovaný s vlastnou ISA kartou na porte $0220, použijúc Lazarus 0.9.10 na systémoch Mandriva Linux 2005 a Damn Small Linux 1.5