nuc977 linux 定时器驱动

32 篇文章 8 订阅

 

drv_timer.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/delay.h>

#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gcr.h>

#include <mach/irqs.h>
#include <linux/fs.h>
#include <linux/cdev.h>

#include <linux/uaccess.h> // copy_from_user



#define TIMER_CNT 1 /* 设备号个数 */
#define TIMER_NAME "timer" /* 名字 */
#define CLOSE_CMD (_IO(0xEF,0x1)) /* 关闭定时器 */
#define OPEN_CMD (_IO(0xEF,0x2)) /* 打开定时器 */
#define SETPERIOD_CMD (_IO(0xEF,0x3)) /* 设置定时器周期命令 */
#define LEDON	1   /* 开灯*/
#define LEDOFF	0   /* 关灯*/




/* timer 设备结构体 */
struct timer_dev{
	dev_t devid; /* 设备号 */
	struct cdev cdev; /* cdev */
	struct class *class; /* 类 */
	struct device *device; /* 设备 */
	int major; /* 主设备号 */
	int minor; /* 次设备号 */

	//struct device_node *nd; /* 设备节点*/
	//int led_gpio; /* led 使用的gpio编号*/

	int timeperiod; /* 定时周期,单位为ms*/
	struct timer_list timer; /* 定义一个定时器*/
	
};


struct timer_dev timerdev; /* timer 设备 */



static int nuc977_timer_open(struct inode *ino, struct file *file)
{
	file->private_data = &timerdev; /* 设置私有数据 */
	
	timerdev.timeperiod=1000; /*1000 ms*/	
	
	return 0;
}





static long nuc977_timer_unlock_ioctl( struct file *files, unsigned int cmd, unsigned long arg)
{
	printk("cmd is %d,arg is %d \n",cmd,(unsigned int)(arg));

	struct timer_dev *dev= (struct timer_dev *)files->private_data;
	int timerperiod;
	//unsigned long flags;
	
	switch(cmd)
	{
		case CLOSE_CMD:  /* 关闭定时器*/
			{
				printk(KERN_INFO "CLOSE_CMD \n");
				del_timer_sync(&dev->timer);
				
				break;		
			}
			
		case OPEN_CMD:	/* 打开定时器*/
			{
				printk(KERN_INFO "OPEN_CMD \n");	
				//gpio_set_value(NUC970_PB0, 1);
				timerperiod=dev->timeperiod;
				mod_timer(&dev->timer,jiffies+msecs_to_jiffies(timerperiod));
				
				break;		
			}

		case SETPERIOD_CMD:  /* 设定定时器周期 */
			dev->timeperiod=arg;
			mod_timer(&dev->timer,jiffies+msecs_to_jiffies(arg));
		break;
		
		

	}
	return 0;
}


/*定时器回调函数 */
void timer_function(unsigned long arg)
{
	struct timer_dev *dev = (struct timer_dev *)arg;
	static int sta=1;
	//int timerperiod;
	//unsigned long flags;

	sta=!sta;  /*取反 led反转*/

    gpio_set_value(NUC970_PB0, sta);	

	/* 重启定时器*/
	//timerperiod=dev->timeperiod;
	mod_timer(&dev->timer,jiffies+msecs_to_jiffies(dev->timeperiod));
	

}






/* 设备操作函数 */
static struct file_operations timer_fops = {
	.owner = THIS_MODULE,
	.open = nuc977_timer_open,
	.unlocked_ioctl = nuc977_timer_unlock_ioctl,	
};




static int __init nuc977_timer_init(void)
{
 
	
	u32 ret;
	ret = gpio_request(NUC970_PB0,"NUC970_PB0");
	if(ret < 0){
		printk(KERN_EMERG "gpio_request NUC970_PB0 failed!\n");
		return ret; 
	}	
	gpio_direction_output(NUC970_PB0,1);
	


	/* 注册字符设备驱动 */
	/* 1、创建设备号 */
	if (timerdev.major) { /* 定义了设备号 */
		timerdev.devid = MKDEV(timerdev.major, 0);
		register_chrdev_region(timerdev.devid, TIMER_CNT,TIMER_NAME);
	}
	else 
	{ /* 没有定义设备号 */
		alloc_chrdev_region(&timerdev.devid, 0, TIMER_CNT,	TIMER_NAME); /* 申请设备号 */
		timerdev.major = MAJOR(timerdev.devid); /* 获取主设备号 */
		timerdev.minor = MINOR(timerdev.devid); /* 获取次设备号 */
	}
	printk("timerdev major=%d,minor=%d\r\n",timerdev.major,timerdev.minor);


	/* 2、初始化 cdev */
	timerdev.cdev.owner = THIS_MODULE;
	cdev_init(&timerdev.cdev, &timer_fops);

	/* 3、添加一个 cdev */
	cdev_add(&timerdev.cdev, timerdev.devid, TIMER_CNT);

	/* 4、创建类 */
	timerdev.class = class_create(THIS_MODULE, TIMER_NAME);
	if (IS_ERR(timerdev.class)) {
		return PTR_ERR(timerdev.class);
	}

	/* 5、创建设备 */
	timerdev.device = device_create(timerdev.class, NULL,
	timerdev.devid, NULL, TIMER_NAME);
	if (IS_ERR(timerdev.device)) {
		return PTR_ERR(timerdev.device);
	}

	/*6. 初始化timer,设置定时器处理函数,还未设置周期,所以不会激活定时器*/
	init_timer(&timerdev.timer);
	timerdev.timer.function=timer_function;
	timerdev.timer.data=(unsigned long)&timerdev;
	
	printk(KERN_INFO "nuc977_timer_init module initialized\n");

	return 0;
}

static void __exit nuc977_timer_exit(void)
{

	del_timer_sync(&timerdev.timer);/*  删除定时器*/

	/* 注销字符设备 */
	cdev_del(&timerdev.cdev);/* 删除 cdev */
	unregister_chrdev_region(timerdev.devid, TIMER_CNT);

	device_destroy(timerdev.class, timerdev.devid);
	class_destroy(timerdev.class);
	
	printk(KERN_INFO "nuc977_timer_exit module exited\n");
	
}

module_init(nuc977_timer_init);
module_exit(nuc977_timer_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HBIN");







app_timer.c

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "string.h"

#include "linux/ioctl.h"



#define CLOSE_CMD (_IO(0xEF,0x1)) /* 关闭定时器 */
#define OPEN_CMD (_IO(0xEF,0x2)) /* 打开定时器 */
#define SETPERIOD_CMD (_IO(0xEF,0x3)) /* 设置定时器周期命令 */



int main(int argc, char *argv[])
{   
	int fd ,ret,i;
	char *filename;
	unsigned int cmd;
	//unsigned int period;
	unsigned int arg=1000;
	unsigned char databuf[1];
	//unsigned int buf[1];

	if (argc < 3){
			printf("Error Usage!");
			return -1;
	}

	for(i=0;i<argc;i++)
		printf(" argv[%d]= %s \n",i,argv[i]);	
	
	
	filename=argv[1];
	fd = open(filename, O_RDWR);  // 打开设备
	if (fd < 0) {
	    printf("Can't open  %s \n",argv[1]);
	    return -1;
	}


	databuf[0] = atoi(argv[2]); /* 要执行的操作:cmd */
	

	if (argc == 3)
	{
		if (databuf[0]==1)
		{
			 printf("1:  databuf[0]  %d \n",databuf[0]);
			 cmd = CLOSE_CMD;
			 ioctl(fd,cmd,arg);
		}		
		else if (databuf[0]==2)
		{
			 printf("2:  databuf[0]  %d \n",databuf[0]);
			 cmd = OPEN_CMD;
			 ioctl(fd,cmd,arg);
		}

	}
	else if (argc == 4)
	{
		cmd = SETPERIOD_CMD;
		//databuf[0] = atoi(argv[3]);//*100
		//arg=databuf[0]*100;

		arg= atoi(argv[3]);
		ioctl(fd,cmd,arg);

	}

	close(fd);

	return 0;
}




 

 argv[i]= 3000 
/mnt/app # ./app_timer2 /dev/timer 3 10
 argv[i]= ./cmd is 61187,arg is 10 
app_timer2 
 argv[i]= /dev/timer 
 argv[i]= 3 
 argv[i]= 10 
/mnt/app # ./app_timer2 /dev/timer 3 100
 argv[i]= ./cmd is 61187,arg is 100 
app_timer2 
 argv[i]= /dev/timer 
 argv[i]= 3 
 argv[i]= 100 
/mnt/app # ./app_timer2 /dev/timer 3 50
 argv[i]= ./cmd is 61187,arg is 50 
app_timer2 
 argv[i]= /dev/timer 
 argv[i]= 3 
 argv[i]= 50 
/mnt/app # ./app_timer2 /dev/timer 3 300
 argv[i]= ./cmd is 61187,arg is 300 
app_timer2 
 argv[i]= /dev/timer 
 argv[i]= 3 
 argv[i]= 300 
/mnt/app # ./app_timer2 /dev/timer 3 1000
 argv[i]= ./cmd is 61187,arg is 1000 

测试led闪烁成功。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值