基于i.MX6ULL的掉電檢測設(shè)計(jì)與軟件測試 基于i.MX6ULL平臺(tái)設(shè)計(jì)實(shí)現(xiàn)掉電檢測功能,首先選擇一路IO,利用IO電平變化觸發(fā)中斷,在編寫驅(qū)動(dòng)時(shí)捕獲該路GPIO的中斷,然后在中斷響應(yīng)函數(shù)中發(fā)送信號(hào)通知應(yīng)用程序掉電發(fā)生了。 圖1.1掉電信號(hào)IO 驅(qū)動(dòng)代碼: #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; //異步通知隊(duì)列 #defineGPIO_NUM 1 //中斷引腳為:GPIO1_1 staticunsigned int irq_num; /* 打開 */ intpower_open(struct inode *inode,struct file *filp){ return 0; } /* 關(guān)閉 */ 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); /*將該設(shè)備登記到fasync_queue隊(duì)列中去*/ if(retval<0) 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, }; /* 在中斷服務(wù)函數(shù)中向應(yīng)用層發(fā)送消息-異步通知 */ 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; /* 注冊設(shè)備驅(qū)動(dòng) */ ret =register_chrdev(power_MAJOR,"power-detect-test",&simple_fops); if(ret<0){ printk("Unable toregister character device %d!/n",ret); return ret; } /* 自動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn) */ 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<0){ printk("gpio_direction_input()failed !\n"); } /*獲取gpio中斷號(hào)*/ irq_num = gpio_to_irq(GPIO_NUM); /*GPIO中斷服務(wù)函數(shù)注冊,*/ /*下降沿觸發(fā)*/ 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); } printk("module_initsucessful!!!\n"); return 0; } /* 卸載 */ voidpower_cleanup_module(void){ /* 卸載相應(yīng)的設(shè)備驅(qū)動(dòng) */ 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"); } /* 宏實(shí)現(xiàn) */ module_init(power_init_module); module_exit(power_cleanup_module); /* 開源許可聲明 */ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Zou"); 應(yīng)用代碼: #include #include #include #include #include #include staticint fd; /* 內(nèi)核產(chǎn)生異步通知,調(diào)用該應(yīng)用層函數(shù)處理 */ voidsigterm_handler(int signo) { printf("app irq work !!!\n"); } intmain(void) { int oflags; fd=open("/dev/powerdetect",O_RDWR); //打開設(shè)備文件 /* 啟動(dòng)異步通知信號(hào)驅(qū)動(dòng)機(jī)制 */ signal(SIGIO, sigterm_handler); fcntl(fd, F_SETOWN, getpid()); oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | FASYNC); /*建立一個(gè)死循環(huán),防止程序結(jié)束 */ while(1) { printf("sleep\n"); usleep(200000); //2ms } close(fd); return 0; } 將驅(qū)動(dòng)編譯成模塊,上電加載并執(zhí)行應(yīng)用程序后,將電壓緩慢下調(diào)至掉電臨界點(diǎn)。觸發(fā)GPIO下降沿中斷,并提供應(yīng)用程序掉電信號(hào)。 圖1..2掉電檢測 |