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

Linux_arm驱动之按键模拟脉冲实现定时器的精确计时的更多相关文章

  1. Delphi驱动方式WINIO模拟按键 可用

    http://www.delphitop.com/html/yingjian/152.html Delphi驱动方式WINIO模拟按键 作者:admin 来源:未知 日期:2010/2/1 1:14: ...

  2. 字符设备驱动(六)按键poll机制

    title: 字符设备驱动(六)按键poll机制 tags: linux date: 2018-11-23 18:57:40 toc: true --- 字符设备驱动(六)按键poll机制 引入 在字 ...

  3. Linux驱动之按键驱动编写(中断方式)

    在Linux驱动之按键驱动编写(查询方式)已经写了一个查询方式的按键驱动,但是查询方式太占用CPU,接下来利用中断方式编写一个驱动程序,使得CPU占有率降低,在按键空闲时调用read系统调用的进程可以 ...

  4. 驱动开发:内核枚举DpcTimer定时器

    在笔者上一篇文章<驱动开发:内核枚举IoTimer定时器>中我们通过IoInitializeTimer这个API函数为跳板,向下扫描特征码获取到了IopTimerQueueHead也就是I ...

  5. 蜕变成蝶~Linux设备驱动之按键设备驱动

    在上述的驱动系列博客中,我们已经了解了关于阻塞和非阻塞.异步通知.轮询.内存和I/O口访问.并发控制等知识,按键设备驱动相对来说是比较简单的,本章内容可以加深我们对字符设备驱动架构.阻塞与非阻塞.中断 ...

  6. Unity问答——NGUI怎么使用按键模拟鼠标点击?

    这篇博客源自我在泰课在线的回答.链接:http://www.taikr.com/group/1/thread/248 问:NGUI怎么模拟用代码模拟控制点击 答: 1. 这个问题问得好.因为在使用按键 ...

  7. Linux驱动之按键驱动编写(查询方式)

    在Linux驱动之LED驱动编写已经详细介绍了一个驱动的编写过程,接着来写一个按键驱动程序,主要是在file_operations结构中添加了一个read函数.还是分以下几步说明 1.查看原理图,确定 ...

  8. Python键盘按键模拟

    有时候我们需要使用python执行一些脚本,可能需要让程序自动按键或自动点击鼠标,下面的代码实现了对键盘的模拟按键, 需要安装pypiwin32,当然也可以直接用ctypes来实现. 输入:pip i ...

  9. python 模拟按键模拟键盘按键按下放开

    python模拟按键 pip install pypiwin32安装库 import win32conimport win32apiimport time 导入 打个比方模拟A win32api.ke ...

随机推荐

  1. 30款最好的 Bootstrap 3.0 免费主题和模板

    Twitter Bootstrap 框架已经广为人知,用于加快网站,应用程序或主题的界面开发,并被公认为是迄今对于 Web 开发的最有实质性帮助的工具之一.在此之前的,各种各样的界面库伴随着高昂的维护 ...

  2. SE要有政治能力

    不光是SE,任何人都需要政治能力. 那么,什么是政治能力?政治能力就是让周围的人跟你一起,一条心,完成你想干的事情的能力. 我们任何人,生活也好,工作也好,学习也好,都不是一个人孤单进行的,都是通过几 ...

  3. java 中 ArrayList LinkedList Vector 三者的异同点

    1.ArrayList和Vector都是基于数组实现的,所以查询速度很快,增加和删除(非最后一个节点)速度慢: Vector是线程安全的,ArrayList不是. 2.LinkedList 是一个双向 ...

  4. ORACLE 实例及RAC

    ORACLE 实例及RAC 一.问题 (1)现象 部署一个sh脚本到生产oracle服务器上,该sh脚本负责读取外系统提供的txt文件,然后用sql loader入库,由oracle服务器的cront ...

  5. 查看表的datapages

    select object_name(i.object_id) as tableName,data_pages as dataPagesfrom sys.indexes as ijoin sys.pa ...

  6. 项目中可能用到的demo

    1. 轮播图   https://github.com/codingZero/XRCarouselView 2. 图表   https://github.com/Zirkfied/ZFChart

  7. mysql的约束类型

    1.主键约束 2.非空约束 3.唯一性约束 4.外键约束 5.默认值约束

  8. oracle 调用java

    1.首先在PL/SQL中创建JAVA类,并编译 例如:这个是到的一个查询目录下面文件列表的java类 创建此java 类用: create or replace and compile java so ...

  9. CentOS 6.5 下离线安装nginx

    一.由于linux下安装nginx 需要  zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc这些依赖,而这些依赖打安装包在我们系统的光 ...

  10. JavaWeb 学习0010-今日问题 2016-12-3

    2016-12-3 1. 今天要做的第一个问题就是,怎么把网页变得好看点: addStudent/listStudent页面都有改动 其中 list页面还有了<c:if 的语句这是还没练习过得知 ...