행복한 하루

Raspberry Pi – Linux Device Driver 만들어 보기-8 ( Timer를 이용한 LED 제어 ) 본문

RaspberryPi/DeviceDriver

Raspberry Pi – Linux Device Driver 만들어 보기-8 ( Timer를 이용한 LED 제어 )

변화의 물결 2022. 12. 30. 00:05

 

 

안녕하세요.

 

 이번에는 Timer를 사용하는 방법을 확인해보려고 합니다. 드라이버가 추가되면 LED가 켜지고 타이머가 초기화  4초 초기화되면서 카운트하기 시작합니다. 시간이 되면 LED가 꺼지는 것을 테스트해 봅니다.


1. 하드웨어 연결

 - 간단한 점퍼 케이블과 LED 하나 정도만 있으면 됩니다. 안전하게 테스트 위해서는 브래드 보드에 220Ω~330Ω정도 저항 뒤에 LED를 달아서 테스트해야 합니다.

 - 라즈베리파이의 GPIO 4 핀에는 LED +극(Anode), Ground핀에는 LED -극(Cathode)을 연결합니다.

2. 사전 작업

 - 기존에 작업한 것처럼 드라이버 구조가 만들어진 소스를 이용합니다. day1에서 기초 형태를 복사합니다.

pi@raspberrypi:~/DriverStudy $ cp -r day1 day8_timer
pi@raspberrypi:~/DriverStudy $ cd day8_timer/
pi@raspberrypi:~/DriverStudy/day8_timer $ ls
pi@raspberrypi:~/DriverStudy/day8_timer $ mv day1_module.c day8_timer.c

 

- Makefile에서 컴파일될 파일 이름을 변경합니다.

pi@raspberrypi:~/DriverStudy/day8_timer $ vim Makefile

obj-m += day8_timer.o

3. 소스 추가

1) 타이머를 이용한 헤더파일을 추가합니다.

#include <linux/gpio.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
...
MODULE_DESCRIPTION("A simple timer Test");

 

2) 기존의 GPIO 내용(day4_gpio)에서 gpio 초기화하는 부분들을 복사해서 리턴값만 -1로 변경해서 사용합니다.

 - static int __init ModuleInit(void) 함수에 추가 

		/* GPIO 4 init */
        if(gpio_request(4, "rpi-gpio-4")) {
                printk("Can not allocate GPIO 4\n");
                return -1;
        }

        /* Set GPIO 4 direction */
        if(gpio_direction_output(4, 0)) {
                printk("Can not set GPIO 4 to output!\n");
                gpio_free(4);
                return -1;
        }

        /* Trun LED on */
        gpio_set_value(4,1);

 

- static void __exit ModuleExit(void) 함수에서 해제해 줍니다.

 gpio_free(4);

 

3) 타이머를 위한 구조체를 전역변수로 선언하고 타이머 시간이 되었을 때 실행되는 콜백함수를 구현해 줍니다. 예제에서는 LED가 꺼지는 동작을 합니다. 

/** variable for timer */
static struct timer_list my_timer;

void timer_callback(struct timer_list * data) {
        gpio_set_value(4, 0); /* Turn LED off */
}

 

4) 타이머 구조체를 초기화 및 시간을 설정하는 것을 ModuleInit 함수에서 구현합니다.

 - timer_list 구조체 안에 expires 변수가 있는데 이것은 타이머가 만료되는 시간을 가지며 jiffies + @ 값으로 된다고 합니다. 그리고 콜백함수를 가지는 함수포인터 변수도 가지고 있고, 타이머 속성을 가지는 flags도 변수로 가지고 있습니다.

 

 - timer_setup 함수로 초기화를 하고 mod_timer 함수로 커널에 타이머를 등록합니다. (혹은 add_timer 함수 이용)

 - 참조 블로그 글에서 타이머가 정확하지 않을 수 있으나 최대한 expires 맞추려고 한다고 합니다. 다음 내용에서 좀 더 정확한 타이머를 다룰 예정입니다.

 

 - msecs_to_jiffies() 함수에 인자로 원하는 시간(ms 단위)을 넣어주면 타이머가 원하는 시간에 콜백함수를 호출하게 됩니다. 여기서 jiffies는 cpu 클럭을 이용한 커널 타이머 실행 시간 단위라고 보시면 어떨까 합니다. 내용이 산으로 갈 것 같아서 참고 사이트 링크를 참고하시면 도움이 될 거라고 생각됩니다. 

           /* Initialize timer */
        timer_setup(&my_timer, timer_callback, 0);
        mod_timer(&my_timer, jiffies + msecs_to_jiffies(4000));

 

 

5) 드라이버 해제 시 ModuleExit 함수에서 타이머를 제거합니다. 위에서 생성된 타이머가 timeout 되어 실행이 완료되었다면 알아서 제거되었고 그렇지 않을 경우 아직 남은 타이머에 대해 제거합니다.

 

del_timer(&my_timer);

4. 컴파일하기

pi@raspberrypi:~/DriverStudy/day8_timer $ make

 - 이전 day1 자료를 이용해서 수정하였다면 driver_init, driver_exit 함수에서 충돌 난다고 에러가 발생할 수 있습니다.

 

 - 다른 이름으로 바꿔주면 됩니다. 예제에서는 ModuleInit, ModuleExit로 변경했습니다. 그리고 마지막 부분에 모듈이 적재될 때 호출하는 함수이름 부분에서도 수정을 해주어야 합니다.

  

 - 정상적으로 컴파일할 경우 드라이버 파일이 생성됩니다.

 5. 동작확인

 - 드라이버 파일을 커널에 추가하면 타이머가 시작됩니다. 예제에서는 4초로 설정했기 때문에 대략 4초 뒤에 LED가 꺼지는 것을 확인할 수 있습니다.

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

 

 - 완료 후 모듈 제거

pi@raspberrypi:~/DriverStudy/day8_timer $ sudo rmmod day8_timer.ko

[TIP] VIM에서 화면 분할 기능

: split  ./Makefile

  - 화면 간 커서 이동은 Ctrl + W 후에 원하는 창으로 화살표키 (예, 위, 아래 화살표를 누르면 커서 이동)

 

 

감사합니다.

 

 

<참고 사이트>

1. Let's code a Linux Driver - 8: Timer in a Linux Kernel Module

https://www.youtube.com/watch?v=3JTfweWGjBg&list=PLCGpd0Do5-I3b5TtyqeF1UdyD4C-S-dMa&index=9

2. Raspberry Pi Pinout

https://pinout.xyz/

3. [Linux Kernel] 시간과 타이머

https://hyeyoo.com/90

4. [라즈베리파이] 커널 타이머(Kernel Timer) - jiffies란

http://egloos.zum.com/rousalome/v/9979958

5. How To Use VIM Split Screen

https://linuxhint.com/how-to-use-vim-split-screen/

6. Linux 커널에서의 디바이스 드라이버 작성

https://www.joinc.co.kr/w/Site/Embedded/Documents/WritingDeviceDriversInLinux

7. ezgif.com

https://ezgif.com/  

day8_timer.zip
0.00MB

 

 

Comments