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. discuz中方法

    discuz中检验是否是邮箱 function isemail($email) { && strlen($email) <= && preg_match(&quo ...

  2. 敏捷软件开发 VS. 传统软件工程

    敏捷软件开发 VS. 传统软件工程 软件工程这一术语1968年被提出,之后美国软件工程专家巴利·玻姆对十多年间研究软件工程的专家学者们提出的一些准则与信条,于1983年对提出软件工程的七条基本定理,将 ...

  3. PHP在linux上执行外部命令

    PHP在linux上执行外部命令 一.PHP中调用外部命令介绍二.关于安全问题三.关于超时问题四.关于PHP运行linux环境中命令出现的问题 一.PHP中调用外部命令介绍在PHP中调用外部命令,可以 ...

  4. Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问题

    Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问 ...

  5. Redis_DataType

    Redis_DataType.html :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,. ...

  6. MFC 获取图像的大小

    // 获致图像的大小 int CCImageDialog::GetImageSize(CSize& size, CString filename) { CImage image; image. ...

  7. json与对象转化

    /// <summary> /// 把JSON字符串还原为对象 /// </summary> /// <typeparam name="T">对 ...

  8. 5.Struts2中的拦截器

    拦截器是Struts2中的核心,其自带很多很多的拦截器,这里主要介绍一下自定义拦截器,恩多一半情况下呢?我们不需要使用到自定义的拦截器,Struts2本身已经提 供了很多的拦截器供我们使用,对于自定义 ...

  9. Linux下JDK、Tomcat

    1.JDK的安装   1. 下载JDK 先查看Linux系统是多少位(32位/64位):getconf  LONG_BIT.再从JDK官网(http://www.oracle.com/technetw ...

  10. Redis学习笔记-初级

    1.Redis简介 Redis是一个高效缓存内存数据库,开源.免费.key-value格式 相比于其他key-value格式的缓存产品,特点/优势在于: 支持持久化,可以将内存中的数据保存在磁盘中,重 ...