Chinaunix首页 | 论坛 | 博客
  • 博客访问: 120002
  • 博文数量: 24
  • 博客积分: 616
  • 博客等级: 中士
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-01 10:54
文章分类
文章存档

2012年(24)

我的朋友

分类: LINUX

2012-08-01 16:46:29

平台:MICRO2440
内核:LINUX2.6.32.2
编译器版本:4.4.3
操作系统:Ubuntu10.04
 
 
 
一、驱动程序:
 

/*********************************
**        TIMER0 驱动程序       **
*********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "s3c24xx-adc.h"
#define DEVICE_NAME "timer0_micro2440_drv"
static void __iomem *base_addr;
#define MINI2440_TCFG0      (*(volatile unsigned long *)(base_addr + 0)) //定时器配置寄存器0
#define MINI2440_TCFG1      (*(volatile unsigned long *)(base_addr+4))//定时器配置寄存器1
#define MINI2440_TCON       (*(volatile unsigned long *)(base_addr+8))//定时器控制寄存器1
#define MINI2440_TCNTB0     (*(volatile unsigned long *)(base_addr+0x0c))//定时器0计数缓冲寄存器
#define MINI2440_TCMPB0     (*(volatile unsigned long *)(base_addr+0x10))//定时器0比较缓冲寄存器
#define MINI2440_TCNTO0     (*(volatile unsigned long *)(base_addr+0x14))//定时器0计数监视寄存器
#define MINI2440_TCNTB1     (*(volatile unsigned long *)(base_addr+0x18))//定时器1计数缓冲寄存器
#define MINI2440_TCMPB1     (*(volatile unsigned long *)(base_addr+0x1c))//定时器1比较缓冲寄存器
#define MINI2440_TCNTO1     (*(volatile unsigned long *)(base_addr+0x20))//定时器1计数监测寄存器
#define MINI2440_TCNTB2     (*(volatile unsigned long *)(base_addr+0x24))//定时器2计数缓冲寄存器
#define MINI2440_TCMPB2     (*(volatile unsigned long *)(base_addr+0x28))//定时器2比较缓冲寄存器
#define MINI2440_TCNTO2     (*(volatile unsigned long *)(base_addr+0x2c))//定时器2计数监测寄存器
#define MINI2440_TCNTB3     (*(volatile unsigned long *)(base_addr+0x30))//定时器3计数缓冲寄存器
#define MINI2440_TCMPB3     (*(volatile unsigned long *)(base_addr+0x34))//定时器3比较缓冲寄存器
#define MINI2440_TCNTO3     (*(volatile unsigned long *)(base_addr+0x38))//定时器3计数监测寄存器
#define MINI2440_TCNTB4     (*(volatile unsigned long *)(base_addr+0x3c))//定时器4计数缓冲寄存器
#define MINI2440_TCNTO4     (*(volatile unsigned long *)(base_addr+0x40))//定时器4计数监测寄存器
static struct semaphore lock;
typedef struct {
 wait_queue_head_t wait;
}ADC_DEV;
static ADC_DEV adcdev;
static volatile int ev_adc = 0;
struct clk *clock;
unsigned long pclk;
static irqreturn_t timer0_interupt_handler(int irq, void *dev_id)
{
 
    ev_adc = 1;
     wake_up_interruptible(&adcdev.wait);
    return IRQ_HANDLED;
}
static timer0_micro2440_start(void)
{
 //struct clk *clk_p;
 //unsigned long pclk;
 base_addr=ioremap(0x51000000,0x20);
 clock = clk_get(NULL, "pclk");//获取PCLK
 clk_enable(clock);
 pclk  = clk_get_rate(clock);
 MINI2440_TCFG0=(MINI2440_TCFG0&(~0xff))|249;
 MINI2440_TCFG1=0x0001;
 MINI2440_TCNTB0=(pclk/250)/4;
 MINI2440_TCMPB0=0;
 MINI2440_TCON=0x02;//注意在此一定手动更新一下,否则定时器瘫痪
 MINI2440_TCON=0x08;
 MINI2440_TCON=MINI2440_TCON|0x01;//启动定时器
  request_irq(IRQ_TIMER0,timer0_interupt_handler,IRQF_SHARED|IRQF_SAMPLE_RANDOM,DEVICE_NAME,&adcdev);
  init_waitqueue_head(&(adcdev.wait));
}
static timer0_micro2440_stop(void)
{
  //1.注销中断
    free_irq(IRQ_TIMER0,&adcdev);
    //2.取消寄存器映射
    iounmap(base_addr);
    //3.停止ADC时钟
    clk_disable(clock);
    clk_put(clock);
    clock=NULL;
    MINI2440_TCON=MINI2440_TCON&(~0x01);//关闭定时器
}
static int timer0_open(struct inode *inode,struct file *file)
{
       int ret;
       ret=down_trylock(&lock);
       if(ret==0)
       {
           timer0_micro2440_start();
           return 0;
       }       
      else
        return -EBUSY;
     
 } 
static int timer0_close(struct inode *inodep,struct file *file)
{
     timer0_micro2440_stop();
      up(&lock);//释放互斥锁
     return 0;
}
static ssize_t timer0_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
   char str[10];
   long int value;
   size_t len;
   if(ev_adc==1)
   {
       value=1;
       wait_event_interruptible(adcdev.wait, ev_adc);
       ev_adc = 0;
   }
   else
   {
       value=0;
   }
  
  
  up(&lock);
   len = sprintf(str, "%d\n", value);//将value打印成一个字符串保存在str中
   if (count >= len) {
      int r = copy_to_user(buffer, str, len);
      return r ? r : len;
   } else {
  return -EINVAL;
   }
}
static struct file_operations dev_fops={
 .owner=THIS_MODULE,
 .open=timer0_open,
 .release=timer0_close,
 .read=timer0_read,
};
static struct miscdevice misc={
 .name=DEVICE_NAME,
 .minor=MISC_DYNAMIC_MINOR,
 .fops=&dev_fops,
};
static int __init timer0_micro2440_init(void)
{
     int ret;
     init_MUTEX(&lock);
     ret=misc_register(&misc); 
     return ret;
}
void __exit timer0_micro2440_exit(void)
{
    misc_deregister(&misc); 
}
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("xubin");
module_init(timer0_micro2440_init);
module_exit(timer0_micro2440_exit);
 
二、应用程序:
 

#include
#include
#include
#include
#include
#include
char buffer[50];
unsigned long time_lambda=0;
int main(int argc,char **argv)
{
    unsigned long i=1;
    unsigned long value=0;
     int fd;
    fd=open("/dev/timer0_micro2440_drv",O_RDWR);
    if(fd<0)
     {
         printf("error\n");
         exit(1);
      }
      while(1)
      {     
           int len = read(fd, buffer, sizeof buffer -1);
            if (len > 0) {
           buffer[len] = '\0';
           value = 0;
           sscanf(buffer, "%d", &value);//将字符串buffer按照整数的形式存在value中
           if(value==1)
           {
              time_lambda++;
              printf("timer Value x: %d\n", time_lambda);
}
           }
       }
       close(fd);
      return 0;
}
阅读(1693) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~