linux核心延時

來源:互聯網
上載者:User
 
 

1、#include <linux/time.h>

void do_gettimeofday(struct timeval *tv)
{
 unsigned long flags;
 unsigned long usec, sec;

 read_lock_irqsave(&xtime_lock, flags);
 sec = xtime.tv_sec;
 usec = xtime.tv_usec + do_gettimeoffset();
 read_unlock_irqrestore(&xtime_lock, flags);

 while (usec >= 1000000) {
  usec -= 1000000;
  sec++;
 }

 tv->tv_sec = sec;
 tv->tv_usec = usec;
}

void MyDelay(unsigned long delay)
{
 struct timeval tv;
 do_gettimeofday(&tv)
 unsigned long start = tv.tv_usec;//unsigned long start = tv.tv_sec;
 while(tv.tv_usec - start <delay)
    do_gettimeofday(&tv)
}

2、如果驅動程式使用等待隊列等待某個事件,而你又想確保在一段時間後運行該驅動程式時
extern inline long sleep_on_timeout(wait_queue_head_t *q, signed long timeout)
{
    signed long early = 0;
       
    current->timeout = jiffies + timeout;
    sleep_on (q);
    if (current->timeout > 0) {
        early = current->timeout - jiffies;
        current->timeout = 0;
    }
    return early;
}

extern inline long interruptible_sleep_on_timeout(wait_queue_head_t *q,
                signed long timeout)
{
    signed long early = 0;
       
    current->timeout = jiffies + timeout;
    interruptible_sleep_on (q);
    if (current->timeout > 0) {
        early = current->timeout - jiffies;
        current->timeout = 0;
    }
    return early;
}

3.無需等待其他事件,則可直接延時等待
extern inline void schedule_timeout(int timeout)
{
    current->timeout = jiffies + timeout;
    current->state = TASK_INTERRUPTIBLE;
    schedule();
    current->timeout = 0;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(jit_delay*HZ);

4
非常短的延時與硬體同步 udelay推薦最大1000us

#include<linux/delay.h>

void __delay(int loops)
{
 long long dummy;
 __asm__ __volatile__("gettr " __t0 ", %1/n/t"
        "_pta 4, " __t0 "/n/t"
        "addi %0, -1, %0/n/t"
        "bne %0, r63, " __t0 "/n/t"
        "ptabs %1, " __t0 "/n/t":"=r"(loops),
        "=r"(dummy)
        :"0"(loops));
}

void __udelay(unsigned long long usecs, unsigned long lpj)
{
 usecs *= (((unsigned long long) HZ << 32) / 1000000) * lpj;
 __delay((long long) usecs >> 32);
}

#ifdef notdef
#define mdelay(n) (/
 {unsigned long msec=(n); while (msec--) udelay(1000);})
#else
#define mdelay(n) (/
 (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : /
 ({unsigned long msec=(n); while (msec--) udelay(1000);}))
#endif

 

發表於: 2006-08-14,修改於: 2006-08-14 14:32,已瀏覽1690次,有評論2條 推薦 投訴
     
     

 

   

   
   
 
 
 
定義一個定時器static struct timer_list scan_timer;

int __init ir_init_module(void)載入初始化時
{      init_timer(&scan_timer);初始化定時器
    scan_timer.function=pad_poll_scan;  // scan
    scan_timer.data= (unsigned long)&pad_priv;
}
static void pad_poll_scan(unsigned long dev_id)
{
--add your code
mod_timer(&scan_timer, jiffies + (scan_period ));//it will add timer internal
 
   

   
   
 
 
 
#include <asm/param.h>
#include <linux/timer.h>
void add_timer(struct timer_list * timer);
int  del_timer(struct timer_list * timer);
inline void init_timer(struct timer_list * timer);
struct timer_list的定義為:
struct timer_list {
               struct timer_list *next;
               struct timer_list *prev;
               unsigned long expires;
               unsigned long data;
               void (*function)(unsigned long d);
       };
其中expires是要執行function的時間。系統核心有一個全域變數JIFFIES
表示目前時間,一般在調用add_timer時jiffies=JIFFIES+num,表示在num個
系統最小時間間隔後執行function。系統最小時間間隔與所用的硬體平台有關,
在核心裡定義了常數HZ表示一秒內最小時間間隔的數目,則num*HZ表示num
秒。系統計時到預定時間就調用function,並把此子程式從定時隊列裡刪除,
因此如果想要每隔一定時間間隔執行一次的話,就必須在function裡再一次調
用add_timer。function的參數d即為timer裡面的data項。
有時驅動程式需要非常短的延遲來與硬體同步。此時,使用jiffies值無法達到目的。這時就要用核心功能udelay和mdelay。u表示希臘字母“mu”(m),它代表“微”。它們的原型如下:
#include <Linux/delay.h>
void udelay(unsigned long usecs); //軟體迴圈延遲指定數目的微秒數
void mdelay(unsigned long msecs); //使用 udelay 做迴圈
該函數在絕大多數體繫結構上是作為內嵌函式編譯的。udelay函數裡要用到BogoMips值:它的迴圈基於整數值loops_per_second,這個值是在引導階段計算BogoMips時得到的結果。
udelay函數只能用於擷取較短的時間延遲,因為loops_per_second值的精度只有8位,所以,當計算更長的延遲時會積累出相當大的誤差。儘管最大能允許的延遲將近1s(因為更長的延遲就要溢出),推薦的udelay函數參數最大值是取1000us(1ms)。當延遲大於11ms時可以使用函數mdelay。許多驅動程式需要將任務延遲到以後處理,但又不想藉助中斷。Linux為此提供了三種方法:任務隊列、tasklet和核心定時器。
要特別注意的是udelay是個忙等待函數,在延遲的時間段內無法運行其他的任務。源碼見標頭檔<asm/delay.h>。 
 
目前核心不支援大於1微秒而小於1個時鐘滴答的延遲,但這不是個問題,因為延遲是給硬體或者人去識別的。百分之一秒的時間間隔對人來說延遲精度足夠了,而1毫秒對硬體來說延遲時間也足夠長。如果你真的需要其間的延遲間隔,你只要建立一個連續執行udelay(1000)函數的迴圈。
linux核心延時函數程式碼範例: 
1、#include <linux/time.h>
void do_gettimeofday(struct timeval *tv)
{
 unsigned long flags;
 unsigned long usec, sec;
 read_lock_irqsave(&xtime_lock, flags);
 sec = xtime.tv_sec;
 usec = xtime.tv_usec + do_gettimeoffset();
 read_unlock_irqrestore(&xtime_lock, flags);
 while (usec >= 1000000) {
  usec -= 1000000;
  sec++;
 }
 tv->tv_sec = sec;
 tv->tv_usec = usec;
}
void MyDelay(unsigned long delay)
{
 struct timeval tv;
 do_gettimeofday(&tv)
 unsigned long start = tv.tv_usec;//unsigned long start = tv.tv_sec;
 while(tv.tv_usec - start <delay)
    do_gettimeofday(&tv)
}
2、如果驅動程式使用等待隊列等待某個事件,而你又想確保在一段時間後運行該驅動程式時
extern inline long sleep_on_timeout(wait_queue_head_t *q, signed long timeout)
{
    signed long early = 0;
       
    current->timeout = jiffies + timeout;
    sleep_on (q);
    if (current->timeout > 0) {
        early = current->timeout - jiffies;
        current->timeout = 0;
    }
    return early;
}
extern inline long interruptible_sleep_on_timeout(wait_queue_head_t *q,
                signed long timeout)
{
    signed long early = 0;
       
    current->timeout = jiffies + timeout;
    interruptible_sleep_on (q);
    if (current->timeout > 0) {
        early = current->timeout - jiffies;
        current->timeout = 0;
    }
    return early;
}
3.無需等待其他事件,則可直接延時等待
extern inline void schedule_timeout(int timeout)
{
    current->timeout = jiffies + timeout;
    current->state = TASK_INTERRUPTIBLE;
    schedule();
    current->timeout = 0;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(jit_delay*HZ);
4 非常短的延時與硬體同步 udelay推薦最大1000us
#include<linux/delay.h>
void __delay(int loops)
{
 long long dummy;
 __asm__ __volatile__("gettr " __t0 ", %1/n/t"
        "_pta 4, " __t0 "/n/t"
        "addi %0, -1, %0/n/t"
        "bne %0, r63, " __t0 "/n/t"
        "ptabs %1, " __t0 "/n/t":"=r"(loops),
        "=r"(dummy)
        :"0"(loops));
}
void __udelay(unsigned long long usecs, unsigned long lpj)
{
 usecs *= (((unsigned long long) HZ << 32) / 1000000) * lpj;
 __delay((long long) usecs >> 32);
}
#ifdef notdef
#define mdelay(n) (/
 {unsigned long msec=(n); while (msec--) udelay(1000);})
#else
#define mdelay(n) (/
 (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : /
 ({unsigned long msec=(n); while (msec--) udelay(1000);}))
#endif

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.