linux 内核定时器精度_使用linux内核hrtimer高精度定时器实现GPIO口模拟PWM,【原创】...

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

10 #include

11 #include

12 #include

13 #include

14

15 #include

16 #include

17

18 #include

19

20 #define BUZZER_DEVICE_NAME "mybuzzer"

21 #define BUZZER_CLASS_NAME "mybuzzer" //sys/class/mybuzzer

22 #define BUZZER_DEVICE_NUM 1 //设备节点的编号最终生成节点的名字为/dev/buzzer-1

23

24

25 #define BUZZER_GPIO_SWITCH 1 //是否设置buzzer的gpio的初始化,另一个驱动已经初始化GPIO

26 #define BUZZER_DELAY_TIME_HIGHT (190000) //2.7KHZ

27 #define BUZZER_DELAY_TIME_LOW (190000) //2.7KHZ

28 #define DE_BUG 1

29

30 #if DE_BUG

31 #define prdebug(fmt,arg...) printk("zbzhuang"KERN_ERR fmt"\n",##arg)

32 #else

33 #define prdebug(fmt,arg...) do{}while(0);

34 #endif

35

36

37

38 typedef enum{39 BUZZER_DISABLE = 0,40 BUZZER_ENABLE,41 }BUZZER_STATUS_t;42

43 //buzzer的设备对象

44 structbuzzer_chip{45 dev_t devno;46 struct cdev *cdev;47 struct class *cls;48 struct device *dev;49 unsigned long count; //从应用空间读取的数据

50 structsemaphore sem;51 structhrtimer mytimer;52 ktime_t kt; //设置定时时间

53 wait_queue_head_t wait_queue;54 BUZZER_STATUS_t status;55 };56

57

58

59

60 static int count = 1000;61 struct buzzer_chip *buzzer_dev;62

63 static void buzzer_test(void);64 static void buzzer_gpio_start(void);65 static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer);66

67

68 int buzzer_drv_open (struct inode * inode, struct file *filp)69 {70 intminor;71 intmajor;72

73

74 prdebug("--------------%s----------------",__func__);75

76 minor =iminor(inode);77 major =imajor(inode);78

79 prdebug("\r\nmajor = %d minor = %d\rn",major,minor);80 filp->private_data = (void *)minor;81

82 if(down_interruptible(&buzzer_dev->sem))83 return -ERESTARTSYS;84

85 return 0;86 }87 ssize_t buzzer_drv_read (struct file *filp, char __user *userbuf, size_t count, loff_t *fpos)88 {89 intret;90

91 prdebug("--------------%s----------------",__func__);92

93 if(filp->f_flags &O_NONBLOCK){94 return -EAGAIN;95 }96

97 ret = copy_to_user(userbuf,&buzzer_dev->count,count);98 if(ret > 0){99 prdebug("error copy_to_user");100 return -EFAULT;101 }102 prdebug("%s :read count = %ld",__func__,buzzer_dev->count);103

104 returncount;105 }106 ssize_t buzzer_drv_write (struct file *filp, const char __user *userbuf, size_t count, loff_t *fpos)107 {108 intret;109

110 prdebug("--------------%s----------------",__func__);111 prdebug("task pid[%d] context[%s]",current->pid,current->comm);112

113 ret = copy_from_user(&buzzer_dev->count,userbuf,count);114 if(ret > 0){115 prdebug("error copy_from_user");116 return -EFAULT;117 }118

119 prdebug("%s :write count = %ld",__func__,buzzer_dev->count);120

121

122

123

124 if(buzzer_dev->count){125 if(buzzer_dev->status ==BUZZER_DISABLE){126 //启动定时器

127 prdebug("-----------start hrtimer timer-------------");128 buzzer_dev->status =BUZZER_ENABLE;129 buzzer_gpio_start();130 wait_event(buzzer_dev->wait_queue, buzzer_dev->status ==BUZZER_DISABLE);131 prdebug("------------wake up queue-------------------------------");132 }else{133 prdebug("buzzer_aready work");134 }135

136 }else{137

138 }139

140

141 returncount;142

143 }144 int buzzer_drv_close (struct inode *inode, struct file *filp)145 {146

147 prdebug("--------------%s----------------",__func__);148 up(&buzzer_dev->sem);149

150 return 0;151

152 }153

154 const struct file_operations buzzer_fops ={155 .open =buzzer_drv_open,156 .write =buzzer_drv_write,157 .read =buzzer_drv_read,158 .release =buzzer_drv_close,159

160 };161

162 static int buzzer_gpio_init(void)163 {164 int ret = -1;165

166 if(gpio_request(BUZZER_IO, "BUZZER_GPIO")){167 prdebug("error buzzer_gpio_init");168 returnret;169

170 }else{171 gpio_direction_output(BUZZER_IO, 1);172 gpio_set_value(BUZZER_IO, 1);173 buzzer_dev->status =BUZZER_DISABLE;174 }175

176 return 0;177

178 }179

180 static void buzzer_gpio_exit(void)181 {182 gpio_set_value(BUZZER_IO, 1);183 gpio_free(BUZZER_IO);184 }185

186 static void buzzer_gpio_start(void)187 {188 prdebug("-----------buzzer_gpio_start------------");189

190

191

192 //高精度定时器

193 hrtimer_init(&buzzer_dev->mytimer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);194 buzzer_dev->mytimer.function =hrtimer_handler;195 buzzer_dev->kt = ktime_set(0, BUZZER_DELAY_TIME_LOW);196 hrtimer_start(&buzzer_dev->mytimer,buzzer_dev->kt,HRTIMER_MODE_REL);197

198

199

200 }201

202 static void buzzer_test(void)203 {204 unsigned longi;205

206 prdebug("-----------start test buzzer------------");207 for(i = 0;i < 10000;i ++){208 gpio_set_value(BUZZER_IO, 0);209 udelay(150);210 gpio_set_value(BUZZER_IO, 1);211 udelay(150);212 }213 prdebug("-----------end test buzzer------------");214 }215

216 static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)217 {218

219

220 //prdebug("--------------%s----------------",__func__);

221

222 if(buzzer_dev->count != 1){223

224 if (gpio_get_value(BUZZER_IO) == 1) {225 gpio_set_value(BUZZER_IO, 0);226

227 buzzer_dev->kt = ktime_set(0, BUZZER_DELAY_TIME_LOW);228 hrtimer_forward_now(&buzzer_dev->mytimer, buzzer_dev->kt);229

230 } else{231 gpio_set_value(BUZZER_IO, 1);232

233 buzzer_dev->kt = ktime_set(0, BUZZER_DELAY_TIME_HIGHT);234 hrtimer_forward_now(&buzzer_dev->mytimer, buzzer_dev->kt);235 }236 buzzer_dev->count --;237 returnHRTIMER_RESTART;238 }else{239 buzzer_dev->count --;240 buzzer_dev->status =BUZZER_DISABLE;241 prdebug("buzzer_dev->count = %d",buzzer_dev->count);242 prdebug("-----------finsh hrtimer timer-------------");243 wake_up(&buzzer_dev->wait_queue);244 returnHRTIMER_NORESTART;245 }246

247

248 }249

250

251 static int __init buzzer_drv_init(void)252 {253 intret;254

255

256 prdebug("--------------%s----------------",__func__);257

258 buzzer_dev = kzalloc(sizeof(structbuzzer_chip),GFP_KERNEL);259 if(buzzer_dev ==NULL){260 prdebug("kzalloc error");261 return -ENOMEM;262 }263

264 //动态的申请设备号

265 ret = alloc_chrdev_region(&buzzer_dev->devno,0,1,BUZZER_DEVICE_NAME);266 if(ret != 0){267 prdebug("error alloc_chrdev_region");268 gotoerr_free;269 }270

271 //分配cdev对象

272 buzzer_dev->cdev =cdev_alloc();273 cdev_init(buzzer_dev->cdev,&buzzer_fops);274 cdev_add(buzzer_dev->cdev,buzzer_dev->devno,1);275

276 //自动创建设备节点

277 buzzer_dev->cls =class_create(THIS_MODULE,BUZZER_CLASS_NAME);278 if(IS_ERR(buzzer_dev->cls)){279 prdebug("error class_create");280 ret = PTR_ERR(buzzer_dev->cls);281 gotoerr_unregister;282 }283

284 buzzer_dev->dev = device_create(buzzer_dev->cls,NULL,buzzer_dev->devno,NULL,"buzzer-%d",BUZZER_DEVICE_NUM);285 if(IS_ERR(buzzer_dev->dev)){286 prdebug("error device_create");287 ret =PTR_ERR(buzzer_dev);288 gotoerr_class_error;289 }290

291 //信号量

292 sema_init(&buzzer_dev->sem,1);293

294 init_waitqueue_head(&buzzer_dev->wait_queue);295

296

297

298

299

300 #if BUZZER_GPIO_SWITCH

301 //初始化Buzzer的GPIO

302 ret =buzzer_gpio_init();303 if(ret !=0){304 prdebug("error buzzer_gpio_init");305 gotoerr_device_create;306 }307

308 #endif

309

310

311

312 return 0;313

314 #if BUZZER_GPIO_SWITCH

315 err_device_create:316 device_destroy(buzzer_dev->cls,buzzer_dev->devno);317 #endif

318

319 err_class_error:320 class_destroy(buzzer_dev->cls);321

322 err_unregister:323 cdev_del(buzzer_dev->cdev);324 unregister_chrdev_region(buzzer_dev->devno,1);325

326 err_free:327 kfree(buzzer_dev);328 returnret;329

330

331 }332

333 static void __exit buzzer_drv_exit(void)334 {335 prdebug("--------------%s----------------",__func__);336 #if BUZZER_GPIO_SWITCH

337 buzzer_gpio_exit();338 #endif

339 device_destroy(buzzer_dev->cls,buzzer_dev->devno);340 class_destroy(buzzer_dev->cls);341 cdev_del(buzzer_dev->cdev);342 unregister_chrdev_region(buzzer_dev->devno,1);343 kfree(buzzer_dev);344

345 }346

347 module_init(buzzer_drv_init);348 module_exit(buzzer_drv_exit);349 MODULE_LICENSE("GPL");350 MODULE_AUTHOR("zhuang zebin@qq.com");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值