반도체 소프트웨어

HC-SR501 디바이스 드라이버 본문

Linux/Linux Device Driver

HC-SR501 디바이스 드라이버

반도체 소프트웨어 엔지니어 2024. 1. 8. 03:03

 

 

단순히 VCC, GND, DATA PIN 만 있어서 쉬울줄 알았던 PIR센서 디바이스 드라이버 개발이 그렇지 않았다. 맨처음에 폴링방식으로 구현했는데 값이 변하지 않아서 한참을 고민했었다. 결론적으로는 다음과 같이 원인을 조사해보면서 문제를 해결했다.

 

1. 전원 공급문제: 멀티테스터 확인 결과, 라즈베리파이 5v출력핀 이상 없음
2. GPIO핀 문제: GPIO핀을 변경해도 변화 없음
3. 데이터 값 읽기 방식: 폴링방식에서 인터럽트 방식으로 소스코드 수정(해결)

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

#define GPIO_SWITCH_IN  6

int     gpio_irq;

static irqreturn_t gpio_interrupt_handler(int irq, void *data)
{
        pr_info(KERN_INFO "interrupted!");

        if (gpio_get_value(GPIO_SWITCH_IN) == 1)
                pr_info(KERN_INFO "ON!");
        else
                pr_info(KERN_INFO "OFF!");

        pr_info(KERN_INFO "----------------------");
        return (IRQ_HANDLED);
}

static int __init gpio_driver_init(void)
{
        int     ret;

        /* gpio initialize      */
        if (gpio_is_valid(GPIO_SWITCH_IN) == false)
                pr_err("GPIO %d is not valid\n", GPIO_SWITCH_IN);

        if (gpio_request(GPIO_SWITCH_IN,"GPIO_6") < 0)
                pr_err("Error: GPIO %d request\n", GPIO_SWITCH_IN);

        gpio_direction_input(GPIO_SWITCH_IN);

        /* interrtup            */
        gpio_irq = gpio_to_irq(GPIO_SWITCH_IN);
        if (gpio_irq < 0)
                pr_info(KERN_ERR "Failed to set gpio IRQ(%d)\n", gpio_irq);

        ret = request_irq(gpio_irq, gpio_interrupt_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "led-gpio", NULL);
        pr_info(KERN_ERR "request IRQ(%d) (%d)\n", gpio_irq, ret);
        if (ret)
                pr_info(KERN_ERR "Failed to request IRQ(%d)\n", ret);

        pr_info("GPIO driver start\n");
        return 0;
}

static void __exit gpio_driver_exit(void)
{
        free_irq(gpio_irq, NULL);
        gpio_free(GPIO_SWITCH_IN);
        pr_info("GPIO driver done\n");
}

module_init(gpio_driver_init);
module_exit(gpio_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("me");
MODULE_DESCRIPTION("HC-SR501");
MODULE_VERSION("1.0");