Changes between Version 13 and Version 14 of SujetTP3-2015


Ignore:
Timestamp:
Mar 5, 2015, 11:56:13 AM (10 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SujetTP3-2015

    v13 v14  
    204204== Étape 4 : accès aux GPIO depuis les fonctions du pilote ==
    205205
     206Pour vous aider, voici un code qui fait clignoter la LED du GPIO04 dans le module noyau.
     207* Pour l'accès aux GPIOs vous voyez que l'on peut simplifier les calculs d'adresses en utilisant une structure représentant l'organisation des registres.
     208* Vous noterez également que l'adresse physique de base des GPIO (ici 0x20200000) est mappé dans l'espace virtuel du noyau à l'adresse '''io_addresse'''.
     209* Vous trouvez aussi le moyen de faire faire périodiquement une fonction au système grâce à une file d'attente temporelle.
     210Inspirez-vous de code pour votre pilote.
     211
     212{{{
     213#include <linux/module.h>
     214#include <linux/init.h>
     215#include <asm/io.h>
     216#include <mach/platform.h>
     217
     218static const int LED0 = 4;
     219
     220//------------------------------------------------------------------------------
     221//                                GPIO ACCES
     222//------------------------------------------------------------------------------
     223
     224struct gpio_s
     225{
     226    uint32_t gpfsel[7];
     227    uint32_t gpset[3];
     228    uint32_t gpclr[3];
     229    uint32_t gplev[3];
     230    uint32_t gpeds[3];
     231    uint32_t gpren[3];
     232    uint32_t gpfen[3];
     233    uint32_t gphen[3];
     234    uint32_t gplen[3];
     235    uint32_t gparen[3];
     236    uint32_t gpafen[3];
     237    uint32_t gppud[1];
     238    uint32_t gppudclk[3];
     239    uint32_t test[1];
     240}
     241*gpio_regs = (struct gpio_s *)__io_address(GPIO_BASE);;
     242
     243enum {FUN_INPUT, FUN_OUTPUT};
     244
     245static void gpio_fsel(int pin, int fun)
     246{
     247    uint32_t reg = pin / 10;
     248    uint32_t bit = (pin % 10) * 3;
     249    uint32_t mask = 0b111 << bit;
     250    gpio_regs->gpfsel[reg] = (gpio_regs->gpfsel[reg] & ~mask) | ((fun << bit) & mask);
     251}
     252
     253static void gpio_write(int pin, bool val)
     254{
     255    if (val)
     256        gpio_regs->gpset[pin / 32] = (1 << (pin % 32));
     257    else
     258        gpio_regs->gpclr[pin / 32] = (1 << (pin % 32));
     259}
     260
     261//------------------------------------------------------------------------------
     262//                             TIMER PROGRAMMING
     263//------------------------------------------------------------------------------
     264
     265static struct timer_list led_blink_timer;
     266static int led_blink_period = 1000;
     267
     268static void led_blink_handler(unsigned long unused)
     269{
     270    static bool on = false;
     271    on = !on;
     272    gpio_write(LED0, on);
     273    mod_timer(&led_blink_timer, jiffies + msecs_to_jiffies(led_blink_period));
     274}
     275
     276//------------------------------------------------------------------------------
     277//                              MODULE INIT & EXIT
     278//------------------------------------------------------------------------------
     279
     280MODULE_LICENSE("GPL");
     281MODULE_AUTHOR("Franck from http://sysprogs.com/VisualKernel/tutorials/raspberry/leddriver/)");
     282MODULE_DESCRIPTION("leds on-off");
     283 
     284static int __init LedBlinkModule_init(void)
     285{
     286    int result;
     287
     288    gpio_fsel(LED0, FUN_OUTPUT);
     289    gpio_write(LED0, 1);
     290    setup_timer(&led_blink_timer, led_blink_handler, 0);
     291    result = mod_timer(&led_blink_timer, jiffies + msecs_to_jiffies(led_blink_period));
     292    BUG_ON(result < 0);
     293    return 0;
     294}
     295
     296static void __exit LedBlinkModule_exit(void)
     297{
     298    gpio_fsel(LED0, FUN_INPUT);
     299    del_timer(&led_blink_timer);
     300}
     301
     302module_init(LedBlinkModule_init);
     303module_exit(LedBlinkModule_exit);
     304
     305}}}