热度 1
2023-11-9 11:10
511 次阅读|
0 个评论
基于 i.MX6ULL 的掉电检测设计与软件测试 基于 i.MX6ULL 平台设计实现掉电检测功能,首先选择一路 IO ,利用 IO 电平变化触发中断,在编写驱动时捕获该路 GPIO 的中断,然后在中断响应函数中发送信号通知应用程序掉电发生了。 图 1.1 掉电信号 IO 驱动代码 : #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #definepower_MAJOR200 staticstructclass*my_class; staticstructfasync_struct*fasync_queue;// 异步通知队列 #defineGPIO_NUM1// 中断引脚为: GPIO1_1 staticunsignedintirq_num; /* 打开 */ intpower_open(structinode*inode,structfile*filp){ return0; } /* 关闭 */ intpower_release(structinode*inode,structfile*filp){ return0; } ssize_tpower_read(structfile*filp,char__user*buf,size_tcount,loff_t*f_pos){ returncount; } ssize_tpower_write(structfile*file,constchar__user*buf,size_tcount,loff_t*f_pos){ returncount; } staticintmy_fasync(intfd,structfile*filp,inton) { intretval; retval=fasync_helper(fd,filp,on,&fasync_queue); /* 将该设备登记到 fasync_queue 队列中去 */ if(retval<0) returnretval; return0; } staticconststructfile_operationssimple_fops={ .owner=THIS_MODULE, .open=power_open, .release=power_release, .read=power_read, .write=power_write, .fasync=my_fasync, }; /* 在中断服务函数中向应用层发送消息 - 异步通知 */ staticirqreturn_tirq_callback(intirqno,void*dev_id){ printk("irqpower-detectworking!\n"); if(fasync_queue){ kill_fasync(&fasync_queue,SIGIO,POLL_IN); } returnIRQ_HANDLED; } intpower_init_module(void){ intrtn; intret; /* 注册设备驱动 */ ret=register_chrdev(power_MAJOR,"power-detect-test",&simple_fops); if(ret<0){ printk("Unabletoregistercharacterdevice%d!/n",ret); returnret; } /* 自动创建设备节点 */ my_class=class_create(THIS_MODULE,"my_class"); device_create(my_class,NULL,MKDEV(power_MAJOR,0),NULL,"powerdetect"); /*gpio 申请 */ rtn=gpio_request(GPIO_NUM,"my_irq"); if(rtn!=0){ printk("my_irqirqpinrequestiofailed.\n"); } rtn=gpio_direction_input(GPIO_NUM); if(rtn<0){ printk("gpio_direction_input()failed!\n"); } /* 获取 gpio 中断号 */ irq_num=gpio_to_irq(GPIO_NUM); /*GPIO 中断服务函数注册, *//* 下降沿触发 */ rtn=request_irq(irq_num,irq_callback,IRQF_TRIGGER_FALLING,"my_irq",NULL); if(rtn<0){ printk("my_irqrequestirqfalse\n"); }else{ printk("my_irqrequestirqsuccess:%d\n",irq_num); } printk("module_initsucessful!!!\n"); return0; } /* 卸载 */ voidpower_cleanup_module(void){ /* 卸载相应的设备驱动 */ unregister_chrdev(power_MAJOR,"power-detect-test"); device_destroy(my_class,MKDEV(power_MAJOR,0)); class_destroy(my_class); /* 释放 GPIO*/ gpio_free(GPIO_NUM); printk("module_exitsucessful!!!\n"); } /* 宏实现 */ module_init(power_init_module); module_exit(power_cleanup_module); /* 开源许可声明 */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Zou"); 应用代码 : #include #include #include #include #include #include staticintfd; /* 内核产生异步通知 , 调用该应用层函数处理 */ voidsigterm_handler(intsigno) { printf("appirqwork!!!\n"); } intmain(void) { intoflags; fd=open("/dev/powerdetect",O_RDWR);// 打开设备文件 /* 启动异步通知信号驱动机制 */ signal(SIGIO,sigterm_handler); fcntl(fd,F_SETOWN,getpid()); oflags=fcntl(fd,F_GETFL); fcntl(fd,F_SETFL,oflags|FASYNC); /* 建立一个死循环,防止程序结束 */ while(1) { printf("sleep\n"); usleep(200000);//2ms } close(fd); return0; } 将驱动编译成模块,上电加载并执行应用程序后,将电压缓慢下调至掉电临界点。触发 GPIO 下降沿中断,并提供应用程序掉电信号。 图 1..2 掉电检测