[Ada/Asm] Accéder au port parallèle avec Ada sur Gnu/Linux (résolu)

Accéder au port parallèle avec Ada sur Gnu/Linux (résolu) [Ada/Asm] - Ada - Programmation

Marsh Posté le 12-11-2011 à 04:28:45    

Bonjour, je me doute bien que c'est possible, mais j'ai pas encore trouvé comment.
J'ai devant moi "Ingénierie du logiciel avec Ada" Traduction de Grady Booch.
Chapitre 17 on aborde le traitement d'exceptions et les fonctionnalités de bas niveau.
Même si je me plante dans l'architecture de ma machine, je lis page 391...
Et je copie à ma sauce.

Code :
  1. --------------------------------------------------------------------------------------------------------------------------------------------
  2. --                                                                                                                                        --
  3. --------------------------------------------------------------------------------------------------------------------------------------------
  4. -- Unit Name   : "Main"                                                                                                                   --
  5. -- Filename    : "main.adb"                                                                                                               --
  6. -- Author      : "jovalise"                                                                                                               --
  7. -- Date        : "Sat Nov 12 01:00:00 CET 2011"                                                                                           --
  8. -- Version     : "0"."0"."0"-"alpha"                                                                                                      --
  9. -- Description : ""                                                                                                                       --
  10. --                                                                                                                                        --
  11. --------------------------------------------------------------------------------------------------------------------------------------------
  12. with System;
  13. use System;
  14. procedure Main is
  15.  
  16.  
  17.   type Io_Port is
  18.      record
  19.         Data               : Integer range 0..255;
  20.         Busy               : Boolean;
  21.         Interrupt_Validity : Boolean;
  22.      end record;
  23.  
  24.   Mot : constant := 1*8;
  25.  
  26.   for Io_Port use
  27.      record at mod 2;
  28.      Data              at 0*Mot range 0..7;
  29.      Busy              at 1*Mot range 3..3;
  30.      Interrupt_Validity at 1*Mot range 7..7;
  31.      end record;
  32.  
  33.   LPT1_Data : Io_Port;
  34.   LPT1_Ctrl : Io_Port;
  35.   for LPT1_Data use at 16#378#;
  36.   for LPT1_Ctrl use at 16#37A#;
  37.  
  38. Begin
  39.  
  40.  
  41.   null;
  42. end Main;


Mais jamais, les ligne 35 et 36 ne passe au compilateur qui me dit :

void:Ada# gnatmake Sources/main -o Targets/main -gnat83
gcc-4.3 -c -ISources/ -gnat83 -I- Sources/main.adb
main.adb:35:25: expected private type "System.Address"
main.adb:35:25: found type universal integer
main.adb:36:25: expected private type "System.Address"
main.adb:36:25: found type universal integer
gnatmake: "Sources/main.adb" compilation error
void:Ada#


 
Mon issue est peut-être dans l'astuce pour passer un type address la ou j'ai mis un universal integer.
Sauriez vous comment s'y prendre ?
Merci pour votre aide.


Message édité par Profil supprimé le 15-11-2011 à 01:19:57
Reply

Marsh Posté le 12-11-2011 à 04:28:45   

Reply

Marsh Posté le 14-11-2011 à 11:38:16    

Bonjour je viens de trouver comment assigner mon adresse que je connais sous forme numérique ; En utilisant la fonction To_Address comme suit :

Code :
  1. for LPT1_Data use at System'To_Address(16#378#);
  2. for LPT1_Ctrl use at System'To_Address(16#37A#);


Reply

Marsh Posté le 14-11-2011 à 13:32:32    

Pour le moment je me tape que des Storage_Error.
 
Je tente également l'asm, avec ce code..
 

Code :
  1. --
  2.      Asm("mov %%al, 0" & LF & HT &
  3.          "mov %%dx,0x378" & LF & HT &
  4.          "out %%al, %%dx" & LF & HT);


 
Je voudrais écrire 0(zero) sur le port parallèle situé à l'adresse 0x378.
Mais je me tape encore un storage_error.
 
Mais la, faut que j'invoque Harko peut-être !


Message édité par Profil supprimé le 14-11-2011 à 14:25:34
Reply

Marsh Posté le 14-11-2011 à 17:42:13    

J'en suis là,  
 

Code :
  1. with Interfaces;
  2. use Interfaces;
  3. with System.Machine_Code;
  4. use System.Machine_Code;
  5. with Ada.Text_Io;
  6. procedure Main is
  7.  
  8.   use Ascii;
  9.  
  10.   LPT1     : Unsigned_16 := 16#0378#;
  11.   In_Value : Unsigned_8 := 255;
  12.   Out_Value : Unsigned_8 := 0;
  13. begin
  14.  
  15.   Asm("mov %2, %%al" & LF & HT &
  16.         "mov %1, %%dx" & LF & HT &
  17.         "out %%al, %%dx"  & LF & HT &
  18.         "mov %0, %%al",
  19.       Inputs  => (Unsigned_16'Asm_Input ("g", LPT1), Unsigned_8'Asm_Input ("b", In_Value)),
  20.       Outputs => Unsigned_8'Asm_Output ("=b", Out_Value));
  21.   delay 0.25;
  22.   Ada.Text_Io.Put_Line("Value = " & Unsigned_8'Image(Out_Value));
  23. end Main;


 
J'avais trouvé un code qui compilait et s'exécutait sans erreur mais sans avoir le résultat escompté, et je l'ai perdu.
Celui-ci lève une l'erreur Storage_Error, stack overflow (or erroneous memory access) au moment d'exécuter "out".

Reply

Marsh Posté le 14-11-2011 à 17:58:33    

Avec les permissions d'accès au port ça marche !.  [:nozdormu]

Reply

Marsh Posté le 14-11-2011 à 20:34:34    

Petit set de 4 fichiers qui vont bien...
 

Code :
  1. -- Provide parallel ports address on Compatible IBM PC
  2. package Pp is
  3.  
  4.   LP0 : constant := 16#0278#;
  5.   LP1 : constant := 16#0378#;
  6.   LP2 : constant := 16#03BC#;
  7.   type Message_Type is (Data, Status, Ctrl);
  8. end Pp;


 

Code :
  1. -- Provide Gnu/Linux basic function to obtain desired IO permissions.
  2. with Interfaces.C;
  3. use Interfaces;
  4. package Pp.Ioperm is
  5.  
  6.   function Ioperm(From : in C.Unsigned_Long;
  7.                   Num : in C.Unsigned_Long;
  8.                   Tuen_On : in C.Int) return C.Int;
  9.   pragma Import(C, Ioperm, "ioperm" );
  10.  
  11. end Pp.Ioperm;


 

Code :
  1. -- Provide tow basic function to read and write value to parallel port.
  2. with Interfaces;
  3. generic
  4.   LP : Interfaces.Unsigned_16;
  5. package Pp.Pp_Io is
  6.   use Interfaces;
  7.   procedure Put(Msg : in Message_Type; Value : in Unsigned_8);
  8.   procedure Get(Msg : in Message_Type; Value : out Unsigned_8);
  9. end Pp.Pp_Io;


 

Code :
  1. with System.Machine_Code;
  2. use System.Machine_Code;
  3. package body Pp.Pp_Io is
  4.  
  5.   use Interfaces, Ascii;
  6.  
  7.   procedure Put(Msg : in Message_Type; Value : in Unsigned_8) is
  8.  
  9.   begin
  10.      Asm("mov %1,   %%al" & LF & HT &
  11.            "mov %0,   %%dx" & LF & HT &
  12.            "out %%al, %%dx",
  13.          Inputs  => (Unsigned_16'Asm_Input ("g", LP+Message_Type'Pos(Msg)), Unsigned_8'Asm_Input ("a", Value)),
  14.          Volatile => True);
  15.   end Put;
  16.  
  17.   procedure Get(Msg : in Message_Type; Value : out Unsigned_8) is
  18.  
  19.   begin
  20.      Asm("mov %1,%%dx" & LF & HT &
  21.            "in %%dx,%%al" & LF & HT &
  22.            "mov %0, %%al",
  23.          Inputs  => (Unsigned_16'Asm_Input ("g", LP+Message_Type'Pos(Msg))),
  24.          Outputs => Unsigned_8'Asm_Output ("=a", Value),
  25.          Volatile => True);
  26.   end Get;
  27. end Pp.Pp_Io;


 
Et un programme de test :

Code :
  1. with Interfaces.C;
  2. use interfaces;
  3. with Text_Io, Ada.Integer_Text_Io;
  4. use Ada;
  5.  
  6. with Pp.Ioperm, Pp.Pp_Io;
  7. use Pp;
  8. procedure Pp_Test is
  9.  
  10.   package Lpt1 is new Pp.Pp_Io(Pp.LP1);
  11.  
  12.   Value : Unsigned_8 := 0;
  13.   Errno : C.Int := Pp.Ioperm.Ioperm(PP.LP1, 3, 1);
  14. begin
  15.   if C."/="(Errno, 0) then
  16.      raise Program_Error;
  17.   end if;
  18.   Lpt1.Put(Data, 128);
  19.   delay 3.0;
  20.   Lpt1.get(Data, Value);
  21.   Text_Io.Put("Value = " );
  22.   Integer_Text_Io.Put(integer(Value), Base => 16);
  23.   Text_Io.New_Line;
  24.   delay 3.0;
  25.   Lpt1.Put(Data, 0);
  26.   Lpt1.get(Data, Value);
  27.   Text_Io.Put("Value = " );
  28.   Integer_Text_Io.Put(integer(Value), Base => 16);
  29.   Text_Io.New_Line;
  30.   Errno := Pp.Ioperm.Ioperm(PP.LP1, 3, 0);
  31. end Pp_Test;


 
Edit, j'espère avoir apporté toute les correction qui s'imposaient.


Message édité par Profil supprimé le 14-11-2011 à 21:16:27
Reply

Marsh Posté le 14-11-2011 à 20:56:26    

Arff, j'ai pas fait gaffe à ce que j'avais fait en fait, et ... Pp-Pp_Io.Get ne fonctionne pas.
J'y retourne.
 
Je sais, mais bon, c'est la vie.

Reply

Marsh Posté le 14-11-2011 à 21:08:07    

Voila, c'est corrigé, dans les deux cas ici, pour put et get il faut spécifier True pour le paramètre Volatile de Asm.
Dans "get", on peut même biaiser %%al et utiliser in en écrivant directement dans la variable de sortie.


Message édité par Profil supprimé le 14-11-2011 à 21:08:52
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed