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

基于i.MX6ULL平台设计实现掉电检测功能,首先选择一路IO,利用IO电平变化触发中断,在编写驱动时捕获该路GPIO的中断,然后在中断响应函数中发送信号通知应用程序掉电发生了。

基于i.MX6ULL的掉电检测设计与软件测试_第1张图片

图 1.1 掉电信号IO

       驱动代码:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

#include    

#include

#include

 

#define power_MAJOR 200

 

static struct class *my_class;

static struct fasync_struct *fasync_queue; //异步通知队列

 

#define GPIO_NUM 1  //中断引脚为:GPIO1_1

static unsigned int irq_num;

                                                                                         

/* 打开 */

int power_open(struct inode *inode,struct file *filp){

         return 0;

 

}

 

/* 关闭 */

int power_release(struct inode *inode,struct file *filp){

         return 0;

}

 

ssize_t power_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos){

 

         return count;

}

 

ssize_t power_write(struct file *file,const char __user *buf,size_t count,loff_t *f_pos){

 

         return count;

}

 

static int 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;

}

static const struct file_operations simple_fops={

         .owner=THIS_MODULE,

         .open=power_open,

         .release=power_release,

    .read=power_read,

         .write=power_write,

    .fasync=my_fasync,

};

 

/* 在中断服务函数中向应用层发送消息-异步通知 */

static irqreturn_t irq_callback (int irqno, void *dev_id){

                  printk("irq power-detect working !\n");

                  if (fasync_queue) {

            kill_fasync(&fasync_queue, SIGIO, POLL_IN);

                  }

         return IRQ_HANDLED;

}

 

int power_init_module(void){

         int rtn;

         int ret;

         /* 注册设备驱动 */

         ret = register_chrdev(power_MAJOR,"power-detect-test",&simple_fops);

         if(ret<0){

                  printk("Unable to register 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 pin request 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 request irq false\n");

         } else {

                  printk("my_irq request irq success: %d\n",irq_num);

         }

        

    printk("module_init sucessful!!!\n");

         return 0;

}

 

/* 卸载 */

void power_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_exit sucessful!!!\n");

}

 

/* 宏实现 */

module_init(power_init_module);

module_exit(power_cleanup_module);

 

/* 开源许可声明 */ 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Zou");

 应用代码:

#include

#include

#include

#include

#include

#include

 

static int fd;

 

/* 内核产生异步通知,调用该应用层函数处理 */

void sigterm_handler(int signo)

{

         printf("app irq work !!!\n");

}

 

int main(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下降沿中断,并提供应用程序掉电信号。

基于i.MX6ULL的掉电检测设计与软件测试_第2张图片

图1..2 掉电检测

你可能感兴趣的:(功能测试,掉电检测,软件测试)