En fouillant sur mon PC à la recherche de place, notamment sur le système de fichiers Coda[1], j'ai retrouvé un petit fichier dans la rubrique Dev répondant au doux nom pas du tout énigmatique de gpio_test.adb.

Il s'agit du fameux programme de test des entrées-sorties de ma carte SBC-GXm tournant sous le système d'exploitation temps-réel MarteOs.

Mais tout de suite, le code !!

with MaRTE.HAL.IO; use Marte.HAL.IO;
 
 
 
procedure Gpio_Test is
 
 SIO_GPIO_START : constant := 16#0fc0#; --GPIO Register IO space
 
 SIO_PM_START : constant IO_Port := 16#0fc8#; --PM Registers next to GPIO
 
 SIO_INDEX : constant IO_Port := 16#2e#; --io address of the SIO index register
 
 SIO_DATA : constant IO_Port := 16#2f#; --io address of the SIO data register
 
 SIO_DEV_SEL : constant := 16#7#;
 
 SIO_DEV_ENB : constant := 16#30#;
 
 SIO_DEV_MSB : constant := 16#60#;
 
 SIO_DEV_LSB : constant := 16#61#;
 
 SIO_GP_DEV : constant := 16#7#;
 
 SIO_PM_DEV : constant := 16#8#;
 
 SIO_PM_BASE : constant := SIO_PM_START;
 
 
 
 SIO_PM_MSB : constant := 16#0f#; --(SIO_PM_BASE>>8);
 
 SIO_PM_LSB : constant := 16#C8#; --(SIO_PM_BASE&16#ff);
 
 SIO_PM_INDEX : constant IO_Port := (SIO_PM_BASE+0);
 
 SIO_PM_DATA : constant IO_Port := (SIO_PM_BASE+1);
 
 SIO_PM_FER2 : constant := 16#1#;
 
 SIO_PM_GP_EN: constant := 16#80#;
 
 
 
 SIO_GP_BASE : constant := SIO_GPIO_START;
 
 SIO_GP_MSB : constant := 16#0f#; -- (SIO_GP_BASE>>8);
 
 SIO_GP_LSB : constant := 16#C0#; --(SIO_GP_BASE&16#ff);
 
 
 
 -- GPIO Register Bank 0
 
 SIO_GP_DATA1 : constant IO_Port := SIO_GP_BASE;
 
 SIO_GP_DIR1 : constant IO_Port := SIO_GP_BASE+1;
 
 SIO_GP_OT1 : constant IO_Port := SIO_GP_BASE+2;
 
 SIO_GP_PUC1 : constant IO_Port := SIO_GP_BASE+3;
 
 
 
 SIO_GP_DATA2 : constant IO_Port := SIO_GP_BASE + 4;
 
 SIO_GP_DIR2 : constant IO_Port := SIO_GP_BASE+5;
 
 SIO_GP_OT2 : constant IO_Port := SIO_GP_BASE+6;
 
 SIO_GP_PUC2 : constant IO_Port := SIO_GP_BASE+7;
 
 
 
 -- GPIO Register Bank 1
 
 SIO_GP_LOCK1 : constant := SIO_GP_BASE;
 
 SIO_GP_I2O1 : constant := SIO_GP_BASE+2;
 
 
 
 GPIO10_MASK : constant := 1;
 
 GPIO20_MASK : constant := 1;
 
 
 
 GPIO_BANK_0 : constant := 0; -- mask of GPIO register bank 0 select bit in SIOC2
 
 GPIO_BANK_1 : constant := 16#80#; -- mask of GPIO register bank 1 select bit in SIOC2
 
 
 
 OFF : constant := 1; -- means a low on the GPIO which draws current
 
                      -- through the LED, thus lighting it
 
 ON : constant := 0;
 
 
 
 -- iopl(3);
 
 --
 
 --
 
 -- First, we have to initialize the 317 part to allow us access
 
 -- to the GPIO registers.
 
 --
 
 
 
begin
 
   outb_p(SIO_INDEX, SIO_DEV_SEL);
 
   outb_p(SIO_DATA, SIO_GP_DEV); -- Talk to GPIO regs.
 
 
 
   outb_p(SIO_INDEX, SIO_DEV_MSB);
 
 
 
   --   outb_p(SIO_DATA, SIO_GP_MSB); -- MSB of GPIO base address
 
   outb_p(SIO_DATA, SIO_GP_MSB); -- MSB of GPIO base address
 
 
 
   outb_p(SIO_INDEX, SIO_DEV_LSB);
 
   outb_p(SIO_DATA, SIO_GP_LSB); -- LSB of GPIO base address
 
   outb_p(SIO_INDEX, SIO_DEV_ENB);
 
   outb_p(SIO_DATA, 1); -- Enable GPIO registers.
 
 
 
   --
 
   -- Now, we have to map the power management section to write
 
   -- a bit which enables access to the GPIO registers.
 
   --
 
   outb(SIO_INDEX, SIO_DEV_SEL);
 
   outb(SIO_DATA, SIO_PM_DEV); -- Talk to GPIO regs.
 
   outb(SIO_INDEX, SIO_DEV_MSB);
 
   outb(SIO_DATA, SIO_PM_MSB); -- MSB of PM base address
 
   outb(SIO_INDEX, SIO_DEV_LSB);
 
   outb(SIO_DATA, SIO_PM_LSB); -- LSB of PM base address
 
   outb(SIO_INDEX, SIO_DEV_ENB);
 
   outb(SIO_DATA, 1); -- Enable PM registers.
 
 
 
   --
 
   -- Now, write the PM register which enables the GPIO registers.
 
   --
 
   outb(SIO_PM_INDEX, SIO_PM_FER2);
 
   outb(SIO_PM_DATA, SIO_PM_GP_EN);
 
   outb(SIO_GP_DIR2, GPIO20_MASK); -- set GPIO20 direction to output
 
   outb(SIO_GP_DATA2, OFF); -- initially turn the light OFF
 
 
 
   --------------------------------------
 
   -- To Blink:
 
 
 
   loop
 
      outb(SIO_GP_DATA2, ON);
 
      delay 1.0;
 
      --    usleep(20000);
 
      outb(SIO_GP_DATA2, OFF);
 
      delay 1.0;
 
      --    usleep(20000);
 
   end loop;
 
end Gpio_Test;


Balaise, non ?

Bon, j'avoue, je ne l'ai pas pondu seul mais je l'ai ressorti lors d'une exhumation webesque. L'original est codé en C et peut encore être trouvé sur cette page.

Par contre, la transcription en Ada, c'est de moi et d'ailleurs, il y aurait besoin de rechanger quelques constantes, notamment sur les opérations de décalage de bits que je n'ai pas transposées mais directement calculées rendant le code moins portable.

En tout cas, cela fonctionne et on peut tout à fait imaginer dériver un ''driver' de ce petit bout de code.

Au passage, je suis assez preneur de vos commentaires et remarques ;-)

Bonne lecture !

Notes

[1] Si vous ne savez pas ce que c'est, cherchez sur ce blog, ce ne sont pas les articles qui manquent