Programme pulling GPIO

This commit is contained in:
2024-12-16 09:32:57 +01:00
parent ac4cfae285
commit d75d6acf9b

318
tp6.md
View File

@@ -31,4 +31,320 @@ Voici un tableau des ports
En suivant ce tableau tout le long du tableau on devrait eviter toute confusion de câbles.
C'est un peu la galère pour tout faire tenir mais bon normalement ca passe.
C'est un peu la galère pour tout faire tenir mais bon normalement ca passe.
## librairie libgpiod
On peut voir dans le cours que les gpios sont visibles sur notre board dans /sys/class/gpio
```
/sys/class/gpio # ls
export gpiochip128 gpiochip64 unexport
gpiochip0 gpiochip32 gpiochip96
```
On a bien nos 5 chips GPIO qui exposent nos 160 pins.
Mais depuis le kernel 4.8 on doit utiliser l'API GPIO et le code du projet libgpio se trouve sous "https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/"
Si on regarde dans /dev on voit bien nos controlleurs gpio également :
```
/dev # ls -a | grep gpio
gpiochip0
gpiochip1
gpiochip2
gpiochip3
gpiochip4
```
Et on voit que ils n'ont pas le même nom. Si on se fie au tableau trouvé dans le cours on peut directement voir quel controlleur utilise quels pins parmis ceux que on utilise :
| Ports | Controlleur |
| -------- | ----------- |
| PA16 | gpiochip0 |
| PA17 | gpiochip0 |
| PA21 | gpiochip0 |
| PA23 | gpiochip0 |
| PB27 | gpiochip1 |
On peut récupèrer les sources de la librairie gpiod avec `git clone https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git` si on utilise l'HTTPS
Pour pouvoir build cette lib on va avoir besoin d'outils que je vais installer sur la vm de compilation croisée.
`sudo apt install dh-autoreconf`
`sudo apt install autoconf-archive`
Je vais créer un repertoire de destination pour le build de la lib `/home/moi/tp/lib/compiledLib`
Ensuite on peut lancer les commandes :
`git checkout v2.1.3`
`./autogen.sh --enable-tools=yes`
Mais je me retrouve avec cette erreur
```
./autogen.sh --enable-tools=yes
autoreconf: export WARNINGS=
autoreconf: Entering directory '.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I m4
autoreconf: configure.ac: tracing
autoreconf: running: libtoolize --copy --force
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'autostuff'.
libtoolize: copying file 'autostuff/ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4'
autoreconf: configure.ac: not using Intltool
autoreconf: configure.ac: not using Gtkdoc
autoreconf: running: aclocal --force -I m4
autoreconf: running: /usr/bin/autoconf --force
configure.ac:88: error: possibly undefined macro: AC_CHECK_HEADERS
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
configure.ac:213: error: possibly undefined macro: AC_LANG_PUSH
configure.ac:216: error: possibly undefined macro: AC_LANG_POP
autoreconf: error: /usr/bin/autoconf failed with exit status: 1
```
J'avais besoin de cette librairie pour faire fonctionner la commande
`sudo apt install pkg-config`
Et ensuite on peut faire la suite
`./configure --prefix=/home/moi/tp/lib/compiledLib --host=arm-linux --enable-tools`
Ensuite on peut comnpiler la lib
`make`
Après avoir compilé on peut installer la lib ce qui devrait installer les fichiers dans compiledLib
`make install`
Si on retourne dans notre repertoire nouvellement créé "compiledLib" et dedans on peut voir une architecture que l'on connait déja un peu de librairies.
Dans le sous repertoire /lib on peut retrouver ces fichiers
`libgpiod.a libgpiod.la libgpiod.so libgpiod.so.3 libgpiod.so.3.1.1 pkgconfig`
On va prendre tous les fichiers en .so sauf ligpio.so et les envoyer sur notre nfsroot sous /lib exactement comme dans le tp4 et la libc.
A partir de la on devrait pouvoir créer des programmes c qui utilisent la librairie GPIO.
Quand on veut le compiler
`arm-buildroot-linux-musleabi-gcc testGpio.c -o gpio` Mais ca ne marche pas car notre machine de compilation croisée ne connait pas la lib gpio
Pour le developpement on a besoin du libgpiod.so, du gpiod.h et potentiellement le libgpio.a si on fait de la compilation statique.
-l = nom de la librairie "gpiod"
-I = chemin vers le .h "/home/moi/tp/lib/compiledLib/include/gpiod.h"
-L = chemin vers le .so "/home/moi/tp/lib/compiledLib/lib/libgpiod.so"
`arm-buildroot-linux-musleabi-gcc testGpio.c -o gpio -I /home/moi/tp/lib/compiledLib/include/ -lgpiod -L /home/moi/tp/lib/compiledLib/lib/`
Voici le premier bout de code qui permet de simplement de lister tous les devices GPIO sur la board embarquée :
```c
#include <gpiod.h>
#include <stdio.h>
int main(void) {
struct gpiod_chip *chip;
char chip_name[32];
int i = 0;
printf("GPIO Chips on the system:\n");
//Ouais c'est moi qui ai fait tout ce code t'inquiète
// Iterate over possible chip names (gpiochip0, gpiochip1, etc.)
for (i = 0; i < 10; i++) {
snprintf(chip_name, sizeof(chip_name), "/dev/gpiochip%d", i);
chip = gpiod_chip_open(chip_name);
if (!chip)
continue; // Skip if chip doesn't exist
printf("- %s\n", chip_name);
gpiod_chip_close(chip);
}
return 0;
}
```
Après avoir tftp le fichier sur la machine hôte du nfsroot et avoir changé les permissions pour permettre l'execution "chmod +x executable" on peut lancer le programme depuis notre système embarqué et on obtient ce resultat :
```
GPIO Chips on the system:
- /dev/gpiochip0
- /dev/gpiochip1
- /dev/gpiochip2
- /dev/gpiochip3
- /dev/gpiochip4
```
On pourra utiliser ces strings quand on voudra parler des différents GPIO dans la suite de nos codes.
On a deux features à implementer dans un premier temps :
1. afficher en boucle l'étât du joystick (ex "haut", "bas", "gauche", "droite")
2. Quand le bouton du joystick est pressé ca ferme le programme.
Voici un exemple de code que j'ai trouvé sur le git de gpiod et que j'ai très légèrement modifié pour qu'il ecrive en boucle la valeur du joystick up
```c
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2023 Kent Gibson <warthog618@gmail.com>
/* Minimal example of reading a single line. */
#include <errno.h>
#include <gpiod.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<unistd.h>
/* Request a line as input. */
static struct gpiod_line_request *request_input_line(const char *chip_path,
unsigned int offset,
const char *consumer){
struct gpiod_request_config *req_cfg = NULL;
struct gpiod_line_request *request = NULL;
struct gpiod_line_settings *settings;
struct gpiod_line_config *line_cfg;
struct gpiod_chip *chip;
int ret;
chip = gpiod_chip_open(chip_path);
if (!chip)
return NULL;
settings = gpiod_line_settings_new();
if (!settings)
goto close_chip;
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
line_cfg = gpiod_line_config_new();
if (!line_cfg)
goto free_settings;
ret = gpiod_line_config_add_line_settings(line_cfg, &offset, 1,
settings);
if (ret)
goto free_line_config;
if (consumer) {
req_cfg = gpiod_request_config_new();
if (!req_cfg)
goto free_line_config;
gpiod_request_config_set_consumer(req_cfg, consumer);
}
request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
gpiod_request_config_free(req_cfg);
free_line_config:
gpiod_line_config_free(line_cfg);
free_settings:
gpiod_line_settings_free(settings);
close_chip:
gpiod_chip_close(chip);
return request;
}
int main(void)
{
static const char *const gpio_0 = "/dev/gpiochip0";
static const char *const gpio_1 = "/dev/gpiochip1";
static const unsigned int JOYSTICK_UP = 16; //GPIO0
static const unsigned int JOYSTICK_DOWN = 17; //GPIO0
static const unsigned int JOYSTICK_LEFT = 21; //GPIO0
static const unsigned int JOYSTICK_RIGHT = 27; //GPIO1
static const unsigned int JOYSTICK_BUTTON = 23; //GPIO0
struct gpiod_line_request *up_request;
struct gpiod_line_request *down_request;
struct gpiod_line_request *left_request;
struct gpiod_line_request *right_request;
struct gpiod_line_request *button_request;
enum gpiod_line_value value;
up_request = request_input_line(gpio_0, JOYSTICK_UP, "get-line-value");
down_request = request_input_line(gpio_0, JOYSTICK_DOWN, "get-line-value");
left_request = request_input_line(gpio_0, JOYSTICK_LEFT, "get-line-value");
right_request = request_input_line(gpio_1, JOYSTICK_RIGHT, "get-line-value");
button_request = request_input_line(gpio_0, JOYSTICK_BUTTON, "get-line-value");
if (!up_request) {
printf("failed to request line: %s\n");
return EXIT_FAILURE;
}
if (!down_request) {
printf("failed to request line: %s\n");
return EXIT_FAILURE;
}
if (!left_request) {
printf("failed to request line: %s\n");
return EXIT_FAILURE;
}
if (!right_request) {
printf("failed to request line: %s\n");
return EXIT_FAILURE;
}
if (!button_request) {
printf("failed to request line: %s\n");
return EXIT_FAILURE;
}
printf("Listening to joystick press\n");
while(true){
sleep(0.1);
value = gpiod_line_request_get_value(up_request, JOYSTICK_UP);
if (value == GPIOD_LINE_VALUE_INACTIVE)
printf("UP\n");
value = gpiod_line_request_get_value(down_request, JOYSTICK_DOWN);
if (value == GPIOD_LINE_VALUE_INACTIVE)
printf("DOWN\n");
value = gpiod_line_request_get_value(left_request, JOYSTICK_LEFT);
if (value == GPIOD_LINE_VALUE_INACTIVE)
printf("LEFT\n");
value = gpiod_line_request_get_value(right_request, JOYSTICK_RIGHT);
if (value == GPIOD_LINE_VALUE_INACTIVE)
printf("RIGHT\n");
value = gpiod_line_request_get_value(button_request, JOYSTICK_BUTTON);
if (value == GPIOD_LINE_VALUE_INACTIVE)
break;
}
/* not strictly required here, but if the app wasn't exiting... */
gpiod_line_request_release(up_request);
gpiod_line_request_release(down_request);
gpiod_line_request_release(left_request);
gpiod_line_request_release(right_request);
gpiod_line_request_release(button_request);
return EXIT_SUCCESS;
}
}
```
Le code ci dessus devrait faire en permanence du pulling et dès que le joystick est bougé on l'affiche.
J'ai ajouté le fait que quand on appuie sur le bouton du joystick ca arrête le programme et que le sleep(0.1) permette à la boucle de ne s'executer que toutes les 0.1s pour ne pas surcharger le processeur.