基于i.MX6ULL的掉电检测设计与软件测试

2023年11月09日 11:08    发布者:武汉万象奥科
基于i.MX6ULL的掉电检测设计与软件测试基于i.MX6ULL平台设计实现掉电检测功能,首先选择一路IO,利用IO电平变化触发中断,在编写驱动时捕获该路GPIO的中断,然后在中断响应函数中发送信号通知应用程序掉电发生了。https://18821080.s21i.faiusr.com/4/ABUIABAEGAAgt-ywqgYoyIab-wUwgwU4iwI.png图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_1staticunsigned 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<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,};
/* 在中断服务函数中向应用层发送消息-异步通知 */ 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<0){                  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<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_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下降沿中断,并提供应用程序掉电信号。https://18821080.s21i.faiusr.com/4/ABUIABAEGAAguvywqgYontajkwIwxgU4lQM.png​图1..2掉电检测