Changes between Version 1 and Version 2 of Peri19_T03


Ignore:
Timestamp:
Mar 1, 2019, 12:54:19 PM (6 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Peri19_T03

    v1 v2  
    6969
    7070**Références**
    71 * Vous trouvez pas mal d'informations sur google, mais si vous voulez allez plus loin il faut lire des livres tel que : [http://www.xml.com/ldd/chapter/book/ Linux Device Drivers, 2nd Edition]
     71* Vous trouverez pas mal d'informations sur internet :
     72  - [http://doc.ubuntu-fr.org/tutoriel/tout_savoir_sur_les_modules_linux]
     73  - [http://pficheux.free.fr/articles/lmf/drivers/]
     74  - [https://broux.developpez.com/articles/c/driver-c-linux/]
     75* si vous voulez allez plus loin, il y a le livre :
     76  - [http://www.xml.com/ldd/chapter/book/ Linux Device Drivers, 2nd Edition]
    7277
    7378
     
    119124* Sur votre PC, vous allez commencer par regarder si le répertoire `/dsk/l1/misc/linux-rpi-3.18.y` existe avec \\`ls -d /dsk/l1/misc/linux-rpi-3.18.y`. \\**s'il existe**, c'est bon, il n'y a rien à faire.\\**s'il n'existe pas** vous allez le créer :
    120125  * en téléchargeant l'archive [[htdocs:linux-rpi-3.18.y.tbz2]]  (192Mb) **dans le répertoire** `/dsk/l1/misc`
    121   * puis en la décompressant \\`tar xvjf /dsk/l1/misc/linux-rpi-3.18.y.tbz2 -C /dsk/l1/misc` (1.1Gb après décompression)
     126  * puis en la décompressant \\`tar xjf /dsk/l1/misc/linux-rpi-3.18.y.tbz2 -C /dsk/l1/misc` (1.1Gb après décompression)
    122127{{{#!make
    123128CARD_NUMB       = 2X
    124 ROUTER          = 132.227.102.36
     129ROUTER          = peri
    125130LOGIN           = nom1-nom2
    126131LAB             = lab2
     
    164169
    165170* Votre driver devra être paramétré pour lui indiquer le numéro de ports utilisés pour les LEDS et les boutons.
    166   Dans un premier temps vous allez vous contenter d'indiquer le nombre de LED et de bouton pour le module de test, mais il faudra être plus précis pour le vrai driver.
    167 * **Vous devez ajouter** dans module.c (faite d'équivalent pour les boutons):
    168 {{{#!c
    169 static int LED;
    170 module_param(LED, int, 0);
    171 MODULE_PARM_DESC(LED, "Nombre de led");
     171  Dans un premier temps vous allez vous contenter d'indiquer le numero du bouton pour le module de test.
     172* **Vous devez ajouter** dans module.c
     173{{{#!c
     174static int btn;
     175module_param(btn, int, 0);
     176MODULE_PARM_DESC(btn, "numéro du port du bouton");
    172177
    173178static int __init mon_module_init(void)
    174179{
    175180    printk(KERN_DEBUG "Hello World !\n");
    176     printk(KERN_DEBUG "LED=%d !\n", LED);
     181    printk(KERN_DEBUG "btn=%d !\n", btn);
    177182    return 0;
    178183}
     
    180185* Le paramètre est défini au moment de l'insertion.
    181186{{{#!sh
    182 $ sudo insmod ./module.ko LED=2
     187$ sudo insmod ./module.ko btn=18
     188}}}
     189* Pour les numéros de GPIO de LEDs, comme il peut y en avoir plusieurs, vous pouvez utiliser `module_param_array`.
     190{{{#!c
     191#define NBMAX_LED 32
     192static int leds[NBMAX_LED];
     193static int nbled;
     194module_param_array(nbled, int, &nbled, 0);
     195MODULE_PARM_DESC(LEDS, "tableau des numéros de port LED");
     196
     197static int __init mon_module_init(void)
     198{
     199    printk(KERN_DEBUG "Hello World !\n");
     200    for (int i=0; i < nbled; i++)
     201       printk(KERN_DEBUG "LED %d = %d\n", i = leds[i]);
     202    return 0;
     203}
     204}}}
     205* Le paramètre est défini au moment de l'insertion.
     206{{{#!sh
     207$ sudo insmod ./module.ko leds=4,17
    183208}}}
    184209* **Questions** :
    185210  * Comment **voir** que le paramètre a bien été lu ?
    186 
    187211
    188212
     
    363387
    364388
    365 == Étape 5 (optionnel) : Usage d'un timer dans le noyau pour faire clignoter la led ==
    366 
    367 * Le code suivant fait clignoter la led GPIO04.\\
    368   Vous pouvez adapter votre driver, pour demander un clignotement plutôt qu'un allumage.
    369   En effet, il existe un moyen de faire faire périodiquement une fonction au système grâce à une file d'attente temporelle.
    370 * Le code ci-dessous n'est pas un pilote, il fait clignoter la led dès son insertion dans le noyau, mais vous pouvez vous en inspirer pour votre pilote.
    371 * La gestion du timer passe par les fonction `setup_timer()` et `mod_timer()`, vous devez en chercher la documentation.
    372 {{{#!c
    373 #include <linux/module.h>
    374 #include <linux/init.h>
    375 #include <asm/io.h>
    376 #include <mach/platform.h>
    377 
    378 static const int LED0 = 2;
    379 
    380 //------------------------------------------------------------------------------
    381 //                                GPIO ACCES
    382 //------------------------------------------------------------------------------
    383 
    384 struct gpio_s
    385 {
    386     uint32_t gpfsel[7];
    387     uint32_t gpset[3];
    388     uint32_t gpclr[3];
    389     uint32_t gplev[3];
    390     uint32_t gpeds[3];
    391     uint32_t gpren[3];
    392     uint32_t gpfen[3];
    393     uint32_t gphen[3];
    394     uint32_t gplen[3];
    395     uint32_t gparen[3];
    396     uint32_t gpafen[3];
    397     uint32_t gppud[1];
    398     uint32_t gppudclk[3];
    399     uint32_t test[1];
    400 }
    401 *gpio_regs = (struct gpio_s *)__io_address(GPIO_BASE);;
    402 
    403 enum {FUN_INPUT, FUN_OUTPUT};
    404 
    405 static void gpio_fsel(int pin, int fun)
    406 {
    407     uint32_t reg = pin / 10;
    408     uint32_t bit = (pin % 10) * 3;
    409     uint32_t mask = 0b111 << bit;
    410     gpio_regs->gpfsel[reg] = (gpio_regs->gpfsel[reg] & ~mask) | ((fun << bit) & mask);
    411 }
    412 
    413 static void gpio_write(int pin, bool val)
    414 {
    415     if (val)
    416         gpio_regs->gpset[pin / 32] = (1 << (pin % 32));
    417     else
    418         gpio_regs->gpclr[pin / 32] = (1 << (pin % 32));
    419 }
    420 
    421 //------------------------------------------------------------------------------
    422 //                             TIMER PROGRAMMING
    423 //------------------------------------------------------------------------------
    424 
    425 static struct timer_list led_blink_timer;
    426 static int led_blink_period = 1000;
    427 
    428 static void led_blink_handler(unsigned long unused)
    429 {
    430     static bool on = false;
    431     on = !on;
    432     gpio_write(LED0, on);
    433     mod_timer(&led_blink_timer, jiffies + msecs_to_jiffies(led_blink_period));
    434 }
    435 
    436 //------------------------------------------------------------------------------
    437 //                              MODULE INIT & EXIT
    438 //------------------------------------------------------------------------------
    439 
    440 MODULE_LICENSE("GPL");
    441 MODULE_AUTHOR("Franck from http://sysprogs.com/VisualKernel/tutorials/raspberry/leddriver/)");
    442 MODULE_DESCRIPTION("leds on-off");
    443  
    444 static int __init LedBlinkModule_init(void)
    445 {
    446     int result;
    447 
    448     gpio_fsel(LED0, FUN_OUTPUT);
    449     gpio_write(LED0, 1);
    450     setup_timer(&led_blink_timer, led_blink_handler, 0);
    451     result = mod_timer(&led_blink_timer, jiffies + msecs_to_jiffies(led_blink_period));
    452     BUG_ON(result < 0);
    453     printk(KERN_DEBUG "blink loaded\n");
    454 
    455     return 0;
    456 }
    457 
    458 static void __exit LedBlinkModule_exit(void)
    459 {
    460     gpio_fsel(LED0, FUN_INPUT);
    461     del_timer(&led_blink_timer);
    462     printk(KERN_DEBUG "blink removed\n");
    463 }
    464 
    465 module_init(LedBlinkModule_init);
    466 module_exit(LedBlinkModule_exit);
    467 
    468 }}}
    469 
    470 }}}
     389}}}