主题 : 关于mini6410linnux定时器驱动的问题 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 20321
精华: 0
发帖: 15
金钱: 75 两
威望: 15 点
贡献值: 0 点
综合积分: 30 分
注册时间: 2010-04-29
最后登录: 2012-02-19
楼主  发表于: 2011-03-10 10:12

 关于mini6410linnux定时器驱动的问题

我现在想利用用板子的pwm功能,但是接口都被占用,因此想利用IO口输出PWM,昨天写了个内核的定时器驱动,但是应用是发现频率只能到200Hz,不能达到我的要求,所以想写一个6410的定时器驱动,我之前有个mini2440的驱动,移植时经常发生错误,现在想写了mini6410的,希望版主给个mini6410定时器的实例。
级别: 新手上路
UID: 20321
精华: 0
发帖: 15
金钱: 75 两
威望: 15 点
贡献值: 0 点
综合积分: 30 分
注册时间: 2010-04-29
最后登录: 2012-02-19
1楼  发表于: 2011-03-10 10:17
这是昨天写的内核定时器驱动,分享一下


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>

#include <plat/gpio-cfg.h>
#include <plat/regs-clock.h>
#include <plat/regs-gpio.h>

#include <plat/gpio-bank-e.h>
#include <plat/gpio-bank-f.h>
#include <plat/gpio-bank-k.h>
#include <linux/timer.h>

#define DEVICE_NAME "pwmtimer"
int PWMTIMER_MAJOR=277;
/*定时器生成pwm驱动设备结构体*/
struct pwmtimer_dev{
    struct cdev cdev;
    atomic_t counter;
    struct timer_list pwm_timer;
};

struct pwmtimer_dev *pwmtimerdev;
unsigned int time=0;
unsigned int pwm[2]={10,10};
unsigned int tmp=0;

/*定时器中断处理函数*/
static void pwm_timer_irq(unsigned long data){
    mod_timer(&pwmtimerdev->pwm_timer ,jiffies +1);
    atomic_inc(&pwmtimerdev->counter);
    printk("%ld timer is working! HZ is %d\n",jiffies,HZ);
    {
           time++;
     if(time ==pwm[0])
     {
        tmp = readl(S3C64XX_GPEDAT);
        tmp |= (0x4);
        writel(tmp, S3C64XX_GPEDAT);
      
     }
     if(time ==pwm[1])
     {
        tmp = readl(S3C64XX_GPEDAT);
        tmp |= (0x8);
        writel(tmp, S3C64XX_GPEDAT);
      
     }
     if(time ==20)
    {
        tmp = readl(S3C64XX_GPEDAT);
        tmp &= ~(0xc);
        writel(tmp, S3C64XX_GPEDAT);
        time=0;
    }
      
      
    }
}
/*文件打开函数*/
static int pwmtimer_open(struct inode *inode , struct file *file){
    init_timer(&pwmtimerdev->pwm_timer);//初始化定时器
    pwmtimerdev->pwm_timer.function = &pwm_timer_irq;//设置中断函数
    pwmtimerdev->pwm_timer.expires = jiffies +HZ;//设置定时器的溢出时间
    
    add_timer(&pwmtimerdev->pwm_timer);//注册定时器
    atomic_set(&pwmtimerdev->counter , 0);//counter清零
    printk("open is working success!\n");
    return 0;
}
/*文件释放函数*/
static int pwmtimer_release(struct inode *inode , struct file *file){
    printk("release is working!\n");
    del_timer(&pwmtimerdev->pwm_timer);  
    return 0;
}
/*ioctl函数*/
static int pwmtimer_ioctl(struct inode *inode , struct file *file , unsigned int cmd , unsigned long arg){

    return 0;
}
static ssize_t pwmtimer_read(struct file *file , char __user *buf ,size_t count , loff_t *ppos){
    
    int counter;
    counter = atomic_read(&pwmtimerdev->counter);
    if(put_user(counter, (int*)buf))
    {
        //printk("read is working success!\n");
        return - EFAULT;
    }
    else
    {
        //printk("read is working fail!\n");
        return sizeof(unsigned int);  
    }
    
}
/*文件操作结构体*/
static const struct file_operations pwmtimer_fops = {
    .owner = THIS_MODULE,
    .open = pwmtimer_open,
    .release = pwmtimer_release,
    .ioctl = pwmtimer_ioctl,
    .read = pwmtimer_read,
};
/*初始化并注册cdev*/
static void pwmtimer_init_cdev(struct pwmtimer_dev *dev , int index){
    int error , devno =MKDEV(PWMTIMER_MAJOR , index);
    cdev_init(&dev->cdev , &pwmtimer_fops);
    dev->cdev.owner = THIS_MODULE;
    dev->cdev.ops = &pwmtimer_fops;
    error = cdev_add(&dev->cdev , devno , 1);
    if(error)
        printk(KERN_NOTICE "Error %d adding LED %d\n" , error , index);  
}
/*设备驱动模块初始化函数*/
static int pwmtimer_init(void){
    int ret;
    dev_t devno = MKDEV(PWMTIMER_MAJOR , 0);
    
    /*申请设备号*/
    if(PWMTIMER_MAJOR)
        ret=register_chrdev_region(devno , 1 ,"pwmtimer");
    else
    {
        ret = alloc_chrdev_region(&devno , 0 ,1 ,"pwmtimer");
        PWMTIMER_MAJOR = MAJOR(devno);
    }
    if(ret<0)
        return ret;
    pwmtimerdev = kmalloc(sizeof(struct pwmtimer_dev) , GFP_KERNEL);
    if(!pwmtimerdev)
    {
        ret = - ENOMEM;
        unregister_chrdev_region(devno , 1);
        return -1;
    }
    memset(pwmtimerdev , 0 , sizeof(struct pwmtimer_dev));
    pwmtimer_init_cdev(pwmtimerdev , 0);
    printk("init pwmtimerdev success!\n");
    printk("MAJOR is %d!\n",PWMTIMER_MAJOR);
    
    {
          unsigned temp;
        temp = readl(S3C64XX_GPECON);
        temp = (temp & ~(0xffU<<8))|(0x11U<<8);
        writel(temp, S3C64XX_GPECON);
        
        temp = readl(S3C64XX_GPEDAT);
        temp |= (0xc);
        writel(temp, S3C64XX_GPEDAT);
    }
    return 0;
}
/*模块卸载函数*/
void pwmtimer_exit(void){
    cdev_del(&pwmtimerdev->cdev);//注销cdev
    kfree(pwmtimerdev);//释放设备结构体内存
    unregister_chrdev_region(MKDEV(PWMTIMER_MAJOR , 0) , 1);//释放设备号
}

MODULE_AUTHOR("GaoFeng's email is gfpeak@gmail.com");
MODULE_LICENSE("GPL");

module_init(pwmtimer_init);
module_exit(pwmtimer_exit);
级别: 新手上路
UID: 20321
精华: 0
发帖: 15
金钱: 75 两
威望: 15 点
贡献值: 0 点
综合积分: 30 分
注册时间: 2010-04-29
最后登录: 2012-02-19
2楼  发表于: 2011-03-14 13:56
以解决,有需要的联系我