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. *但是内核定时器精确度最小就为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");

[cpp] view plaincopy

  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. }

[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. arm-linux-gcc button_app.c -o button_app
    11. clean:
    12. rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*
时间: 2024-08-26 02:33:25

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

初入android驱动开发之字符设备(五-定时器)

这个字符设备系列,主要借助较容易上手的字符设备实例,去讲解linux的一些机制,以及驱动中比较常用到的中断.定时器.信号量等一些知识,由于本人自身的知识有限,对于arm的架构体系不太了解,这里,一般这里只讲,如何去用,对于一些原理性的东西不会深究,以后的文章会慢慢的加深. 想想我们当初玩51单片机的时候,那时候按键防抖是一个硬件.软件都需要处理的地方.软件一般就是加延时检测判断.当然,这里我们也可以用到定时器的这个机制,做按键驱动,这里主要还是以按键为例,但不是讲的按键防抖. 1. 定时器的一些

远程控制之鼠标、按键模拟

做远程控制相关软件(远程办公.远程教育.远程协助等)时,鼠标.按键模拟必不可少.在windows环境下,windows API提供的两个方法可以很方便的完成鼠标.按键的模拟:mouse_event.keybd_event.模拟鼠标按键单击时,首先要计算鼠标位置X.Y(使用ClientToScreen),并把被控端鼠标位置移到X.Y位置,即鼠标Move事件(SetCursorPos),之后使用mouse_event来模拟需要执行的鼠标行为,主要为按下.弹起.按键的模拟主要是键的按下与弹起. 鼠标模

字符设备驱动(五)按键优化休眠

目录 字符设备驱动(五)按键优化 按键值读取 休眠读取 程序设计 测试 title: 字符设备驱动(五)按键优化 tags: linux date: 2018-11-23 17:56:57 toc: true --- 字符设备驱动(五)按键优化 按键值读取 Linux内部有系统函数s3c2410_gpio_getpin能够读取GPIO的值 unsigned int s3c2410_gpio_getpin(unsigned int pin) { void __iomem *base = S3C24

字符设备驱动(七)按键异步通知

目录 按键驱动方式对比 进程间发信号 目标 如何让驱动通知应用 程序编写 驱动程序 应用程序 完整代码如下 测试 title: 字符设备驱动(七)按键异步通知 tags: linux date: 2018-11-24 16:39:47 toc: true --- 按键驱动方式对比 查询:耗资源 中断: 没有超时机制,当没有中断作为生产者,read函数一直休眠 poll机制,加入超时机制 上述三种都是app主动去获取按键,使用异步通知的形式可以使按键发生后,通知app去读取 进程间发信号 以前使用

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

title: 字符设备驱动(六)按键poll机制 tags: linux date: 2018-11-23 18:57:40 toc: true --- 字符设备驱动(六)按键poll机制 引入 在字符设备驱动(五)按键休眠中的App中虽然使用了休眠,但是如果Read没有返回的话会一直死等,类似阻塞,我们期望等待一段时间后自动返回,等待的时候程序依然是睡眠的,这里引入poll机制 应用程序的open/close/write/read都有对应的系统内核的sys_open/sys_close/sys

《自拍教程50》Python_adb随机按键模拟2小时

Android终端(车载,手机)等, 需要考虑进行随意进行各类按键(车载方向盘按键,手机硬按键)的操作, 测试系统对按键事件的响应稳定性,一般测试2小时. 准备阶段 一般是用adb shell input keyevent + keyCode 来模拟按键事件, 比如adb shell input keyevent 24 可以模拟"音量加键", 以下是比较常用的几个按键的键值表. table th:first-of-type { width: 100px; } KeyCode 释义 3

深入浅出~Linux设备驱动之按键设备驱动

在上述的驱动系列博客中,我们已经了解了关于阻塞和非阻塞.异步通知.轮询.内存和I/O口访问.并发控制等知识,按键设备驱动相对来说是比较简单的,本章内容可以加深我们对字符设备驱动架构.阻塞与非阻塞.中断定时器等相关知识的理解.在嵌入式的系统中,按键的硬件原理简单,就是通过一个上拉电阻将处理器的外部中断引脚拉高,电阻的另一端接按钮并接地就可以实现. 1.按键的确认流程如下 2 按键驱动中的有关数据结构 2.1 按键设备结构体以及定时器 #define MAX KEY BUF 16 // 键缓冲区大小

块设备驱动之内存模拟硬盘

转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/25240899 一.块设备驱动框架 app:      open,read,write "hello.txt" ---------------------------------------------  文件的读写 文件系统: vfat, ext2, ext3, yaffs2, jffs2      (把文件的读写转换为扇区的读写) ----------------

将程序变成system app 实现home、back、menu等按键模拟

1.使一个程序成为系统程序 我们必须在manifest 中配置android:sharedUserId="android.uid.system" <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.flyaudio.floatwindows" android:versionCode="1" android:sh