RaspberryPi/DeviceDriver

Raspberry Pi – Linux Device Driver 만들어 보기-4 ( GPIO Driver 만들기 )

변화의 물결 2022. 11. 3. 00:11



안녕하세요.
 이번에는 GPIO(general-purpose input/output) 드라이버 제작해보겠습니다. 간단하게 작은 LED를 준비합니다. 그리고 버튼 구하기가 조금 어려우니 그냥 케이블을 연결해서 확인하는 것으로 테스트해보았습니다.


1. 사전 준비

  - 이전에 했던 day3 디렉터리를 day4_gpio로 복사를 합니다.

pi@raspberrypi:~/DriverStudy $ cp -r day3 day4_gpio

  - 기본의 파일 이름을 작업하기 위한 파일로 바꿉니다. 그리고 Makefile의 obj 파일 리스트에서도 바꿔줍니다.

pi@raspberrypi:~/DriverStudy/day4_gpio $ mv read_write.c gpio_driver.c
pi@raspberrypi:~/DriverStudy/day4_gpio $ vim Makefile

  - 핀맵, 가지고 있는 제품에 따라 핀번호 수정 영상 속에서는 GPIO 4를 이용했지만, 가지고 있는 라즈베리파이 보드나 캐리어 보드에 따라서 핀번호는 수정해서 사용하면 됩니다. CM4 모델로 소형 캐리어 보드를 사용하다 보니 GPIO14, 15로 테스트하였습니다. 

2. 소스(Source) 수정 

1) gpio_driver.c 수정
  - gpio 제어를 하기 위한 헤더 파일 추가 설명을 바꿉니다.

#include <linux/gpio.h>

MODULE_DESCRIPTION(“Control LED, input Button ... ”);


  - 사용하지 않는 변수 삭제합니다.

/* Buffer for data */ 
static char buffer[255];
static int buffer_pointer;


  - ModuleInit() 함수에서 GPIO 포트 초기화 및 검사 
  - int gpio_reqeust(unsigned int gpio, const char *label); // 함수 인자로 GPIO 핀번호와 sysfs에 나타날 이름을 넣어줍니다. 반환 값이 0 이면 할당이 성공된 것입니다.
- int gpio_direction_output(unsigned int gpio, int value); // GPIO 핀번호와 상태 값 0 혹은 1로 PULL-UP과 PULL-DOWN 상태로 만들어 줍니다.
- GPIO 할당 시 에러가 발생할 수 있기 때문에 기존의 할당된 것이 해제될 수 있도록 goto 문으로 처리해놓았습니다.

		/* GPIO 14 init */
        if(gpio_request(14, "rpi-gpio-14")){
                printk("Can not allocate GPIO14\n");
                goto AddError;
        }

        if(gpio_direction_output(14,0)) {
                printk("Can not set GPIO14 to output!\n");
                goto Gpio14Error;
        }

        /* GPIO 15 init */
        if(gpio_request(15, "rpi-gpio-15")){
                printk("Can not allocate GPIO15\n");
                goto AddError;
        }

        if(gpio_direction_input(15)) {
                printk("Can not set GPIO15  to input!\n");
                goto Gpio15Error;
        }
        return 0;

Gpio15Error :
        gpio_free(15);
Gpio14Error:
        gpio_free(14);


  - 모듈 제거 시 GPIO 해제해줍니다.

static void __exit ModuleExit(void) {
        gpio_set_value(14, 0);
        gpio_free(15);
        gpio_free(14);
   // ...
}


  - DriverName을 변경해줍니다. (원하는 이름으로 바꾸면 됩니다.)

#define DRIVER_NAME “testGPIO_driver”


  - read() 함수에서 버튼의 상태를 읽는 코드를 추가합니다.

        char tmp[3] = " \n";

        /* Get amount of data to copy */
        to_copy = min(count, sizeof(tmp));

        /* Read value of button */
        printk("Value of button: %d\n", gpio_get_value(15));
        tmp[0] = gpio_get_value(15) + '0';

        /* Copy data to User Area */
        not_copied = copy_to_user(user_buffer, &tmp, to_copy);


  - write() 함수 소스 추가

        char value;

        /* Get amount of data to copy */
        to_copy = min(count, sizeof(value));

        /* Copy data from User Area */
        not_copied = copy_from_user(&value, user_buffer, to_copy);

        printk("Write - value : %d\n",value);

        switch(value) {
                case '0' :
                        gpio_set_value(14, 0);
                        break;
                case '1' :
                        gpio_set_value(14, 1);
                        break;
                default :
                        printk("Invalid Input!\n");
                        break;
        }


  - gpio가 지원하지 않는 핀이나 사용 중인 핀을 사용하면 아래와 같이 에러가 발생할 수 있습니다.

 그리고 메시지를 찍어보면 GPIO를 할당받지 못했다고 나옵니다.
pi@raspberrypi:~/DriverStudy/day4_gpio $ dmesg | tail -n 10으로 확인할 수 있습니다.

  - 정상적으로 컴파일되면 warning 하나 나타나고 ko 파일이 정상적으로 생성되어 있습니다.


- 드라이버를 커널에 삽입한 후 메시지를 확인해봅니다.

pi@raspberrypi:~/DriverStudy/day4_gpio $ sudo insmod gpio_driver.ko


  - 드라이버 장치 파일이 자동으로 만들어지므로 이제 접근할 수 있는 권한을 줍니다.

pi@raspberrypi:~/DriverStudy/day4_gpio $ sudo chmod 666 /dev/testGPIO_driver
pi@raspberrypi:~/DriverStudy/day4_gpio $ ls /dev/testGPIO_driver  -al

3. 결과 확인 하기

  - 현재 안정적이게 부품을 구성하지 않고 간단하게 확인하기 위해서 작업한 것입니다. 조금 안정적이게 테스트하려면 LED에 저항 달고, Push Button에 Capacity 등을 달아서 테스트해야 합니다.

1) 출력 확인
- 사진상으로는 잘 안 보이는데, 제어 신호를 주면 LED가 깜박이는 것을 확인할 수 있습니다.
- On (1) 

pi@raspberrypi:~/DriverStudy/day4_gpio $ echo 1 > /dev/testGPIO_driver

- Off (0)

pi@raspberrypi:~/DriverStudy/day4_gpio $ echo 0 > /dev/testGPIO_driver



 


  - 추가적으로 dmesg를 확인해보면 LF(Line Feed)도 같이 입력신호로 들어간다는 것을 알 수 있습니다. 그렇기 때문에 예외처리를 하거나 정확한 입력을 받아야 한다는 것을 알 수 있습니다.


  - 10진수로 나온 값을 보면 어떤 값이 입력된 것인지 알 수 있습니다.  48 = 0(문자), 49 = 1(문자), 10 = LF

2) 입력 확인
- 버튼을 대신해서 GND 핀을 연결해서 누르는 것처럼 했습니다. 

pi@raspberrypi:~/DriverStudy/day4_gpio $ head -n 1 /dev/testGPIO_driver

  - 가지고 있는 캐리어 보드 IO Pin map입니다. 원본 라즈베리파이 4 핀 맵과 동일한 구조이니 동일한 핀을 연결하시면 작동 확인을 할 수 있습니다.



 감사합니다.


<참고 사이트>
1. Let's code a Linux Driver - 4: GPIO driver
https://www.youtube.com/watch?v=P3Judr4i7QI&list=PLCGpd0Do5-I3b5TtyqeF1UdyD4C-S-dMa&index=5
2. [Linux kernel] GPIO 정리
https://blog.dasomoli.org/446/   

day4_gpio.zip
0.00MB