基于i.MX6ULL的掉电检测设计与软件测试
基于i.MX6ULL平台设计实现掉电检测功能,首先选择一路IO,利用IO电平变化触发中断,在编写驱动时捕获该路GPIO的中断,然后在中断响应函数中发送信号通知应用程序掉电发生了。
掉电信号IO
图1.1掉电信号IO
驱动代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#definepower_MAJOR?200
staticstruct?class?*my_class;
staticstruct?fasync_struct?*fasync_queue;?//异步通知队列
#defineGPIO_NUM?1??//中断引脚为:GPIO1_1
staticunsigned?int?irq_num;
/*?打开?*/
intpower_open(struct?inode?*inode,struct?file?*filp){
return?0;
}
/*?关闭?*/
intpower_release(struct?inode?*inode,struct?file?*filp){
return?0;
}
ssize_tpower_read(struct?file?*filp,char?__user?*buf,size_t?count,loff_t?*f_pos){
return?count;
}
ssize_tpower_write(struct?file?*file,const?char?__user?*buf,size_t?count,loff_t*f_pos){
return?count;
}
staticint?my_fasync(int?fd,?struct?file?*?filp,?int?on)
{
int?retval;
retval=fasync_helper(fd,filp,on,&fasync_queue);
/*将该设备登记到fasync_queue队列中去*/
if(retval
return?retval;
return?0;
}
staticconst?struct?file_operations?simple_fops={
.owner=THIS_MODULE,
.open=power_open,
.release=power_release,
.read=power_read,
.write=power_write,
.fasync=my_fasync,
};
/*?在中断服务函数中向应用层发送消息-异步通知?*/
staticirqreturn_t?irq_callback?(int?irqno,?void?*dev_id){
printk("irq?power-detectworking?!\n");
if?(fasync_queue)?{
kill_fasync(&fasync_queue,?SIGIO,POLL_IN);
}
return?IRQ_HANDLED;
}
intpower_init_module(void){
int?rtn;
int?ret;
/*?注册设备驱动?*/
ret?=register_chrdev(power_MAJOR,"power-detect-test",&simple_fops);
if(ret
printk("Unable?toregister?character?device?%d!/n",ret);
return?ret;
}
/*?自动创建设备节点?*/
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_irq?irq?pinrequest?io?failed.\n");
}
rtn?=?gpio_direction_input(GPIO_NUM);
if(rtn
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
printk("my_irq?requestirq?false\n");
}?else?{
printk("my_irq?requestirq?success:?%d\n",irq_num);
}
printk("module_initsucessful!!!\n");
return?0;
}
/*?卸载?*/
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
staticint?fd;
/*?内核产生异步通知,调用该应用层函数处理?*/
voidsigterm_handler(int?signo)
{
printf("app?irq?work?!!!\n");
}
intmain(void)
{
int?oflags;
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);
return?0;
}
将驱动编译成模块,上电加载并执行应用程序后,将电压缓慢下调至掉电临界点。触发GPIO下降沿中断,并提供应用程序掉电信号。
?
图1..2掉电检测
领取专属 10元无门槛券
私享最新 技术干货