九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 4095|回复: 0
打印 上一主题 下一主题

x4412&ibox项目实战46-Linux内核延时实验

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-14 19:19:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
linux的内核延时包括短延时,长延时以及休眠延时。
1.1.1    短延时
Linux内核中提供了如下3个函数分别进行纳秒、微秒和毫秒延迟。
  1. void ndelay(unsigned long nsecs);
  2. void udelay(unsigned long usecs);
  3. void mdelay(unsigned long msecs);
复制代码
上述延迟的实现原理本质上是忙等待,它根据CPU频率进行一定次数的循环。在单片机程序中,经常见到如下的延时函数:
  1. void delay(unsigned int i,j)
  2. {
  3.          for(i=0;i<255;i++)
  4.                    for(j=0;j<255,j++);
  5. }
复制代码
ndelay()、udelay()和 mdelay()函数的实现方式机理与此类似。毫秒相对内核来说已经很大了,在进行毫秒延时时,不推荐使用这种忙等待的方式延时。
1.1.2    长延时
内核中进行延迟的一个很直观的方法是比较当前的jiffies和目标jiffies(设置为当前 jiffies加上时间间隔的jiffies),直到未来的jiffies达到目标jiffies。
jiffies是一个全局变量,用来记录自系统启动以来产生的节拍的总数,它反应了系统所运行的时间。启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。一秒内时钟中断的次数等于HZ,所以jiffies一秒内增加的值也就是Hz。
   系统运行时间以秒为单位,等于jiffies/HZ。注意,jiffies类型为无符号长整型(unsigned long),其他任何类型存放它都不正确。
将以秒为单位的时间转化为jiffies:
  1. seconds * HZ
复制代码
将jiffies转化为以秒为单位的时间:
  1. jiffies / HZ
复制代码
相比之下,内核中将秒转换为jiffies用的多些。
以下程序表示延时100个jiffies:
  1. <span style="line-height: 1.5;">unsigned long delay = jiffies + 100;</span>
  2. while (time_before(jiffies, delay));
复制代码
以下程序表示延时2秒:
  1. unsigned long delay = jiffies + 2*HZ;
  2. while (time _ before(jiffies, delay));
复制代码
1.1.3    休眠延时
休眠延时指在进程调用延时期间主动进入睡眠状态,CPU被其他进程使用。对于毫秒级以上的延时,推荐使用休眠延时,内核提供了以下几个函数:
  1. void msleep(unsigned int millisecs);
  2. unsigned long msleep_interruptible(unsigned int milosecs);
  3. void ssleep(unsigned int seconds);
复制代码
1.1.4    内核延时示例
编写一个驱动模块,通过不同的延时方式,控制蜂鸣器间隔鸣叫。
在kernel/drivers/char/x4412目录下新建x4412-delay.c文件,参考代码如下:
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/fs.h>
  5. #include <linux/uaccess.h>
  6. #include <linux/timer.h>
  7. #include <linux/jiffies.h>
  8. #include <linux/delay.h>
  9. #include <linux/sched.h>
  10. #include <linux/kthread.h>
  11. #include <linux/gpio.h>
  12. #include <plat/gpio-cfg.h>
  13. static void x4412_beep_init(void)
  14. {
  15.          int ret;
  16.          ret = gpio_request(EXYNOS4_GPD0(1), "GPD0(1)");
  17.          if(ret)
  18.                    printk("x4412-beep: request gpio GPD0(1) fail\n");
  19.          s3c_gpio_setpull(EXYNOS4_GPD0(1), S3C_GPIO_PULL_UP);
  20.          s3c_gpio_cfgpin(EXYNOS4_GPD0(1), S3C_GPIO_SFN(1));
  21.          gpio_set_value(EXYNOS4_GPD0(1), 0);
  22. }
  23. static int thread_process(void* param)
  24. {
  25.          unsigned long delay;
  26.          while(1)
  27.          {
  28.                    set_current_state(TASK_UNINTERRUPTIBLE);
  29.                    if(kthread_should_stop())
  30.                    {
  31.                             printk("kernel thread should stop;file:%s;line:%d\n", __FILE__, __LINE__);
  32.                             break;
  33.                    }
  34.                    //滴
  35.                    mdelay(5*HZ);
  36.                    gpio_set_value(EXYNOS4_GPD0(1), 1);
  37.                    mdelay(1*HZ);
  38.                    gpio_set_value(EXYNOS4_GPD0(1), 0);
  39.                    //滴滴
  40.                    delay = jiffies + 2*HZ;
  41.                    while(time_before(jiffies,delay));//延时2s
  42.                    gpio_set_value(EXYNOS4_GPD0(1), 1);
  43.                    mdelay(100);//延时100000us,即100ms
  44.                    gpio_set_value(EXYNOS4_GPD0(1), 0);
  45.                    mdelay(100);//延时100ms
  46.                    gpio_set_value(EXYNOS4_GPD0(1), 1);
  47.                    msleep_interruptible(100);//延时100ms
  48.                    gpio_set_value(EXYNOS4_GPD0(1), 0);
  49.                    //滴滴滴
  50.                    mdelay(5*HZ);
  51.                    gpio_set_value(EXYNOS4_GPD0(1), 1);
  52.                    mdelay(100);
  53.                    gpio_set_value(EXYNOS4_GPD0(1), 0);
  54.                    mdelay(100);
  55.                    gpio_set_value(EXYNOS4_GPD0(1), 1);
  56.                    mdelay(100);
  57.                    gpio_set_value(EXYNOS4_GPD0(1), 0);
  58.                    mdelay(100);
  59.                    gpio_set_value(EXYNOS4_GPD0(1), 1);
  60.                    mdelay(100);
  61.                    gpio_set_value(EXYNOS4_GPD0(1), 0);
  62.          }
  63.          return 1;
  64. }
  65. static struct task_struct* x4412_thread = NULL;
  66. static int __init x4412_second_init(void)
  67. {
  68.          int err = 0;
  69.          x4412_beep_init();
  70.          x4412_thread = kthread_create(thread_process, NULL, "x4412_thread");
  71.          if(IS_ERR(x4412_thread))
  72.          {
  73.                    err = PTR_ERR(x4412_thread);
  74.                    x4412_thread = NULL;
  75.                    printk(KERN_ERR "unable to start kernel thread:%d\n", err);
  76.                    return err;
  77.          }
  78.          wake_up_process(x4412_thread);
  79.          printk("x4412 kernel thread start;file:%s;line:%d\n", __FILE__, __LINE__);
  80.          return 0;
  81. }
  82. static void x4412_second_exit(void)
  83. {
  84.          int ret = -1;
  85.          if(x4412_thread)
  86.          {
  87.                    ret = kthread_stop(x4412_thread);
  88.                    x4412_thread = NULL;
  89.          }
  90.          gpio_set_value(EXYNOS4_GPD0(1), 0);
  91.          gpio_free(EXYNOS4_GPD0(1));
  92. }
  93. MODULE_AUTHOR("www.9tripod.com");
  94. MODULE_LICENSE("Dual BSD/GPL");
  95. module_init(x4412_second_init);
  96. module_exit(x4412_second_exit);
复制代码
       该驱动使用了多种延时方法,用于控制蜂鸣器的鸣叫间隔。
       kernel/drivers/char/x4412/Kconfig中添加如下语句:
  1. config X4412_DELAY_DRIVER
  2.          tristate "x4412 delay driver"
  3.          default m
  4.          help
  5.          compile for x4412 delay driver,y for kernel,m for module.
复制代码
       kernel/drivers/char/x4412/Makefile中添加如下语句:
  1. obj-$(CONFIG_X4412_DELAY_DRIVER) += x4412-delay.o
复制代码
       编译内核,在kernel/drivers/char/x4412目录下将会生成目标文件x4412-delay.ko。加载内核,观察蜂鸣器的现象。当卸载模块后,蜂鸣器将停止鸣叫。
      编译好的驱动模块:
x4412-delay.ko (4.01 KB, 下载次数: 4)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-6-14 18:30 , Processed in 0.019778 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表