zoukankan      html  css  js  c++  java
  • Linux_arm驱动之按键模拟脉冲实现定时器的精确计时

     
    http://wenku.baidu.com/link?url=-9_IHk-7BFRSAxPAeutaQ8Ifhs0Rs9Qg3yAG9LxsqYqRauQRBwjVJ_xnmQ6R-CKbwVDSVmbr4vDJcDyUpbj_Y2RD75J1iLjQonsHywjECRW
    [cpp] view plaincopy
     
    1. /***************************************************************** 
    2.                        内核驱动部分button_ker.c 
    3. *****************************************************************/  
    4.   
    5. /* 
    6.  *应用内核定时器简单实现计时的功能 
    7.  *但是内核定时器精确度最小就为50ms 
    8.  *较4_button_timer完善功能:利用硬件的定时器计时 
    9.  *精确度提高 
    10.  *应用linux-2.6.32.2内核里arch/arm/plat_s3/timer.c 
    11.  *实现对定时器的精确提高问题 
    12.  */  
    13. #include <linux/module.h>  
    14. #include <linux/kernel.h>  
    15. #include <linux/fs.h>  
    16. #include <linux/init.h>  
    17. #include <linux/delay.h>  
    18. #include <asm/irq.h>  
    19. #include <linux/irq.h>  
    20. #include <linux/interrupt.h>  
    21. #include <asm/uaccess.h>  
    22. #include <linux/timer.h>  
    23. #include <linux/sched.h>  
    24.   
    25. //*****///  
    26. #include <linux/clk.h>  
    27. #include <plat/regs-timer.h>  
    28. #include <asm/io.h>  
    29. ///****///  
    30. #include <linux/miscdevice.h>  
    31. #include <mach/regs-irq.h>  
    32. //#include <linux/platform_device.h>  
    33. //#include <linux/miscdevice.h>  
    34. //#include <mach/regs-gpio.h>  
    35.   
    36. #include <linux/wait.h>  
    37. #define DEVICE_NAME "timer_test"  
    38. #define BUTTON_MAJOR 240  
    39.   
    40. #define TIMER_IOCTL_SET_FREQ  1  
    41. #define TIMER_IOCTL_STOP      0  
    42.   
    43. static struct semaphore lock;  
    44.   
    45. struct button_irq_desc{  
    46.     int irq;  
    47.     unsigned long flags;  
    48.     int num;  
    49.     char *name;  
    50. };  
    51. //用来指定按键所有的外部中断引脚以及中断出发方式和名字  
    52. static struct button_irq_desc button_irqs[] = {  
    53.     {IRQ_EINT0,IRQF_TRIGGER_FALLING,1,"KEY1"},  
    54.     {IRQ_EINT1,IRQF_TRIGGER_FALLING,2,"KEY2"},  
    55.     {IRQ_EINT2,IRQF_TRIGGER_FALLING,3,"KEY3"},  
    56.     {IRQ_EINT4,IRQF_TRIGGER_FALLING,4,"KEY4"},  
    57. };  
    58. static volatile char key_values[4]={'0','0','0','0'};  
    59. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
    60. static volatile int ev_press =0;  
    61.   
    62. static void timer_open(void);  
    63. static void timer_stop(void);  
    64. static inline int timer_interrupt_pending(void);  
    65. static unsigned long get_timer_offset(void);  
    66. ///********************************////  
    67. static volatile bool value=false;  
    68. static volatile unsigned long count = 0;  
    69. static volatile unsigned long freq_value = 500;  
    70. static volatile unsigned long tcnt_value = 50625;  
    71. //定时器中断函数  
    72. static irqreturn_t timer_interrupt_function(int irq,void *dev_id)  
    73. {  
    74.     count++;  
    75.     //printk("timer_interrupt occur! ");  
    76.     return IRQ_HANDLED;  
    77. }  
    78. //时间处理函数  
    79. static void timer_second_manage(unsigned long second_value)  
    80. {  
    81.     static volatile unsigned long ss_value1 = 0;  
    82.     static volatile unsigned long ms_value2 = 0;  
    83.     static volatile unsigned long us_value3 = 0;  
    84.       
    85.     us_value3 = //(second_value*10000/tcnt_value)*1000/freq_value/10;  
    86.                     (second_value*1000/freq_value)*10000/tcnt_value/10;  
    87.                   
    88.     ms_value2 = (count%freq_value)*1000/freq_value + us_value3/1000;  
    89.     ss_value1 = count/freq_value + ms_value2/1000;  
    90.   
    91.     printk("++++++++++++++++++++++++ ");  
    92.     printk("used time:%lu n ",count);  
    93.     printk("the second_value :%lu n ",second_value);  
    94.     printk("used time:%lu.%03lu %03lu s ",ss_value1,  
    95.                                 ms_value2%1000,us_value3%1000);  
    96.     printk("++++++++++++++++++++++++ ");  
    97.   
    98. }  
    99. //外部中断函数  
    100. static irqreturn_t button_interrupt(int irq,void *dev_id){  
    101.     unsigned long second_value = 0;  
    102.     int num= ((struct button_irq_desc *)dev_id)->num;  
    103.     switch(num){  
    104.         case 2://17  
    105.             value=false;  
    106.             timer_stop();  
    107.             printk("key1 press ");  
    108.             break;  
    109.         case 4://48  
    110.             if(!value) {  
    111.                 value=true; count=0;  
    112.                 timer_open();  
    113.             }else {  
    114.                 timer_stop();  
    115.                 second_value=get_timer_offset();  
    116.                 timer_second_manage(second_value);  
    117.                 value=false;  
    118.             }  
    119.             printk("key2 press ");  
    120.             break;  
    121.         case 3://18  
    122.             value=false;  
    123.             timer_stop();  
    124.             printk("key3 press ");  
    125.             break;  
    126.         case 1://16  
    127.             value=false;  
    128.             timer_stop();  
    129.             printk("key4 press ");  
    130.             break;  
    131.         default:  
    132.             printk("num error,nothing to do! ");  
    133.           
    134.     }  
    135.     //ev_press=1;  
    136.     //wake_up_interruptible(&button_waitq);  
    137.     return IRQ_HANDLED;  
    138. }  
    139.   
    140. //频率设置函数  
    141. //freq: pclk/50/16/65536~pclk/50/16  
    142. //if  : pclk=50mhz freq is 1Hz~62500Hz  
    143. //human ear : 20Hz~20000Hz  
    144. //  
    145. static void timer_set_freq(unsigned long freq)  
    146. {  
    147.     unsigned long tcon;  
    148.     unsigned long tcnt;  
    149.     unsigned long tcfg0;  
    150.     unsigned long tcfg1;  
    151.       
    152.     struct clk *clk_p;  
    153.     unsigned long pclk;  
    154.   
    155.     tcon  = __raw_readl(S3C2410_TCON);  
    156.     tcfg0 = __raw_readl(S3C2410_TCFG0);  
    157.     tcfg1 = __raw_readl(S3C2410_TCFG1);  
    158.   
    159.     tcfg0 &= ~(255<<0);  
    160.     //tcfg0 |= (50-1);  
    161.     tcfg0 |= 0;  
    162.   
    163.     tcfg1 &= ~(15<<0);  
    164.     tcfg1 |= (0<<0);  
    165.   
    166.     __raw_writel(tcfg0,S3C2410_TCFG0);  
    167.     __raw_writel(tcfg1,S3C2410_TCFG1);  
    168.   
    169.     clk_p = clk_get(NULL,"pclk");  
    170.     pclk  = clk_get_rate(clk_p);  
    171.     printk("the pclk is : %ld ",pclk);  
    172.     //tcnt  = (pclk/50/16)/freq;  
    173.     tcnt  = (pclk/2)/freq;  
    174.     tcnt_value = tcnt;  
    175.     printk("the tcnt is %ld ",tcnt);  
    176.      __raw_writel(tcnt,S3C2410_TCNTB(0));  
    177.      __raw_writel(0,S3C2410_TCMPB(0));  
    178.   
    179.     //tcon &= ~0x1f;  
    180.     tcon &= ~0x1e;  
    181.     tcon |=0xb;  
    182.   
    183.      __raw_writel(tcon,S3C2410_TCON);  
    184.     tcon &= ~2;  
    185.     __raw_writel(tcon,S3C2410_TCON);  
    186.   
    187. }  
    188. static void timer_open(void)  
    189. {  
    190.     unsigned long tcon = 0;  
    191.     //printk("***1>tcnto is :%u ",__raw_readl(S3C2410_TCNTO(0)));  
    192.     tcon = __raw_readl(S3C2410_TCON);  
    193.     tcon |= 1;  
    194.     __raw_writel(tcon,S3C2410_TCON);  
    195.     //printk("***2>tcnto is :%u ",__raw_readl(S3C2410_TCNTO(0)));  
    196.   
    197. }  
    198. static void timer_stop(void)  
    199. {  
    200.     unsigned long tcon;  
    201.     tcon = __raw_readl(S3C2410_TCON);  
    202.     tcon &= ~1;  
    203.     __raw_writel(tcon,S3C2410_TCON);  
    204.   
    205. }  
    206. #define SRCPND_TIMER0 (1<<(IRQ_TIMER0 - IRQ_TIMER0))  
    207. //中断识别函数 查看在按键产生中断时,定时器是否也在中断中  
    208. static inline int timer_interrupt_pending(void)  
    209. {  
    210.     return __raw_readl(S3C2410_SRCPND) & SRCPND_TIMER0;  
    211. }  
    212. //计算中断寄存器中TCNTO0中的偏移量  
    213. static unsigned long get_timer_offset (void)  
    214. {  
    215.     unsigned long tdone;  
    216.     unsigned long tval;  
    217.   
    218.     tdone = (tcnt_value -__raw_readl(S3C2410_TCNTO(0)));  
    219.     if(timer_interrupt_pending()) {  
    220.         tval = __raw_readl(S3C2410_TCNTO(0));  
    221.         tdone = tcnt_value - tval;  
    222.         if(!tval)  
    223.             tdone += tcnt_value;  
    224.     }  
    225.     return tdone;  
    226.   
    227. }  
    228. static struct irqaction timer_irq = {  
    229.     .name    = "S3C2410 Timer Tick",  
    230.     .flags   = IRQF_DISABLED |IRQF_TIMER|IRQF_IRQPOLL,  
    231.     .handler = timer_interrupt_function,  
    232.     .dev_id  = NULL  
    233. };  
    234.   
    235. static int button_open(struct inode *inode,struct file *file)  
    236. {  
    237.   
    238.     int i,err;  
    239.     if(down_trylock(&lock)){  
    240.         printk("down_trylock failed! ");  
    241.         return -EBUSY;  
    242.     }  
    243.     if(setup_irq(IRQ_TIMER0,&timer_irq)){  
    244.         printk("setup_irq failed! ");  
    245.         return -EBUSY;  
    246.     }  
    247.   
    248.     for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++) {  
    249.         err=request_irq(button_irqs[i].irq,button_interrupt,button_irqs[i].flags,  
    250.                 button_irqs[i].name,(void*)&(button_irqs[i]));  
    251.         if(err)  
    252.             break;  
    253.     }  
    254.     if(err) {  
    255.         for(--i;i>=0;i--)  
    256.             free_irq(button_irqs[i].irq,(void *)&button_irqs[i].num);  
    257.         printk("request_irq error! ");  
    258.         return -1;  
    259.     }  
    260.   
    261.     disable_irq(IRQ_EINT0);  
    262.     disable_irq(IRQ_EINT1);  
    263.     disable_irq(IRQ_EINT2);  
    264.     disable_irq(IRQ_EINT4);  
    265.       
    266.     set_irq_type(IRQ_EINT0,IRQ_TYPE_LEVEL_LOW);//key4  
    267.     set_irq_type(IRQ_EINT1,IRQ_TYPE_EDGE_RISING);//key1  
    268.     set_irq_type(IRQ_EINT2,IRQ_TYPE_EDGE_FALLING);//key3  
    269.     //set_irq_type(IRQ_EINT4,IRQ_TYPE_EDGE_BOTH);//key2  
    270.     set_irq_type(IRQ_EINT4,IRQ_TYPE_EDGE_FALLING);//key2  
    271.   
    272.     enable_irq(IRQ_EINT0);  
    273.     enable_irq(IRQ_EINT1);  
    274.     enable_irq(IRQ_EINT2);  
    275.     enable_irq(IRQ_EINT4);  
    276.   
    277.     return 0;  
    278. }  
    279.   
    280. static int button_close(struct inode *inode,struct file *file)  
    281. {  
    282.     int i;  
    283.     for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++) {  
    284.         free_irq(button_irqs[i].irq,(void *)&button_irqs[i]);  
    285.     }  
    286.     remove_irq(IRQ_TIMER0,&timer_irq);  
    287.     up(&lock);  
    288.     return 0;  
    289. }  
    290.   
    291. static int button_read(struct file *filp,char __user *buff,  
    292.                         size_t count,loff_t *offp)  
    293. {  
    294.     unsigned long err;  
    295.     if(filp->f_flags & O_NONBLOCK)  
    296.         return -EAGAIN;  
    297.     else {  
    298.         wait_event_interruptible(button_waitq,ev_press);  
    299.     }  
    300.     ev_press=0;  
    301.     err=copy_to_user(buff,(const void*)key_values,  
    302.                             min(sizeof(key_values),count));  
    303.     return err ? -EFAULT : min(sizeof(key_values),count);  
    304. }  
    305. static int timer_ioctl(struct inode *inode,struct file *file,  
    306.                         unsigned int cmd,unsigned long arg)  
    307. {  
    308.     switch (cmd) {  
    309.         case TIMER_IOCTL_SET_FREQ:  
    310.             printk("timer_ioctl_set_freq ");  
    311.             if(arg==0)  
    312.                 return -EINVAL;  
    313.             timer_set_freq(arg);  
    314.             freq_value = arg;  
    315.             break;  
    316.         case TIMER_IOCTL_STOP:  
    317.             printk("timer_ioctl_stop ");  
    318.             timer_stop();  
    319.             break;  
    320.     }  
    321.     return 0;  
    322. }  
    323.   
    324. static struct file_operations button_fops = {  
    325.     .owner      = THIS_MODULE,  
    326.     .open       = button_open,  
    327.     .read       = button_read,  
    328.     .release    = button_close,  
    329.     .ioctl      = timer_ioctl,  
    330. };  
    331. static struct miscdevice misc = {  
    332.     .minor = MISC_DYNAMIC_MINOR,  
    333.     .name  = DEVICE_NAME,  
    334.     .fops  = &button_fops,  
    335. };  
    336. //初始化函数  
    337. static int __init button_init(void)  
    338. {  
    339.     init_MUTEX(&lock);  
    340.       
    341.     /* 
    342.     if(register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&button_fops)<0) { 
    343.         printk(DEVICE_NAME"can't register major number! "); 
    344.         return -1; 
    345.     } 
    346.     printk(DEVICE_NAME"register sucess! "); 
    347.     */  
    348.     if(misc_register(&misc)<0) {  
    349.         printk(DEVICE_NAME"can't register major number! ");  
    350.         return -1;  
    351.     }  
    352.     printk(DEVICE_NAME"register sucess! ");  
    353.       
    354.     return 0;  
    355. }  
    356. static void __exit button_exit(void)  
    357. {  
    358.     timer_stop();  
    359.     //unregister_chrdev(BUTTON_MAJOR,DEVICE_NAME);  
    360.     misc_deregister(&misc);  
    361. }  
    362.   
    363. module_init(button_init);  
    364. module_exit(button_exit);  
    365.   
    366. MODULE_LICENSE("GPL");  



    [cpp] view plaincopy
     
    1. /********************************************************************** 
    2.                      应用程序部分button_app.c 
    3. **********************************************************************/  
    4.   
    5. #include <stdio.h>  
    6. #include <stdlib.h>  
    7. #include <unistd.h>  
    8. #include <sys/ioctl.h>  
    9. #define msleep(x) usleep(x*1000);  
    10. #define TIMER_IOCTL_SET_FREQ 1  
    11. #define TIMER_IOCTL_STOP     0  
    12. int main(int argc,char **argv)  
    13. {  
    14.     int fd;  
    15.     int ioarg=500;  
    16.     int press_cnt[4]={0};  
    17.     if((fd=open("/dev/timer_test",0))<0){  
    18.         printf("Can't open /dev/timer_test~!");  
    19.         return -1;  
    20.     }  
    21.     printf("sleep begin... ");  
    22.     ioctl(fd,TIMER_IOCTL_SET_FREQ,ioarg);  
    23.     //msleep(70000);  
    24.     while(1)  
    25.         usleep(11111);  
    26.     ioctl(fd,TIMER_IOCTL_STOP);  
    27.     printf("sleep end... ");  
    28.     close(fd);  
    29.     return 0;  
    30.   
    31. }  
    [cpp] view plaincopy
     
      1. /*************************************************************** 
      2.                         makefile部分 
      3. ****************************************************************/  
      4. ifneq ($(KERNELRELEASE),)  
      5. obj-m := button_ker.o  
      6. else  
      7. KDIR :=/home/kernel/linux-2.6.32.2  
      8. all:  
      9.     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-  
      10.   
      11.     arm-linux-gcc button_app.c -o button_app  
      12. clean:  
      13.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*  
  • 相关阅读:
    工作流调度器azkaban
    日志采集框架Flume
    MAPREDUCE框架结构及核心运行机制
    Python爬虫开发系列之五》数据存储为TXT、JSON格式
    Python爬虫开发系列之二》请求库及解析库安装
    策略模式+简单工厂模式
    简单工厂模式
    单例模式
    5、计算高可用
    4、存储高可用
  • 原文地址:https://www.cnblogs.com/zym0805/p/6235353.html
Copyright © 2011-2022 走看看