Différences entre versions de « Linux sunxi armbian gpio »

De The Linux Craftsman
Aller à la navigation Aller à la recherche
Ligne 70 : Ligne 70 :
  
 
== Informations sur les broches ==
 
== Informations sur les broches ==
Pour avoir des informations sur les broches, le principe est le même, sauf que la structure utilisée est ''gpioline_info''.  Nous allons le mettre dans un fichier ''read_gpio.c'':
+
Pour avoir des informations sur les broches, le principe est le même, sauf que la structure utilisée est ''gpioline_info''.  Nous allons créer le fichier ''read_gpio.c'':
 
<source lang="c">
 
<source lang="c">
 
#include <stdio.h> // pour EXIT_SUCCESS
 
#include <stdio.h> // pour EXIT_SUCCESS
Ligne 85 : Ligne 85 :
 
int main(int argc, char * argv[]){
 
int main(int argc, char * argv[]){
 
   // ouverture du contrôleur en lecture seule
 
   // ouverture du contrôleur en lecture seule
   int fd = open(GPIO_CHIP, O_RDONLY);
+
   int fd_chip = open(GPIO_CHIP, O_RDONLY);
 
   // Structure contenant les informations
 
   // Structure contenant les informations
 
   struct gpioline_info info;
 
   struct gpioline_info info;
Ligne 95 : Ligne 95 :
 
     info.line_offset = offset;
 
     info.line_offset = offset;
 
     // Lecture des informations
 
     // Lecture des informations
     ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &info);
+
     ioctl(fd_chip, GPIO_GET_LINEINFO_IOCTL, &info);
 
     // Affichage
 
     // Affichage
 
     printf(" %d: consommateur = %s, Direction = %s, Autres: %s %s %s %s\n",
 
     printf(" %d: consommateur = %s, Direction = %s, Autres: %s %s %s %s\n",
Ligne 107 : Ligne 107 :
 
}
 
}
 
</source>
 
</source>
Une fois compilé, on peut afficher des informations sur les 224 broches du contrôleur gpiochip0:
+
Une fois compilé, on peut afficher des informations sur les 224 broches du contrôleur ''gpiochip0'':
<source lang="bash">
+
<pre>
gcc -std=c99 -o read_gpio.bin read_gpio.c
+
# gcc -std=c99 -o read_gpio.bin read_gpio.c
./read_gpio.bin
+
# ./read_gpio.bin
 
  0: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 
  0: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 
  1: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 
  1: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
Ligne 134 : Ligne 134 :
 
/..../
 
/..../
 
  223: consommateur = , Direction = IN , Autres: ACTIVE_HIGH
 
  223: consommateur = , Direction = IN , Autres: ACTIVE_HIGH
 +
</pre>
 +
On remarque qu'il nous manque l'état de la broche et on peut le récupérer en plusieurs étapes.
 +
Tout d'abord il faut récupérer le descripteur de la ligne (GPIO) qui nous intéresse grâce à la structure suivante:
 +
<source lang="c">
 +
struct gpiohandle_request {
 +
  __u32 lineoffsets[GPIOHANDLES_MAX];
 +
  __u32 flags;
 +
  __u8 default_values[GPIOHANDLES_MAX];
 +
  char consumer_label[32];
 +
  __u32 lines;
 +
  int fd;
 +
};
 +
</source>
 +
Cette structure contient plusieurs attributs et notamment:
 +
* lineoffsets: qui est un tableau contenant les numéros des lignes qui nous intéresse
 +
* flags : qui est le type de requête (GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_INPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW, etc...)
 +
* lines : qui correspond au nombre de lignes concernée par la requête
 +
* fd : contiendra le descripteur de la requête
 +
Une fois la requête préparée, on peut utiliser la structure suivante pour récupérer la valeur:
 +
<source lang="c">
 +
struct gpiohandle_data {
 +
  __u8 values[GPIOHANDLES_MAX];
 +
};
 +
</source>
 +
Cette structure contient un tableau d'entier sur 8 bits avec l'état des lignes.
 +
 +
Dans l'exemple suivant, on demande l'état de la ligne 199 du contrôleur ''gpiochip0''.  Nous allons créer le fichier read_gpio.c:
 +
<source lang="c">
 +
#include <stdio.h> // pour EXIT_SUCCESS
 +
#include <stdlib.h> // pour printf
 +
#include <linux/gpio.h> // pour struct gpiochip_info
 +
#include <fcntl.h> // pour open
 +
#include <sys/ioctl.h> // pour ioctl
 +
#include <string.h> // Pour memset
 +
 +
// Macro pour le nom du contrôleur
 +
#define GPIO_CHIP "/dev/gpiochip0"
 +
// Macro pour le numéro de la ligne
 +
#define GPIO 199
 +
 +
int main(int argc, char * argv[]){
 +
  // ouverture du contrôleur en lecture seule
 +
  int chip_fd = open(GPIO_CHIP, O_RDONLY); int offset;
 +
  // Structure contenant les informations de la ligne
 +
  struct gpiohandle_request request;
 +
  // Initialisation de la structure avec des zéro
 +
  memset(&request, 0, sizeof(struct gpiohandle_request));
 +
  // Positionnement du numéro de la ligne à lire
 +
  request.lineoffsets[0] = GPIO;
 +
  // Spécification de la demande
 +
  request.flags = GPIOHANDLE_REQUEST_INPUT;
 +
  // Quantité de ligne a traiter
 +
  request.lines = 1;
 +
  // Récupération du descripteur de la ligne
 +
  ioctl(chip_fd, GPIO_GET_LINEHANDLE_IOCTL, &request);
 +
  // Structure contenant les valeurs de la ligne
 +
  struct gpiohandle_data values;
 +
  // Initialisation de la structure avec des zéro
 +
  memset(&values, 0, sizeof(struct gpiohandle_data));
 +
  // Lecture des valeurs présente dans le descripteur
 +
  ioctl(request.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &values);
 +
  // Affichage
 +
  printf("Line %i is %s\n", GPIO, values.values[0] == 0 ? "LOW" : "HIGH");
 +
}
 
</source>
 
</source>
On remarque qu'il nous manque l'état de la broche et il se récupère avec une autre structure:
+
Une fois compilé, on peut afficher l'état de la ligne 199 du contrôleur ''gpiochip0'':
 +
<pre>
 +
# gcc -o read_gpio_state.bin read_gpio_state.c
 +
# ./read_gpio_state.bin
 +
Line 199 is LOW
 +
# ./read_gpio_state.bin
 +
Line 199 is HIGH
 +
</pre>
  
 
= Modification =
 
= Modification =

Version du 9 juin 2020 à 21:40

Introduction

Nous allons piloter les broches d'un Orange Pi Zéro grâce à l'API C libgpiod ainsi qu'à la fonction ioctl.

  • ioctl prend trois paramètres:
  1. un descripteur de fichier
  2. le code de la requête (souvent une macro)
  3. une valeur discrète (type primitif) ou un pointeur sur une structure de données.
#include <sys/ioctl.h>

int ioctl(int d, int requête, ...);
  • libgpiod fournie les structures de données qui vont nous permettre de manipuler ou lire l'état des broches
#include <linux/gpio.h>

struct gpiochip_info {
    char name[32];
    char label[32];
    __u32 lines;
};

struct gpioline_info {
    __u32 line_offset;
    __u32 flags;
    char name[32];
    char consumer[32];
};

Lecture

Informations sur les contrôleurs

Commençons par récupérer des informations sur les contrôleurs il faut d'abord récupérer leurs noms:

root@orangepizero:~# ll /dev/gpiochip*
crw------- 1 root root 254, 0 May 25 08:44 /dev/gpiochip0
crw------- 1 root root 254, 1 May 25 08:44 /dev/gpiochip1

Le programme ci-dessous permet d'afficher les informations de gpiochip0. Nous allons le mettre dans un fichier read_gpiochip.c:

#include <stdio.h> // pour EXIT_SUCCESS
#include <stdlib.h> // pour printf
#include <linux/gpio.h> // pour struct gpiochip_info
#include <fcntl.h> // pour open
#include <sys/ioctl.h> // pour ioctl
#include <string.h> // Pour memset

// Macro pour le nom du contrôleur
#define GPIO_CHIP "/dev/gpiochip0" 

int main(int argc, char * argv[]){
	// ouverture du contrôleur en lecture seule
	int fd = open(GPIO_CHIP, O_RDONLY); 
	// création de la structure qui va contenir les informations
	struct gpiochip_info chip_info; 
	// Initialisation de la structure avec des zéro (pour valgrind)
	memset(&chip_info, 0, sizeof(struct gpiochip_info));
	// Lecture des informations
	ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip_info);
	// Affichage
	printf("name = %s, label = %s, lines = %d\n", chip_info.name, chip_info.label, chip_info.lines);
	return EXIT_SUCCESS;
}

Une fois compilé, ce programme nous apprend que le contrôleur possède 224 lignes:

# gcc -o read_gpiochip.bin read_gpiochip.c
# ./read_gpiochip.bin
name = gpiochip0, label = 1c20800.pinctrl, lines = 224

Informations sur les broches

Pour avoir des informations sur les broches, le principe est le même, sauf que la structure utilisée est gpioline_info. Nous allons créer le fichier read_gpio.c:

#include <stdio.h> // pour EXIT_SUCCESS
#include <stdlib.h> // pour printf
#include <linux/gpio.h> // pour struct gpiochip_info
#include <fcntl.h> // pour open
#include <sys/ioctl.h> // pour ioctl
#include <string.h> // Pour memset

// Macro pour le nom du contrôleur
#define GPIO_CHIP "/dev/gpiochip0"
#define LINES 224 

int main(int argc, char * argv[]){
  // ouverture du contrôleur en lecture seule
  int fd_chip = open(GPIO_CHIP, O_RDONLY);
  // Structure contenant les informations
  struct gpioline_info info;
  // Itération sur toutes les lignes
  for (int offset = 0; offset < LINES; offset ++) {
    // Initialisation de la structure avec des zéro (pour valgrind)
    memset(&info, 0, sizeof(struct gpioline_info));
    // Positionnement du numéro de la ligne à lire
    info.line_offset = offset;
    // Lecture des informations
    ioctl(fd_chip, GPIO_GET_LINEINFO_IOCTL, &info);
    // Affichage
    printf(" %d: consommateur = %s, Direction = %s, Autres: %s %s %s %s\n",
        info.line_offset, info.consumer,
        info.flags & GPIOLINE_FLAG_IS_OUT ? "OUT" : "IN ",
        info.flags & GPIOLINE_FLAG_ACTIVE_LOW ? "ACTIVE_LOW " : "ACTIVE_HIGH",
        info.flags & GPIOLINE_FLAG_OPEN_DRAIN ? "OPEN_DRAIN" : "",
        info.flags & GPIOLINE_FLAG_OPEN_SOURCE ? "OPEN_SOURCE" : "",
        info.flags & GPIOLINE_FLAG_KERNEL ? "KERNEL" : "");
  }
}

Une fois compilé, on peut afficher des informations sur les 224 broches du contrôleur gpiochip0:

# gcc -std=c99 -o read_gpio.bin read_gpio.c
# ./read_gpio.bin
 0: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 1: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 2: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 3: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 4: consommateur = , Direction = IN , Autres: ACTIVE_HIGH
 5: consommateur = , Direction = IN , Autres: ACTIVE_HIGH
 6: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 7: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 8: consommateur = , Direction = IN , Autres: ACTIVE_HIGH
 9: consommateur = , Direction = IN , Autres: ACTIVE_HIGH
 10: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 11: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 12: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 13: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 14: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 15: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 16: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 17: consommateur = orangepi:red:status, Direction = OUT, Autres: ACTIVE_HIGH   KERNEL
 18: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 19: consommateur = , Direction = OUT, Autres: ACTIVE_HIGH
 20: consommateur = reg_vcc_wifi, Direction = OUT, Autres: ACTIVE_HIGH   KERNEL
/..../
 223: consommateur = , Direction = IN , Autres: ACTIVE_HIGH

On remarque qu'il nous manque l'état de la broche et on peut le récupérer en plusieurs étapes. Tout d'abord il faut récupérer le descripteur de la ligne (GPIO) qui nous intéresse grâce à la structure suivante:

struct gpiohandle_request {
  __u32 lineoffsets[GPIOHANDLES_MAX];
  __u32 flags;
  __u8 default_values[GPIOHANDLES_MAX];
  char consumer_label[32];
  __u32 lines;
  int fd;
};

Cette structure contient plusieurs attributs et notamment:

  • lineoffsets: qui est un tableau contenant les numéros des lignes qui nous intéresse
  • flags : qui est le type de requête (GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_INPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW, etc...)
  • lines : qui correspond au nombre de lignes concernée par la requête
  • fd : contiendra le descripteur de la requête

Une fois la requête préparée, on peut utiliser la structure suivante pour récupérer la valeur:

struct gpiohandle_data {
  __u8 values[GPIOHANDLES_MAX];
};

Cette structure contient un tableau d'entier sur 8 bits avec l'état des lignes.

Dans l'exemple suivant, on demande l'état de la ligne 199 du contrôleur gpiochip0. Nous allons créer le fichier read_gpio.c:

#include <stdio.h> // pour EXIT_SUCCESS
#include <stdlib.h> // pour printf
#include <linux/gpio.h> // pour struct gpiochip_info
#include <fcntl.h> // pour open
#include <sys/ioctl.h> // pour ioctl
#include <string.h> // Pour memset

// Macro pour le nom du contrôleur
#define GPIO_CHIP "/dev/gpiochip0"
// Macro pour le numéro de la ligne
#define GPIO 199

int main(int argc, char * argv[]){
  // ouverture du contrôleur en lecture seule
  int chip_fd = open(GPIO_CHIP, O_RDONLY); int offset;
  // Structure contenant les informations de la ligne
  struct gpiohandle_request request;
  // Initialisation de la structure avec des zéro
  memset(&request, 0, sizeof(struct gpiohandle_request));
  // Positionnement du numéro de la ligne à lire
  request.lineoffsets[0] = GPIO;
  // Spécification de la demande
  request.flags = GPIOHANDLE_REQUEST_INPUT;
  // Quantité de ligne a traiter
  request.lines = 1;
  // Récupération du descripteur de la ligne
  ioctl(chip_fd, GPIO_GET_LINEHANDLE_IOCTL, &request);
  // Structure contenant les valeurs de la ligne
  struct gpiohandle_data values;
  // Initialisation de la structure avec des zéro
  memset(&values, 0, sizeof(struct gpiohandle_data));
  // Lecture des valeurs présente dans le descripteur
  ioctl(request.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &values); 
  // Affichage
  printf("Line %i is %s\n", GPIO, values.values[0] == 0 ? "LOW" : "HIGH");
}

Une fois compilé, on peut afficher l'état de la ligne 199 du contrôleur gpiochip0:

# gcc -o read_gpio_state.bin read_gpio_state.c
# ./read_gpio_state.bin
Line 199 is LOW
# ./read_gpio_state.bin
Line 199 is HIGH

Modification

Direction

Écriture

PWM logiciel