/************************************************************* 基于tq2440开发板,内核2.6.30 功能 能实现定时器0 的中断函数。 定时器的中断让led 闪烁 2012年7月15日13:14:02 **************************************************************/ #include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h> #include <linux/pci.h> #include <linux/poll.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/clk.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/atomic.h> #include <asm/unistd.h> #include <plat/regs-timer.h> #define DEVICE_NAME "driver_time" volatile unsigned long *gpbcon = NULL; volatile unsigned long *gpbdat = NULL; volatile unsigned long *tcfg0 = NULL; //用来设置预分频 volatile unsigned long *tcfg1 = NULL; //用来设置分频 volatile unsigned long *tcon = NULL; //定时器控制器 volatile unsigned long *tcntb0 = NULL; //计数缓冲寄存器 volatile unsigned long *tcmpb0 = NULL; //比较缓冲寄存器 volatile unsigned long *tcnto0 = NULL; //计数观察寄存器 volatile unsigned long *gpfcon = NULL; volatile unsigned long *gpfdat = NULL; volatile unsigned long *srcpnd = NULL; volatile unsigned long *intmask = NULL; volatile unsigned long *intpnd = NULL; volatile unsigned long *intoffset = NULL; static irqreturn_t irq_interrupt(int irq, int dev_id) { //*gpbcon &=~(3<<0*2); //*gpbcon |= (2<<0*2); //设置b0 为 tout0 static unsigned int irq_count; irq_count++; printk("in irq_interrupt %d\n",irq_count); if(irq_count%2) *gpbdat &= ~((1<<5) ); else *gpbdat |= ((1<<5) ); return IRQ_RETVAL(IRQ_HANDLED); } // ------------------- OPEN ------------------------ ssize_t drive_open (struct inode * inode ,struct file * file) { *gpbcon &= ~((0x3<<(5*2)) | (0x3<<(6*2)) | (0x3<<(7*2)) | (0x3<<(8*2)));//清零 *gpbcon |= ((0x1<<(5*2)) | (0x1<<(6*2)) | (0x1<<(7*2)) | (0x1<<(8*2)));//设置成输出 request_irq(IRQ_TIMER0, irq_interrupt, IRQ_TYPE_EDGE_FALLING, "TIME0", NULL); printk("-----------------drive open ok----------------\n"); return 0; } // ------------------- RELEASE/CLOSE --------------- ssize_t drive_release (struct inode * inode ,struct file * file) { free_irq(IRQ_TIMER0, NULL); printk("-----------------drive close ok----------------\n"); return 0; } // ------------------- READ ------------------------ ssize_t drive_read (struct file * file ,char * buf, size_t count, loff_t * f_ops) { printk("-----------------drive read ok----------------\n"); //copy_to_user( buf,(const void *)press_cnt,sizeof(press_cnt) ); return 0; } // ------------------- WRITE ----------------------- ssize_t drive_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) { printk("-----------------drive write ok----------------\n"); return 0; } // ------------------- IOCTL ----------------------- ssize_t drive_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, unsigned long arg) { struct clk *clk_p; unsigned int pclk; unsigned int tcnt; printk("-----------------drive ioctl ok----------------\n"); //定时器时钟频率=pclk /( 预分频器的值+1) / 分频器 //62.5k *tcfg0 &= ~0xff; //定时器0预分配清零 *tcfg0 |=(50-1); //预分频 50 *tcfg1 &= ~0xf; //定时器0 mux 输入分频清零 *tcfg1 |=3; //mux 分频 16 clk_p = clk_get(NULL, "pclk"); pclk = clk_get_rate(clk_p); tcnt = (pclk/50/16)/10; printk("pclk = %d\n",pclk); printk("tcnt = %d\n",tcnt); *tcntb0 &=0x0000; //16位寄存器 *tcmpb0 &=0x0000; *tcntb0 |= 1000; *tcmpb0|=500; //*tcon &=0x0; // printk("tcon=%d\n",*tcon); printk("tcntb0=%d\n",*tcntb0); printk("tcmpb0=%d\n",*tcmpb0); *tcon &= ~0x1f; //清零 // printk("tcon=%d\n",*tcon); msleep(10); //第一次必须手动更新 *tcon |= 0xb; //关闭死区、自动重载、关反相器、手动更新TCNTB0&TCMPB0、启动定时器0 //1011 //printk("tcon=%d\n",*tcon); msleep(10); *tcon &= ~2; //清除定时器0的手动更新位 //printk("tcon=%d\n",*tcon); printk("tcfg0=%d\n",*tcfg0); printk("tcfg1=%d\n",*tcfg1); printk("tcntb0=%d\n",*tcntb0); printk("tcmpb0=%d\n",*tcmpb0); printk("tcon=%d\n",*tcon); return 0; } // ------------------------------------------------- static struct file_operations drive_ops ={ .owner = THIS_MODULE, .open = drive_open, .read = drive_read, .write = drive_write, .ioctl = drive_ioctl, .release = drive_release, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &drive_ops, }; static int __init init_drive(void) { int ret; ret = misc_register(&misc); gpbcon = (volatile unsigned long *)ioremap(0x56000010,32); gpbdat = (volatile unsigned long *)ioremap(0x56000014, 32); tcfg0 = (volatile unsigned long *)ioremap(0x51000000, 4); tcfg1 = (volatile unsigned long *)ioremap(0x51000004, 4); tcon = (volatile unsigned long *)ioremap(0x51000008, 4); tcntb0 = (volatile unsigned long *)ioremap(0x5100000c, 4); tcmpb0 = (volatile unsigned long *)ioremap(0x51000010, 4); tcnto0 = (volatile unsigned long *)ioremap(0x51000014, 4); gpfcon = (volatile unsigned long *)ioremap(0x56000050, 4); gpfdat = (volatile unsigned long *)ioremap(0x56000054, 4); srcpnd = (volatile unsigned long *)ioremap(0x4a000000, 4); intmask= (volatile unsigned long *)ioremap(0x4a000008, 4); intpnd = (volatile unsigned long *)ioremap(0x4a000010, 4); intoffset=(volatile unsigned long *)ioremap(0x4a000014, 4); printk("-----------------drive button init ok----------------\n"); return 0; } static void __exit exit_drive(void) { *tcon &=~1; misc_deregister(&misc); printk("-----------------drive button exit ok----------------\n"); } module_init(init_drive); module_exit(exit_drive); MODULE_LICENSE("GPL"); //-----------------------------应用程序---------------------------------------------- #include <stdio.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> // open() close() #include <unistd.h> // read() write() #define DEVICE_NAME "/dev/driver_time" //------------------------------------- main --------------------------------------------- int main(int argc, char **argv) { int fd,ret; fd = open(DEVICE_NAME, O_RDWR); if (fd == -1) { printf("can't open device mknod %s c zhu ci \n",DEVICE_NAME); return 0; } ioctl(fd, 1); while(1) { ; } // close ret = close(fd); return 0; }// end main |
|