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");