W tym poście chciałbym opisać sposób przygotowanie sterownika odpowiedzialnego za sterowanie przyciskami.
[Źródło: https://somlabs.com/product/visionsom-6ull/]
W płytce VisionCB-STD przyciski są podłączone w następujący sposób:
Podobnie jak w poprzednim przypadku należy odpowiednio skonfigurować jądro systemu.
Aby skonfigurować sterowniki należy przejść do pobranego obrazu somlabs-debian.
Następnie w celu modyfikacji sterowników należy uruchomić go na systemie:
Podobnie jak w poprzednim przypadku należy odpowiednio skonfigurować jądro systemu.
Aby skonfigurować sterowniki należy przejść do pobranego obrazu somlabs-debian.
Następnie w celu modyfikacji sterowników należy uruchomić go na systemie:
- sudo ./somlabs-debian/chtoolchain
- cd /home/developer/source/kernel/linux-rel_imx_4.1.15_2.1.0_ga
- make ARCH=arm menuconfig
Na samym początku należy uruchomić sterownik GPIO Buttons w jądrze systemu. W kompilacji systemu umieszczonej przez producenta te sterowniki powinny zostać już włączone. W innym przypadku należy uruchomić te sterownik (make menuconfig):
Ta sama sytuacja dotyczy interfejsu zdarzeń:
- Device Drivers -> Input device support -> [*] Keyboards -> <*>GPIO Buttons
Ta sama sytuacja dotyczy interfejsu zdarzeń:
- Device Drivers -> Input device support -> <*> Event interface
W przygotowanym obrazie przez producenta powyższe ustawienia powinny być już przygotowane. Więc prawdopodobnie wystarczy jedynie edycja Device Tree.
Konfiguracja przycisków wygląda następująco:
Konfiguracja przycisków wygląda następująco:
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-0 = <&pinctrl_gpio_keys>;
- pinctrl-names = "default";
- btn3 {
- label = "btn3";
- gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
- linux,code = <103>; /* <KEY_UP> */
- };
- btn4 {
- label = "btn4";
- gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
- linux,code = <108>; /* <KEY_DOWN> */
- };
- };
- &iomuxc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog_1>;
- imx6ul-evk {
- pinctrl_gpio_keys: gpio-keys {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x1b0b0
- MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x1b0b0
- >;
- };
- };
- };
Dostęp do przycisków jest możliwy przez plik /dev/input/event2. Odczytu nie można zrealizować za pomocą instukcji cat:
- cat /dev/input/event2
Pod niego zostały podłączone przyciski IO08 oraz IO09. Po odczytaniu powyższą instrukcją zostaną przesłane następujące informacje:
Dziwne odczyty podczas klikania przycisków wynikają z zapisu danych do struktury. Wygląda ona następująco:
- struct input_event {
- #if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__)
- struct timeval time;
- #define input_event_sec time.tv_sec
- #define input_event_usec time.tv_usec
- #else
- __kernel_ulong_t __sec;
- #if defined(__sparc__) && defined(__arch64__)
- unsigned int __usec;
- unsigned int __pad;
- #else
- __kernel_ulong_t __usec;
- #endif
- #define input_event_sec __sec
- #define input_event_usec __usec
- #endif
- __u16 type;
- __u16 code;
- __s32 value;
- };
Poszczególne pola zawierają takie informacje jak:
- struct timeval time - czas zdarzenia,
- unsigned short type - rodzaj zdarzenia,
- unsigned short code - kod przycisku,
- unsigned int value - aktualna wartość.
Rodzaje zdarzeń zawarte w polu type to:
- EV_REL - Relative Movement - np. poruszenie myszką.
- EV_ABS - Absolute Position - pozycja kliknięcia na wyświetlaczu przy wykorzystaniu ekranu dotykowego.
- EV_SYN - Event Separator - używany przy ekranach dotykowych dla dotyku wielopunktowego.
- EV_KEY - Key Event - wciśnięcie przycisku itp.
Obsługa przycisków w C
Odczyt pliku oraz wyświetlenie potrzebnych danych na ekranie za pomocą programu napisanego w języku C może wyglądać następująco:
Na samym początku następuje otwarcie pliku. Po nim w pętli dane są odczytywane i sprawdzane jest czy został przycisk wciśnięty i jakie informację są zapisane do struktury po jego kliknięciu. Program nie zawiera żadnego mechanizmu filtrującego fałszywe kliknięcia. Wobec tego mogą pojawiać się dodatkowe kliknięcia przycisków.
Bez wprowadzania dodatkowych ustawień można odczytać dane zapisane w pliku event1. Tym razem po kliknięciu przycisku oznaczonego jako IO4 (należy zmienić nazwę pliku do otwarcia z event2 na event1).
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <linux/input.h>
- int main (void)
- {
- struct input_event ev_input;
- int size = sizeof(ev_input), fd;
- fd = open("/dev/input/event2", O_RDONLY);
- if (fd < 0)
- {
- printf("Open event2 failed!\n");
- return EXIT_FAILURE;
- }
- else
- {
- printf("Open event2 OK\n");
- }
- while (1)
- {
- if (read(fd, &ev_input, size) < size)
- {
- printf ("Reading from /dev/input/event1 failed!\n");
- close(fd);
- return(EXIT_FAILURE);
- }
- if (ev_input.type == EV_KEY) //ev_input.type == 0x01
- {
- printf("----------Btn Click------\n");
- printf("type - %u\n", ev_input.type);
- printf("code - %u\n", ev_input.code);
- printf("value - %d\n", ev_input.value);
- }
- }
- close (fd);
- return EXIT_FAILURE;
- }
Na samym początku następuje otwarcie pliku. Po nim w pętli dane są odczytywane i sprawdzane jest czy został przycisk wciśnięty i jakie informację są zapisane do struktury po jego kliknięciu. Program nie zawiera żadnego mechanizmu filtrującego fałszywe kliknięcia. Wobec tego mogą pojawiać się dodatkowe kliknięcia przycisków.
Bez wprowadzania dodatkowych ustawień można odczytać dane zapisane w pliku event1. Tym razem po kliknięciu przycisku oznaczonego jako IO4 (należy zmienić nazwę pliku do otwarcia z event2 na event1).
W celu uruchomienia pozostałych przycisków w Device Tree należy wprowadzić drobne zmiany.
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-0 = <&pinctrl_gpio_keys>;
- pinctrl-names = "default";
- btn1 {
- label = "btn1";
- gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
- linux,code = <106>; /* <KEY_RIGHT> */
- };
- btn2 {
- label = "btn2";
- gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
- linux,code = <105>; /* <KEY_LEFT> */
- };
- btn3 {
- label = "btn3";
- gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
- linux,code = <103>; /* <KEY_UP> */
- };
- btn4 {
- label = "btn4";
- gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
- linux,code = <108>; /* <KEY_DOWN> */
- };
- };
- &iomuxc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog_1>;
- imx6ul-evk {
- pinctrl_gpio_keys: gpio-keys {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO08__GPIO1_IO03 0x1b0b0
- MX6UL_PAD_GPIO1_IO09__GPIO1_IO04 0x1b0b0
- MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0x1b0b0
- MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x1b0b0
- >;
- };
- };
- };
Powyżej zostają uruchomione wszystkie cztery przyciski. Dodatkowo należy usunąć następujące elementy. Ponieważ blokują one dwie ostatnie linie przycisków.
- /*
- pinctrl_tsc: tscgrp {
- fsl,pins = <
- MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
- MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
- MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
- MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
- };
- */
- /*
- &tsc {
- pinctrl-names = "default;
- pinctrl-0=<&pinctrl_tsc>;
- xnur-gpio = <&gpio 1 3 GPIO_ACTIVE_LOW>;
- measure-delay-time = <0xffff>;
- status="okay";
- };
- */