Lekcja 04- Obsługa GPIO

Wstęp

W tej krótkiej lekcji zapoznamy się z podstawami obsługi GPIO w kernelu Linuksa. Obsługa tego interfejsu jest bardzo prosta tak samo jak on sam, ale umożliwia on zaprezentowanie wielu aspektów kernela na żywo, a nie „na sucho” jakimiś dziwnymi przykładami. GPIO będzie nam towarzyszyło w kilku kolejnych lekcjach w których będą prezentowane takie koncepcje jak timery, przerwania, sysfs, sterowniki platformowe(platform drivers) czy device-tree. Zatem zabierzmy się do roboty.

Czym jest GPIO?

Mam nadzieję, że nikomu nie trzeba przedstawiać czym jest GPIO, ale dla formalności dwa zdania czym to mniej więcej jest. GPIO(General Purpose Input/Output) to interfejs, który umożliwia nam wysłanie jednego bitu informacji bądź odczyt jednego bitu informacji, mówiąc po ludzku, są to te piny na twojej płytce, które nie mają przypisanej żadnej konkretnej roli jak np. UART i umożliwiają ustawienie na swoim wyjściu stanu wysokiego lub niskiego bądź umożliwiają odczyt czy dochodzi do nich stan wysokiego lub niskiego napięcia.

Implementacja

Nasz sterownik będzie bardzo prosty, jego działanie będzie polegało tylko i wyłącznie na zapaleniu podłączonej diody podczas jego ładowania i wyłączenia jej podczas jego usunięcia z systemu.

W przypadku RPi4 podłączałem diodę do pinu GPIO4, a w przypadku BBB do pinu GPIO48, oczywiście możesz użyć innych pinów. Podczas podłączania diody pamiętaj o użyciu rezystora.

Kod wygląda następująco:

#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

#define LED // 48 dla BBB lub 4 dla RPi4, wybierz odpowiedni pin

static int __init led_init(void)
{
    if (!gpio_is_valid(LED)){
        pr_err("Invalid GPIO pin!!1\n");
        return -ENODEV;
    }
    gpio_request(LED, "gpioLED");
    gpio_direction_output(LED, 1);
    gpio_set_value(LED, 1);
    gpio_export(LED, false);	
    return 0;
}
static void __exit led_exit(void)
{
    gpio_set_value(LED, 0);
    gpio_unexport(LED);
    gpio_free(LED);
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");

Jak widać kod jest bardzo prosty, składa się tylko z funkcji init oraz exit. Ale po kolei, co się dzieje w tym kodzie.

Najpierw sprawdzamy czy nasz podany pin jest poprawny za pomocą funkcji gpio_is_valid, jeśli zwróci ona błąd zwrócimy informację o braku takiego urządzenia w systemie.

Następnie prosimy o dostęp do tego pinu za pomocą gpio_request, pierwszy parametr to numer naszego GPIO, a drugi to po prostu etykieta, którą mu nadajemy, może być ona jakakolwiek.

W kolejnej linijce ustawiamy pin GPIO jako wyjście ponieważ chcemy ustawiać jego stan gdyż chcemy zapalać diodę. Gdybyśmy chcieli odczytywać stan guzika byśmy ustawili GPIO jako wejście. Aby ustawić pin GPIO jako wyjście używamy funkcji gpio_direction_output, jako parametry podajemy numer pinu oraz jaki stan ma mieć- 1 dla stanu wysokiego(włączony) lub 0 dla stanu niskiego(wyłączony).

Kolejna linijka jest dla celów demonstracyjnych i nie ma ona wpływu na działanie modułu. Funkcja gpio_set_value służy do ustawienia stanu na wyjściu, my tutaj ustawiamy stan wysoki, który to już został ustawiony wcześniej przez funkcję gpio_direction_output.

Funkcja gpio_export służy do utworzenia odpowiednich katalogów i plików w wirtualnym systemie plików(katalog /sys) dzięki, którym użytkownik mógłby komunikować się z naszą diodą. My nie chcemy aby system utworzył takie pliki więc przekazujemy wartość false jako drugi parametr.

Na końcu zwracamy wartość 0 jako informację, że wszystko się powiodło.

Jak wiemy z poprzedniej lekcji funkcja exit robi to samo co init tylko, że na odwrót. W tym przypadku ustawiamy stan pinu na 0 czyli stan niski oraz zwracamy diodę do systemu za pomocą funkcji gpio_unexport i gpio_free.

Makfile wygląda jak poprzednio:

obj-m += 04_gpio.o
all:
	make -C /ścieżka/do/zbudowanego/kernela M=$(PWD) modules
clean:
	make -C /ścieżka/do/zbudowanego/kernela M=$(PWD) clean

Przebuduj moduł komendą odpowiednią dla swojego systemu:

# BBB
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
# RPi4
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- KERNEL=kernel8

Testowanie sterownika

Aby przetestować sterownik musisz mieć wcześniej podłączoną diodę jak to zostało opisane na początku poprzedniej sekcji.

Prześlij plik na swoją płytkę np. za pomocą scp i załaduj moduł:

sudo insmod 04_gpio.ko

Dioda powinna się zapalić. Teraz usuń moduł:

sudo rmmod 04_gpio

Dioda powinna zgasnąć.

I to tyle w tej lekcji, dzięki temu prostemu interfejsowi poznamy całkiem złożone funkcjonalności kernela.

Ten wpis został opublikowany w kategorii Kurs pisania sterowników. Dodaj zakładkę do bezpośredniego odnośnika.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *