分享

tq2440 time0 led 定时器控制led闪烁 驱动

 汉江秋月夜 2012-10-31

tq2440 time0 led 定时器控制led闪烁 驱动  

2012-07-15 13:15:46|  分类: ARM |字号 订阅

/*************************************************************
基于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




分享到:        
阅读(41)| 评论(0)| 转载 (0) |举报

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约