Difference between revisions of "Hardware Access/pt"

From Lazarus wiki
Jump to navigationJump to search
 
m (Fixed syntax highlighting)
 
(10 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
{{Hardware Access}}
 
__TOC__
 
__TOC__
 
==Visão Geral==
 
==Visão Geral==
Está página é o começo de um tutorial sobre acesso a dispositivos de hardware por programas desenvolvidos no Lazarus. Estes dispositivos incluem, porem não estão limitados a: Placas ISA e PCI, as portas paralela e serial e USB.
+
Está página é o inicio de um tutorial sobre acesso a dispositivos de hardware no Lazarus. Estes dispositivos incluem, mas não se limitam a: Placas ISA e PCI, as portas paralela e serial e USB.
  
O acesso ao hardware de uma maneira completamente multi-plataforma não é implementada pela biblioteca RunTime do Free Pascal ou pela LCL, assim este tutorial cobre metodos diferentes para diferentes plataformas. O código pode ser compilado em ambientes diferentes utilizando a compilação condicional. Abaixo segue um exemplo disto:
+
Acessar o hardware de uma maneira completamente multi-plataforma não é implementada pela biblioteca RunTime do Free Pascal ou pela LCL, assim este tutorial cobre métodos diferentes para diferentes plataformas. O código pode ser compilado em ambientes diferentes utilizando compilação condicional. Abaixo segue um exemplo disso:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  uses
 
  uses
 
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
 
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Line 14: Line 15:
 
   ports;
 
   ports;
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
  
Quem desejar pode contribuir para este documento.
+
Não se sabe ainda, até esse momento, se Mac OS x/x86 permitirá acesso HW. Ele pode não permitir isso, embora eu assuma neste caso , em tempo, que drivers como io.dll aparecerão.
  
==Utilizando a inpout32.dll para Windows==
+
==Comparação entre Paralelo e Serial==
No Windows diferentes metodos para acessar dispositivos de hardware na série 9x e na série NT, o que pode gerar muitos problemas. A série 9x (95, 98, Me) permite que os programas acessem as portas diretamente, da mesma maneira que éra feita no DOS. A série NT, porém, não permite isto e todos acesso as portas deve ser feito através de Device Drivers. Isto é mecanismo de segurança, mas pode complicar o desenvolvimento de aplicativos pequenos que apenas precisam acessar uma determinada porta.
+
Placas ISA, Placas PCI e a Porta Paralela comunicam-se com o computador utilizando um protocolo de comunição '''paralela'''. A Porta Serial e dispositivos USB trabalham com um protocolo '''serial'''. Como o processando e, consequentemente, as linguagens de programação trabalham com uma abordagem paralela aos dados, esse tipo de acesso é mais fácil de ser implementado no lado do software. Ao acessar uma variável do tipo inteiro, por exemplo, você pode acessar seu conteúdo inteiro com um único comando. Com o protocolo serial apenas um bit é enviado de cada vez e é preciso juntá-los para depois poder compreender os dados.
 +
 
 +
A Comunicação serial é difícil de ser implementada diretamente, mas pode ser muito fácil se utilizarmos um componente pronto. Ela também é mais difícil no lado do hardware, logo muitos dispositivos utilizam Circuitos Integrados especialmente desenvolvidos ou até microcontroladores para implementar o protocolo serial.
 +
 
 +
Agora uma breve comparação dos protocolos de comunicação:
 +
 
 +
{| border=2 width="100%"
 +
 
 +
|-
 +
!
 +
! Velocidade
 +
! Dificuldade de implementação do hardware
 +
 
 +
|-
 +
! Porta Serial
 +
| align="center" | Muito lenta (< E5 bit/s)
 +
| align="center" | Média
 +
 
 +
|-
 +
! Porta Paralela
 +
| align="center" | Lenta (~ E6 bit/s)
 +
| align="center" | Fácil
 +
 
 +
|-
 +
 
 +
! Placa ISA
 +
| align="center" | Média (~ E7 bit/s)
 +
| align="center" | Média
 +
 
 +
|-
 +
! USB
 +
| align="center" | Média (~ E7 bit/s)
 +
| align="center" | Difícil
 +
 
 +
|-
 +
! Placa PCI
 +
| align="center" | Muito Rápida (> E9 bit/s)
 +
| align="center" | Muito difícil
 +
 
 +
|}
 +
 
 +
==Comunicação Paralela==
 +
 
 +
===Utilizando a inpout32.dll para Windows===
 +
O Windows tem diferentes formas para acessar dispositivos de hardware na série 9x e na série NT. A série 9x (95, 98, Me) os programas podem acessar as portas diretamente, da mesma maneira que era feito no DOS. A série NT, porém, não permite isto e todos acesso as portas devem ser feitos através de Dispositivos Drivers. Isto é um  mecanismo de segurança, mas pode complicar o desenvolvimento de aplicativos pequenos que apenas precisam acessar uma determinada porta.
  
 
Felizmente existe uma biblioteca que carrega dentro de si um driver. Quando ela é chamada para acessar uma determinada porta ela detecta se o Windows em operação é da série NT e, em caso afirmativo, descomprime o driver Hwinterface.sys e o instala no kernel. Se a série 9x for detectada ele simplesmente utiliza instruções de assembler para acessar o hardware.
 
Felizmente existe uma biblioteca que carrega dentro de si um driver. Quando ela é chamada para acessar uma determinada porta ela detecta se o Windows em operação é da série NT e, em caso afirmativo, descomprime o driver Hwinterface.sys e o instala no kernel. Se a série 9x for detectada ele simplesmente utiliza instruções de assembler para acessar o hardware.
Line 27: Line 72:
 
Nós estaremos carregando a biblioteca dinamicamente, então é bom definir as funções antes:
 
Nós estaremos carregando a biblioteca dinamicamente, então é bom definir as funções antes:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  type
 
  type
 
   TInp32 = function(Address: ShortInt): ShortInt; stdcall;
 
   TInp32 = function(Address: ShortInt): ShortInt; stdcall;
 
   TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;
 
   TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;
</code>
+
</syntaxhighlight>
  
* Address representa o endereço da porta a ser acessada. Out32 envida Dados para a porta. Inp32 returna um byte da porta no Address.
+
* Address representa o endereço da porta a ser acessada.  
 +
* Out32 envida Dados para a porta.  
 +
* Inp32 returna um byte da porta no Address.
  
 
Agora podemos carregar a biblioteca. Isto pode ser implementado num lugar como o evento OnCreate do seu formulário principal:
 
Agora podemos carregar a biblioteca. Isto pode ser implementado num lugar como o evento OnCreate do seu formulário principal:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  type
 
  type
 
   TMyForm = class(TForm)
 
   TMyForm = class(TForm)
Line 63: Line 110:
 
  {$ENDIF}
 
  {$ENDIF}
 
  end;
 
  end;
</code>
+
</syntaxhighlight>
  
 
Se você carregar a biblioteca no evento OnCreate não esqueça de descarrega-la no evento OnDestroy:
 
Se você carregar a biblioteca no evento OnCreate não esqueça de descarrega-la no evento OnDestroy:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  procedure TMyForm.FormDestroy(Sender: TObject);
 
  procedure TMyForm.FormDestroy(Sender: TObject);
 
  begin
 
  begin
Line 74: Line 121:
 
  {$ENDIF}
 
  {$ENDIF}
 
  end;
 
  end;
</code>
+
</syntaxhighlight>
  
 
Aqui está um exemplo de uso da função Inp32:
 
Aqui está um exemplo de uso da função Inp32:
  
<code>
+
<syntaxhighlight lang=pascal>
 
  {$IFDEF WIN32}
 
  {$IFDEF WIN32}
 
   myLabel.Caption := IntToStr(Inp32($0220));
 
   myLabel.Caption := IntToStr(Inp32($0220));
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
 +
 
 +
Este código foi testado com uma placa ISA própria na porta$0220, utilizando o Lazarus 0.9.10 no Windows XP. Obviamente é necessário possuir a unidade Windows na cláusula "uses" para que este código possa funcionar. Para distribuir um aplicativo que utilize a biblioteca você precisa apenas incluir a "inpout32.dll" no mesmo diretório do executável.
 +
 
 +
Está é a página principal da biblioteca: [http://www.logix4u.net/inpout32.htm www.logix4u.net/inpout32.htm]
 +
 
 +
===Usando assembler no Windows 9x===
 +
 
 +
No Windows 9x você pode também utilizar código assembler. Supondo que você deseja escrever em $CC para a portal $320. O seguinte código fará isso:
  
This code was tested with a custom ISA card on port $0220, using Lazarus 0.9.10 on Windows XP. Of course you will need to have Windows on your uses clause in order for this code to run. For deployment you only need to include "inpout32.dll" in the same directory of our application.
+
<syntaxhighlight lang=pascal>
 +
{$ASMMODE ATT}
 +
...
 +
    asm
 +
        movl $0x320, %edx
 +
        movb $0xCC, %al
 +
        outb %al, %dx
 +
    end ['EAX','EDX'];
 +
</syntaxhighlight>
  
This is the homepage for the library: [http://www.logix4u.net/inpout32.htm www.logix4u.net/inpout32.htm]
+
===Troubleshooting no Windows===
  
==Using ioperm to access ports on Linux==
+
Uma possível fonte de confusão usando hardware paralelo que não suporta Plug and Play no Windows é que o Windows pode associar a porta utilizada pelo seu hardware para outro dispositivo. Você pode procurar instruções na URL a seguir sobre como falar para o Windows não associar o endereço de seu dispositivo para dispositivos Plug And Play:
  
The best way to access the hardware on Linux is throught device drivers, but, due to the complexity of the task of creating a driver, sometimes a quick method is very useful.
+
http://support.microsoft.com/kb/135168
  
In order to use the "ports" unit under linux your program must be run as root, and IOPerm must be called to set appropriate permissions on the port access. You can find documentation about the "ports" unit [http://www.freepascal.org/docs-html/rtl/ports/index.html here].
+
===Utilizando ioperm para acessar portas no Linux===
  
The first thing to do is link to glibc and call IOPerm. A unit that links to the entire glibc exists on free pascal, but this unit gives problems when used directly by application and linking statically to the entire glibc library is not a very good idea for a multi-platform application. The use of platform-specific functions should be kept to a minimum.
+
A melhor maneira de acessar dispositivos de hardware no Linux é através de drivers, mas, devido a complexidade envolvida na criação de um, às vezes um método mais simples é muito útil.
  
<code>
+
Para utilizar a unidade "[[doc:rtl/ports|ports]]" no Linux, seu programa deve ser executado como super-usuário (ex: root) e a função IOPerm deve ser chamada para definir as permissões de acesso as portas. Você pode encontrar documentação sobre a unidade "[[doc:rtl/ports|ports]]" [http://www.freepascal.org/docs-html/rtl/ports/index.html aqui].
 +
 
 +
A primeira coisa a ser feita é estabelecer um vínculo com o (g)libc e chamar a função IOPerm. Uma unidade que estabelece vínculos para todo o (g)libc existe no Free Pascal, mas ela causa problemas quando é utilizada diretamente pela aplicação e vinculação estática, além do que não é uma boa idéia porque ela mudança frequentemente entre versões em uma incompatível maneira. Funções como ioperm, entretanto, são improváveis de serem modificadas.
 +
 
 +
<syntaxhighlight lang=pascal>
 
  {$IFDEF Linux}
 
  {$IFDEF Linux}
 
  function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 
  function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
  
* "from" represents the first port to be accessed.
+
* "from" representa a primeira porta a ser acessada.
* "num" is the number of ports after the first to be accessed, so ioperm($220, 8, 1) will give access for the program for all ports between and including $220 and $227.
+
* "num" é o número de portas após a primeira a serem acessadas, assim ioperm($220, 8, 1) dará ao programa acesso a todos portas entre e incluindo $220 e $227.
  
After linking to OIPerm you can port[<Address>] to access the ports.
+
Após vincular OIPerm você pode utilizar port[<Endereço>] para acessar as portas.
  
<code>
+
<syntaxhighlight lang=pascal>
 
  {$IFDEF Linux}
 
  {$IFDEF Linux}
 
   i := ioperm($220, 8, 1);
 
   i := ioperm($220, 8, 1);
Line 113: Line 180:
 
   myLabel.Caption := 'ioperm: ' + IntToStr(i);
 
   myLabel.Caption := 'ioperm: ' + IntToStr(i);
 
   i := Integer(port[$220]);
 
   i := Integer(port[$220]);
   myOtherLabel.Caption := 'response: ' + IntToStr(i);
+
   myOtherLabel.Caption := 'resposta: ' + IntToStr(i);
 
  {$ENDIF}
 
  {$ENDIF}
</code>
+
</syntaxhighlight>
 +
 
 +
Este código for testado com uma placa ISA própria na porta $0220, utilizando o Lazarus 0.9.10 no Mandriva Linux 2005 e no Damn Small Linux 1.5.
 +
 
 +
===Acesso geral ao Hardware UNIX===
 +
 
 +
<syntaxhighlight lang=pascal>
 +
{$IFDEF Unix}
 +
Uses Clib;  // recupera o nome da biblioteca libc.
 +
{$ENDIF}
 +
 
 +
{$IFDEF Unix}
 +
function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib;
 +
{$ENDIF}
 +
</syntaxhighlight>
 +
 
 +
 
 +
'''Nota''' Note que o FPC fornece uma abstração para ioperm chamada "fpioperm" na [[doc:rtl/x86/index.html|unit x86]], e também define funções out e inport. Essas funções atualmente são implementadas por Linux/x86 e FreeBSD/x86.
 +
 
 +
Não é recomendado vincular libc a menos que seja absolutamente necessário para possibilitar o desenvolvimento e portabilidades das funções.
 +
Também a vinculação manual da libc (declarando importações pontuais libc para funções que estão disponíveis noutros países) como feito anteriormente não é recomendado (ex: a importação libc na linha acima irá falhar se, desnecessariamente, o padrão lib C não é chamado libc, como por exemplo libroot no BeOS, ou em plataformas com  simbolos não-padrão C estragados).
 +
 
 +
'''Nota 2''' Usar _unit_ libc não é recomendado sob quaisquer outras cirscunstâncias do que a compatibilidade com Kylix. Isso porque a unit é relativamente não-portável (garanta a exposição das estruturas e outros símbolos privados) e deve ser modificada tão pouco quanto possível fora das questões de compatibilidades com Kylix.
 +
 
 +
==Comunicação Serial==
 +
 
 +
A seção de [[Hardware Access/pt#External Links | Links Externos]] tem tutoriais de portas seriais UNIX e Windows.
 +
 
 +
==USB==
 +
 
 +
===libusb===
 +
 
 +
Uma possibilidade multi-plataforma para Linux, BSDs e Mac OS X é a [http://libusb.sourceforge.net/ libusb].
 +
 
 +
Os cabeçalhos estão listado em http://www.freepascal.org/contrib/db.php3?category=Miscellaneous:
 +
 
 +
{|cellpadding="4"
 +
|-
 +
! nome !! autor !! versão !! data !! link !! comentários
 +
|-
 +
| libusb.pp || nowrap | Uwe Zimmermann || 0.1.12 || nowrap | 2006-06-29 || http://www.sciencetronics.com/download/fpc_libusb.tgz ||
 +
|-
 +
| libusb.pas || Johann Glaser ||  || nowrap | 2005-01-14 || http://www.johann-glaser.at/projects/libusb.pas ||
 +
|-
 +
| fpcusb || Joe Jared || 0.11-14 || nowrap | 2006-02-02 || http://relays.osirusoft.com/fpcusb.tgz || nowrap | link download quebrado
 +
|}
 +
 
 +
===FTDI===
 +
 
 +
Se você usa um dos chips da [http://www.ftdichip.com/ FTDI], você pode os cabeçalhos pascal da sua interface de dll para o chip.
 +
 
 +
==Links Externos==
 +
 
 +
Comparação de velocidade de Protocolos de Comunicação
 +
 
 +
# http://en.wikipedia.org/wiki/Serial_port#Speed
 +
# http://www.lvr.com/jansfaq.htm - Jan Axelson's Parallel Port FAQ
 +
# http://en.wikipedia.org/wiki/USB#Transfer_Speed
 +
# http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications
 +
 
 +
Links de Comunicação Serial:
 +
 
 +
# Em UNIX: [http://www.easysw.com/~mike/serial/serial.html]
 +
# Em Windows: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
 +
# Componente Synaser: http://synapse.ararat.cz/
 +
# Pacote Delphi Comport: http://sourceforge.net/projects/comport/
 +
 
 +
ISA Digital Oscilloscope - Um exemplo de acesso ao hardware com fonte completo incluso:
  
This code was tested with a custom ISA card on port $0220, using Lazarus 0.9.10 on Mandriva Linux 2005 and Damn Small Linux 1.5
+
[http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/]

Latest revision as of 12:21, 16 February 2020

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)

Visão Geral

Está página é o inicio de um tutorial sobre acesso a dispositivos de hardware no Lazarus. Estes dispositivos incluem, mas não se limitam a: Placas ISA e PCI, as portas paralela e serial e USB.

Acessar o hardware de uma maneira completamente multi-plataforma não é implementada pela biblioteca RunTime do Free Pascal ou pela LCL, assim este tutorial cobre métodos diferentes para diferentes plataformas. O código pode ser compilado em ambientes diferentes utilizando compilação condicional. Abaixo segue um exemplo disso:

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

Não se sabe ainda, até esse momento, se Mac OS x/x86 permitirá acesso HW. Ele pode não permitir isso, embora eu assuma neste caso , em tempo, que drivers como io.dll aparecerão.

Comparação entre Paralelo e Serial

Placas ISA, Placas PCI e a Porta Paralela comunicam-se com o computador utilizando um protocolo de comunição paralela. A Porta Serial e dispositivos USB trabalham com um protocolo serial. Como o processando e, consequentemente, as linguagens de programação trabalham com uma abordagem paralela aos dados, esse tipo de acesso é mais fácil de ser implementado no lado do software. Ao acessar uma variável do tipo inteiro, por exemplo, você pode acessar seu conteúdo inteiro com um único comando. Com o protocolo serial apenas um bit é enviado de cada vez e é preciso juntá-los para depois poder compreender os dados.

A Comunicação serial é difícil de ser implementada diretamente, mas pode ser muito fácil se utilizarmos um componente pronto. Ela também é mais difícil no lado do hardware, logo muitos dispositivos utilizam Circuitos Integrados especialmente desenvolvidos ou até microcontroladores para implementar o protocolo serial.

Agora uma breve comparação dos protocolos de comunicação:

Velocidade Dificuldade de implementação do hardware
Porta Serial Muito lenta (< E5 bit/s) Média
Porta Paralela Lenta (~ E6 bit/s) Fácil
Placa ISA Média (~ E7 bit/s) Média
USB Média (~ E7 bit/s) Difícil
Placa PCI Muito Rápida (> E9 bit/s) Muito difícil

Comunicação Paralela

Utilizando a inpout32.dll para Windows

O Windows tem diferentes formas para acessar dispositivos de hardware na série 9x e na série NT. A série 9x (95, 98, Me) os programas podem acessar as portas diretamente, da mesma maneira que era feito no DOS. A série NT, porém, não permite isto e todos acesso as portas devem ser feitos através de Dispositivos Drivers. Isto é um mecanismo de segurança, mas pode complicar o desenvolvimento de aplicativos pequenos que apenas precisam acessar uma determinada porta.

Felizmente existe uma biblioteca que carrega dentro de si um driver. Quando ela é chamada para acessar uma determinada porta ela detecta se o Windows em operação é da série NT e, em caso afirmativo, descomprime o driver Hwinterface.sys e o instala no kernel. Se a série 9x for detectada ele simplesmente utiliza instruções de assembler para acessar o hardware.

Mas como utilizar a biblioteca? Simples! Ela possuí apenas duas funções, Inp32 e Out32, e seu uso é bastante intuitivo.

Nós estaremos carregando a biblioteca dinamicamente, então é bom definir as funções antes:

 type
   TInp32 = function(Address: ShortInt): ShortInt; stdcall;
   TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;
  • Address representa o endereço da porta a ser acessada.
  • Out32 envida Dados para a porta.
  • Inp32 returna um byte da porta no Address.

Agora podemos carregar a biblioteca. Isto pode ser implementado num lugar como o evento OnCreate do seu formulário principal:

 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;

Se você carregar a biblioteca no evento OnCreate não esqueça de descarrega-la no evento OnDestroy:

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

Aqui está um exemplo de uso da função Inp32:

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

Este código foi testado com uma placa ISA própria na porta$0220, utilizando o Lazarus 0.9.10 no Windows XP. Obviamente é necessário possuir a unidade Windows na cláusula "uses" para que este código possa funcionar. Para distribuir um aplicativo que utilize a biblioteca você precisa apenas incluir a "inpout32.dll" no mesmo diretório do executável.

Está é a página principal da biblioteca: www.logix4u.net/inpout32.htm

Usando assembler no Windows 9x

No Windows 9x você pode também utilizar código assembler. Supondo que você deseja escrever em $CC para a portal $320. O seguinte código fará isso:

 {$ASMMODE ATT}
 ...
    asm
        movl $0x320, %edx
        movb $0xCC, %al
        outb %al, %dx
    end ['EAX','EDX'];

Troubleshooting no Windows

Uma possível fonte de confusão usando hardware paralelo que não suporta Plug and Play no Windows é que o Windows pode associar a porta utilizada pelo seu hardware para outro dispositivo. Você pode procurar instruções na URL a seguir sobre como falar para o Windows não associar o endereço de seu dispositivo para dispositivos Plug And Play:

http://support.microsoft.com/kb/135168

Utilizando ioperm para acessar portas no Linux

A melhor maneira de acessar dispositivos de hardware no Linux é através de drivers, mas, devido a complexidade envolvida na criação de um, às vezes um método mais simples é muito útil.

Para utilizar a unidade "ports" no Linux, seu programa deve ser executado como super-usuário (ex: root) e a função IOPerm deve ser chamada para definir as permissões de acesso as portas. Você pode encontrar documentação sobre a unidade "ports" aqui.

A primeira coisa a ser feita é estabelecer um vínculo com o (g)libc e chamar a função IOPerm. Uma unidade que estabelece vínculos para todo o (g)libc existe no Free Pascal, mas ela causa problemas quando é utilizada diretamente pela aplicação e vinculação estática, além do que não é uma boa idéia porque ela mudança frequentemente entre versões em uma incompatível maneira. Funções como ioperm, entretanto, são improváveis de serem modificadas.

 {$IFDEF Linux}
 function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
 {$ENDIF}
  • "from" representa a primeira porta a ser acessada.
  • "num" é o número de portas após a primeira a serem acessadas, assim ioperm($220, 8, 1) dará ao programa acesso a todos portas entre e incluindo $220 e $227.

Após vincular OIPerm você pode utilizar port[<Endereço>] para acessar as portas.

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

Este código for testado com uma placa ISA própria na porta $0220, utilizando o Lazarus 0.9.10 no Mandriva Linux 2005 e no Damn Small Linux 1.5.

Acesso geral ao Hardware UNIX

{$IFDEF Unix}
Uses Clib;   // recupera o nome da biblioteca libc.
{$ENDIF}

{$IFDEF Unix}
function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib;
{$ENDIF}


Nota Note que o FPC fornece uma abstração para ioperm chamada "fpioperm" na unit x86, e também define funções out e inport. Essas funções atualmente são implementadas por Linux/x86 e FreeBSD/x86.

Não é recomendado vincular libc a menos que seja absolutamente necessário para possibilitar o desenvolvimento e portabilidades das funções. Também a vinculação manual da libc (declarando importações pontuais libc para funções que estão disponíveis noutros países) como feito anteriormente não é recomendado (ex: a importação libc na linha acima irá falhar se, desnecessariamente, o padrão lib C não é chamado libc, como por exemplo libroot no BeOS, ou em plataformas com simbolos não-padrão C estragados).

Nota 2 Usar _unit_ libc não é recomendado sob quaisquer outras cirscunstâncias do que a compatibilidade com Kylix. Isso porque a unit é relativamente não-portável (garanta a exposição das estruturas e outros símbolos privados) e deve ser modificada tão pouco quanto possível fora das questões de compatibilidades com Kylix.

Comunicação Serial

A seção de Links Externos tem tutoriais de portas seriais UNIX e Windows.

USB

libusb

Uma possibilidade multi-plataforma para Linux, BSDs e Mac OS X é a libusb.

Os cabeçalhos estão listado em http://www.freepascal.org/contrib/db.php3?category=Miscellaneous:

nome autor versão data link comentários
libusb.pp Uwe Zimmermann 0.1.12 2006-06-29 http://www.sciencetronics.com/download/fpc_libusb.tgz
libusb.pas Johann Glaser 2005-01-14 http://www.johann-glaser.at/projects/libusb.pas
fpcusb Joe Jared 0.11-14 2006-02-02 http://relays.osirusoft.com/fpcusb.tgz link download quebrado

FTDI

Se você usa um dos chips da FTDI, você pode os cabeçalhos pascal da sua interface de dll para o chip.

Links Externos

Comparação de velocidade de Protocolos de Comunicação

  1. http://en.wikipedia.org/wiki/Serial_port#Speed
  2. http://www.lvr.com/jansfaq.htm - Jan Axelson's Parallel Port FAQ
  3. http://en.wikipedia.org/wiki/USB#Transfer_Speed
  4. http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications

Links de Comunicação Serial:

  1. Em UNIX: [1]
  2. Em Windows: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp
  3. Componente Synaser: http://synapse.ararat.cz/
  4. Pacote Delphi Comport: http://sourceforge.net/projects/comport/

ISA Digital Oscilloscope - Um exemplo de acesso ao hardware com fonte completo incluso:

[2]