A long time ago in a galaxy far, far away...
Par Fred le mercredi 20 avril 2011, 11:21 - Développement - Lien permanent
Dans un épisode précédent (ici en fait), je vous avais fait un coup de teasing sur les ports d'entrées-sorties de ma mini-carte EBX.
Tel un Georges Lucas qui met vingt ans à sortir la première trilogie, voilà, au bout de presqu'un an et demi, l'article promis.
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