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>
" @/ W$ a0 ^) P( Y#include<asm/gpio.h> #include<linux/interrupt.h> #include<linux/irq.h> ! v; w9 e( \+ S) c4 l! G( G& w3 N3 J0 d
8 |7 \+ o4 i3 _3 R# f# M" \3 F
#definepower_MAJOR 200 / T% D: g' ^/ V' y! l$ @1 i j
staticstruct class *my_class; staticstruct fasync_struct *fasync_queue; //异步通知队列
5 Z! P% e6 L+ F1 B6 Y* i8 b$ @#defineGPIO_NUM 1 //中断引脚为:GPIO1_1 staticunsigned int irq_num;
# ] N& |% j" P
" B9 Z) F2 T2 U7 m. Q/* 打开 */ intpower_open(struct inode *inode,struct file *filp){ return 0; 4 W3 t5 k3 p7 N9 Z! R) I3 R
} - x4 m4 M1 \$ s8 B( t
/* 关闭 */ intpower_release(struct inode *inode,struct file *filp){ return 0; }
) M$ `- v0 @+ _+ t" |ssize_tpower_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos){
) o; Z' B- Z u& X9 Z return count; } 1 u- v, ^ H f' m: U. ~( `) D
ssize_tpower_write(struct file *file,const char __user *buf,size_t count,loff_t*f_pos){ $ q7 q; e9 t" P7 ]8 F; J
return count; }
' g) s; D9 [' j8 X Xstaticint 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; } * `7 Z/ M& l! j$ T; I- _$ o9 i
staticconst struct file_operations simple_fops={ .owner=THIS_MODULE, .open=power_open, .release=power_release, .read=power_read, .write=power_write, .fasync=my_fasync, };
E+ r4 |' _) T6 @& V; @/ v/ N0 c/* 在中断服务函数中向应用层发送消息-异步通知 */ 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; }
: [* X6 A( w: A( { tintpower_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; }
* K5 o, C# Y3 o+ s3 I /* 自动创建设备节点 */ my_class = class_create(THIS_MODULE,"my_class"); device_create(my_class, NULL,MKDEV(power_MAJOR, 0), NULL,"powerdetect");
/ g# P! W( T. \ /*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);
9 A5 u) l! k" q7 U /*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); }
6 c* P% H* `, {0 X0 c f$ _ printk("module_initsucessful!!!\n"); return 0; } 8 b3 c6 N* }- ?
/* 卸载 */ voidpower_cleanup_module(void){ /* 卸载相应的设备驱动 */ unregister_chrdev(power_MAJOR,"power-detect-test"); device_destroy(my_class,MKDEV(power_MAJOR,0)); class_destroy(my_class);
7 o: e& q! @: b( X2 \ /*释放GPIO*/ gpio_free(GPIO_NUM); , _- r5 a. L; t; z" ]
printk("module_exitsucessful!!!\n"); } 5 |% F/ ]" l+ E6 B" a
/* 宏实现 */ module_init(power_init_module); module_exit(power_cleanup_module);
! h! q7 K( d: z$ w1 r& _; ` {/* 开源许可声明 */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Zou"); 应用代码: #include<stdio.h> #include<fcntl.h> #include<stdlib.h> #include<signal.h> #include<unistd.h> #include<fcntl.h>
0 f) m- D$ W! I8 _; Istaticint fd;
( g% K% f7 L# ^+ l3 M& I. r/* 内核产生异步通知,调用该应用层函数处理 */ voidsigterm_handler(int signo) { printf("app irq work !!!\n"); } , W3 b1 M( ]5 _2 `3 |3 e1 n! x1 N
intmain(void) { int oflags; 3 c5 ~$ M }0 h. M* c
fd=open("/dev/powerdetect",O_RDWR); //打开设备文件 / a0 F" z/ s* P
/* 启动异步通知信号驱动机制 */ signal(SIGIO, sigterm_handler); fcntl(fd, F_SETOWN, getpid()); oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | FASYNC);
& ^2 W) |, t6 f* a5 h3 E /*建立一个死循环,防止程序结束 */ while(1) { printf("sleep\n"); usleep(200000); //2ms }
3 L' e, L$ L0 i; P: ` close(fd); return 0; } 将驱动编译成模块,上电加载并执行应用程序后,将电压缓慢下调至掉电临界点。触发GPIO下降沿中断,并提供应用程序掉电信号。 ![]() 图1..2掉电检测
: R' c% {4 \( O8 i
/ v4 w2 H3 j6 D4 B7 ?% R3 R0 V" r! \- e* l5 \: z+ V
# y. z. [7 |2 X% V: `
' M1 h) U2 h& c! r G; S
1 B7 ^6 X. G# t6 }# G" G* X+ w1 n- U' `/ Q, }! i( Y% o9 ?- s
|