문자 장치 파일에 의해 제어 마이크로 GPIO 신호 레벨을 알림.
드라이버 코드
GPIO 번호를 가져옵니다
notify_gpio = of_get_named_gpio(pdev->dev.of_node, "notify_gpio", 0);
if((ret = gpio_init()) < 0)
{
printk("[gale] %s: notify pin init failed\n", __func__);
goto err_gpio_init;
}
문자 장치를 등록
#define GPIO_MAJOR 199 // major device NO.
#define GPIO_MINOR 0 // minor device NO.
#define DEVICE_NAME "gpio_notify" //driver device node.
static const struct file_operations gpio_fops =
{
.owner = THIS_MODULE,
.open = gpio_open,
.release = gpio_release,
.unlocked_ioctl = gpio_ioctl,
.fasync = gpio_fasync,
};
static int gpio_init(void)
{
int ret;
dev_t my_dev_no;
struct cdev *gpio_cdev;
gpio_cdev = cdev_alloc();
if(gpio_cdev == NULL)
{
printk(KERN_EMERG "Cannot alloc cdev\n");
goto request_failed;
}
cdev_init(gpio_cdev,&gpio_fops);
gpio_cdev->owner=THIS_MODULE;
ret = alloc_chrdev_region(&my_dev_no,0,1,DEVICE_NAME);
if(ret < 0)
{
printk(KERN_EMERG "alloc_chrdev_region failed\n");
goto request_failed;
}
ret=cdev_add(gpio_cdev,my_dev_no,1);
ret = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &gpio_fops);
if(ret < 0)
{
printk(KERN_EMERG "GPIO register failed\n");
goto request_failed;
}
gpio_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(gpio_class, NULL, MKDEV(GPIO_MAJOR, GPIO_MINOR), NULL, DEVICE_NAME);
printk("[gale] %s: OK ###############################\n", __func__);
return ret;
request_failed:
return ret;
}
다음 IOCTL 기능이 구현된다 : 수신 된 신호는 하이 및 로우 설정에 대응
static int gpio_ioctl(struct file *filp,unsigned int cmd)
{
if(0 == notify_gpio)
return -1;
switch(cmd)
{
case SET_OUTPUT_LOW://0
{
printk("\n\n%s: set mcu wakeup(pin2) to low level\n",current->comm);
gpio_direction_output(notify_gpio, 0);
break;
}
case SET_OUTPUT_HIGH://1
{
printk("\n\n%s: set mcu wakeup(pin2) to high level\n",current->comm);
gpio_direction_output(notify_gpio, 1);
break;
}
case GET_VALUE://2
{
return gpio_get_value(notify_gpio);
}
case SET_INPUT://3
{
gpio_direction_input(notify_gpio);
break;
}
default:
{
printk(KERN_EMERG "GPIO command mistake!!!\n");
break;
}
}
return 0;
}
비동기 통지 함수는 대상 프로세스 ID kill_fasync 지정된 함수를 초기화
static int gpio_fasync (int fd, struct file *filp, int mode)
{
printk("quectel low consume: gpio_fasync\n");
return fasync_helper(fd, filp, mode, &gpio_async);
}
지정된 데이터 파일 콘텐츠 저장 위치, 위치 : / SYS / 장치 / SOC : quec, quectel - 낮은 소비 / irq_edge
static volatile char edge[8] = "rising";
static ssize_t irq_edge_show(struct device* dev, struct device_attribute *attr, char* buf)
{
ssize_t ret = 0;
sprintf(buf, "%s", edge);
ret = strlen(buf) + 1;
return ret;
}
static DEVICE_ATTR(irq_edge, S_IRUGO, irq_edge_show, NULL);
제어 코드
두 부분으로 나누었다; 문자 장치에 발행 IOCTL 명령 곳에 사용 GPIO 인터럽트 기능 문자 kill_fasync 장치를 사용하는 신호를 전송한다;
1, GPIO 문자 kill_fasync 장치를 사용하여 신호를 전송 기능을 방해;
static irqreturn_t quectel_wakeup_irq_func(void)
{
int value = gpio_get_value(wakeup_gpio);
if(value == LOW_VALUE)
{
strcpy(edge, "falling");
kill_fasync(&gpio_async, SIGIO, POLL_IN);
}
else if(value == HIGH_VALUE)
{
strcpy(edge, "rising");
kill_fasync(&gpio_async, SIGIO, POLL_IN );
}
return IRQ_HANDLED;
}
(2) 상기 수신 된 신호의 나머지가 자 장치에 발행 IOCTL 명령을 사용하여 그 컨텐츠 데이터를 획득하고;
#define WAKEUP_IO "/dev/gpio_notify"
pm_register(WAKEUP_IO, pm_handle);
static int pm_register(char *path, void (*handle)(int signal))
{
int oflags;
signal(SIGIO, handle); /* 应用程序注册信号处理函数, SIGIO 表示 Io 有数据可供读取; */
io_fd = open(path, O_RDWR);
if (io_fd < 0)
return -1;
fcntl(io_fd, F_SETOWN, getpid());/* 信号发给谁,是通过这段程序告诉内核的 */
oflags = fcntl(io_fd, F_GETFL);//读取 Oflags;
fcntl(io_fd, F_SETFL, oflags | FASYNC);/* 改变 Oflags 为异步通知 FASYNC, 改变 FASYNC标志, 最终调用到驱动的 fasync -> fasync_helper */
handle(SIGIO);
return 0;
}
신호 처리 기능
#define IRQ_EDGE "/sys/devices/soc:quec,quectel-low-consume/irq_edge"
#define ACTIVE 0
static void pm_handle(int signal)
{
int fd;
int count = 0;
char edge[8] = {0};
fd = open(IRQ_EDGE, O_RDONLY | O_NONBLOCK);
if (fd < 0)
return "null";
count = read(fd, edge, sizeof(edge)); //读取数据内容
printf("%s:%s(%d)\n", IRQ_EDGE, edge, count);
close(fd);
if (strncmp(edge, "falling", 7) == 0) {
ioctl(io_fd, !ACTIVE);
} else if (strncmp(edge, "rising", 6) == 0) {
ioctl(io_fd, ACTIVE);
}
이 방법 GPIO GPIO는 충돌이 신호의 산발적 낮은 확률의 문제에지도 실패한 전송 방지 할 필요가있다.