EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
基于i.MX6ULL的掉电检测设计与软件测试 基于i.MX6ULL平台设计实现掉电检测功能,首先选择一路IO,利用IO电平变化触发中断,在编写驱动时捕获该路GPIO的中断,然后在中断响应函数中发送信号通知应用程序掉电发生了。 图1.1掉电信号IO 驱动代码: #include<linux/module.h> #include<linux/init.h> #include<linux/types.h> #include<linux/fs.h> #include<linux/mm.h> #include<linux/cdev.h> #include<linux/errno.h> #include<linux/sched.h> #include<linux/device.h> #include<asm/io.h> #include<asm/switch_to.h> #include<asm/uaccess.h> 4 h% ^# W6 S3 w4 X. D
#include<asm/gpio.h> #include<linux/interrupt.h> #include<linux/irq.h> 6 x+ h- a7 n/ J V! }5 s6 W7 U8 ]
" B1 K9 I. V/ J, o& [% h8 Y: w. ~#definepower_MAJOR 200
7 v7 @6 A- b3 \3 x Jstaticstruct class *my_class; staticstruct fasync_struct *fasync_queue; //异步通知队列 ! d; D7 d2 U1 Q, O) ?
#defineGPIO_NUM 1 //中断引脚为:GPIO1_1 staticunsigned int irq_num; 3 i5 T. L6 l/ k9 V- y! f& p
( S8 p8 t4 F* b d4 G5 r1 a
/* 打开 */ intpower_open(struct inode *inode,struct file *filp){ return 0; 4 |1 g+ }9 q% |+ r3 X
} 0 E2 J& L, I8 I& `' |7 I2 r
/* 关闭 */ intpower_release(struct inode *inode,struct file *filp){ return 0; } + y \+ U3 j- g5 C
ssize_tpower_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos){ k6 w, G2 j" R8 U
return count; }
) F1 P0 C3 Y4 V/ @ fssize_tpower_write(struct file *file,const char __user *buf,size_t count,loff_t*f_pos){
6 k9 W* s, ^ h7 ] return count; }
) W% h$ j' S# P/ [staticint my_fasync(int fd, struct file * filp, int on) { int retval; retval=fasync_helper(fd,filp,on,&fasync_queue); /*将该设备登记到fasync_queue队列中去*/ if(retval<0) return retval; return 0; } + p- u, |, A" q9 y' X! L4 [
staticconst struct file_operations simple_fops={ .owner=THIS_MODULE, .open=power_open, .release=power_release, .read=power_read, .write=power_write, .fasync=my_fasync, };
/ p- c4 q# g6 v8 c( D/* 在中断服务函数中向应用层发送消息-异步通知 */ 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; }
: B2 t) g/ y1 Gintpower_init_module(void){ int rtn; int ret; /* 注册设备驱动 */ ret =register_chrdev(power_MAJOR,"power-detect-test",&simple_fops); if(ret<0){ printk("Unable toregister character device %d!/n",ret); return ret; } 6 r& z% `5 ^% N
/* 自动创建设备节点 */ my_class = class_create(THIS_MODULE,"my_class"); device_create(my_class, NULL,MKDEV(power_MAJOR, 0), NULL,"powerdetect");
- N0 K, k: q2 `5 C /*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<0){ printk("gpio_direction_input()failed !\n"); } /*获取gpio中断号*/ irq_num = gpio_to_irq(GPIO_NUM); 4 L( g# e% o/ y; M1 m" R7 {
/*GPIO中断服务函数注册,*/ /*下降沿触发*/ rtn = request_irq(irq_num,irq_callback,IRQF_TRIGGER_FALLING,"my_irq", NULL); if (rtn<0) { printk("my_irq requestirq false\n"); } else { printk("my_irq requestirq success: %d\n",irq_num); }
0 b1 ?3 ?' q: p! W4 H1 e printk("module_initsucessful!!!\n"); return 0; } 5 c8 _+ p' E# W ~+ r0 h5 D, L) L
/* 卸载 */ voidpower_cleanup_module(void){ /* 卸载相应的设备驱动 */ unregister_chrdev(power_MAJOR,"power-detect-test"); device_destroy(my_class,MKDEV(power_MAJOR,0)); class_destroy(my_class); & x1 Q5 d' H# `! v
/*释放GPIO*/ gpio_free(GPIO_NUM); ' E; Q+ P/ [0 f- M
printk("module_exitsucessful!!!\n"); } ) ` n5 ^: k. P Y l( @( u% T
/* 宏实现 */ module_init(power_init_module); module_exit(power_cleanup_module);
2 A( H+ R: C, K" N3 ^! z) w! n' c) b/* 开源许可声明 */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Zou"); 应用代码: #include<stdio.h> #include<fcntl.h> #include<stdlib.h> #include<signal.h> #include<unistd.h> #include<fcntl.h> 9 a+ n; c O, k. r0 w5 C& ~
staticint fd; ) {- E7 f/ Q5 G+ k1 {
/* 内核产生异步通知,调用该应用层函数处理 */ voidsigterm_handler(int signo) { printf("app irq work !!!\n"); } . P* A5 W" q: n3 ?4 w1 R9 L/ [
intmain(void) { int oflags;
6 ~1 r+ y( B( ^ fd=open("/dev/powerdetect",O_RDWR); //打开设备文件
% C- ~$ w8 d9 L% i2 o7 F+ V, ] /* 启动异步通知信号驱动机制 */ signal(SIGIO, sigterm_handler); fcntl(fd, F_SETOWN, getpid()); oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | FASYNC); " d6 W, T' ?1 G2 m. O: @: Y
/*建立一个死循环,防止程序结束 */ while(1) { printf("sleep\n"); usleep(200000); //2ms }
- Y ?( A0 _; M0 o8 f: a2 ^ close(fd); return 0; } 将驱动编译成模块,上电加载并执行应用程序后,将电压缓慢下调至掉电临界点。触发GPIO下降沿中断,并提供应用程序掉电信号。 ![]() 图1..2掉电检测
7 d( D. t) \) c) q1 p1 A4 a5 y2 n$ m! e( }3 Q+ I
, @$ @( O* q% n( L; f5 N4 v
. [4 x$ y' R7 L
' V, H* W3 n* W9 L
4 z, N& x3 P3 i! b
" [# k% {& h' R! Z |