Linux sunxi armbian gpio

De The Linux Craftsman
Aller à la navigation Aller à la recherche

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 le mettre dans un 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 = 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, 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 il se récupère avec une autre structure:

Modification

Direction

Écriture

PWM logiciel