




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、S3C2440上門狗理七由如9)驅(qū)動開發(fā)實(shí)例講解S3C2440上看門狗(Watchdog)驅(qū)動開發(fā)實(shí)例講解嵌入式Linux之我行,主要講述和總結(jié)了本人在學(xué)習(xí)嵌入式linux中的每個步驟。一為總結(jié)經(jīng)驗,二希望能給想入門 嵌入式Linux的朋友提供方便。如有錯誤之處,謝請指正。共享資源,歡迎轉(zhuǎn)載:一、開發(fā)環(huán)境主機(jī):VMWare-Fedora 9開發(fā)板:Mini2440-64MB Nand, Kernel:編譯器:arm-linux-gcc-4.3.2二、相關(guān)概念1、平臺設(shè)備及平臺設(shè)備驅(qū)動:這個在前面篇幅:S3C2440上RTC時鐘驅(qū)動開發(fā)實(shí)例講解中已經(jīng)講過了。這里只需了解一下系統(tǒng)為我們定義的看門狗
2、(Watchdog)平臺設(shè)備及資源情況,在arch/arm/plat-s3c24xx/devs.c中,如下:/* Watchdog */*定義了 Watchdog平臺設(shè)備使用的資源,這些資源在驅(qū)動程序中都會用到*/static struct resource s3c_wdt_resource = 0 = /*Watchdog所使用IO端口資源范圍*/.start = S3C24XX_PA_WATCHDOG,.end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,.flags = IORESOURCE_MEM,,1 = /*Watchdog 中斷
3、資源*/.start = IRQ_WDT,.end = IRQ_WDT,.flags = IORESOURCE_IRQ,;/*定義了 Watchdog平臺設(shè)備*/struct platform_device s3c_device_wdt = .name = s3c2410-wdt, /*設(shè)備名稱*/.id = -1,.num_resources = ARRAY_SIZE(s3c_wdt_resource), /資源數(shù)量 */.resource = s3c_wdt_resource, /* 引用上面定義的資源 */;EXPORT_SYMBOL(s3c_device_wdt);2、混雜設(shè)備(mis
4、c設(shè)備)misc設(shè)備是Linux定義的主設(shè)備號為10的特殊字符設(shè)備,因為不符合字符設(shè)備的范疇,所以被歸納為misc設(shè)備, 在Linux中有很多這種設(shè)備,例如:LED設(shè)備、Watchdog設(shè)備等等,系統(tǒng)會根據(jù)設(shè)備的次設(shè)備號來區(qū)分具體是哪個設(shè)備, 通常這些次設(shè)備號被定義在include/linux/miscdevice.h中。在Linux中用miscdevice結(jié)構(gòu)體來描述一個misc設(shè)備,這就 意味著被定義為misc設(shè)備的驅(qū)動中就要實(shí)現(xiàn)該結(jié)構(gòu)體中的接口函數(shù)。該結(jié)構(gòu)體也定義在miscdevice.h中,如下:struct miscdevice int minor;const char *name;
5、const struct file_operations *fops;struct list_head list;struct device *parent;struct device *this_device;;三、實(shí)例講解1、Watchdog硬件結(jié)構(gòu)圖分析:我們從結(jié)構(gòu)圖和數(shù)據(jù)手冊得知,看門狗Watchdog主要是實(shí)現(xiàn)系統(tǒng)自動復(fù)位的功能,他是利用芯片內(nèi)部的定時器,定時輸出連接到電路的復(fù)位端,程序在一定時間范圍內(nèi)對定時器清零(俗稱“喂狗”),所以程序在正常工作時,定時器總是 不能溢出,也就不能產(chǎn)生復(fù)位信號;如果程序出現(xiàn)錯誤,不在定時周期內(nèi)復(fù)位看門狗,那么定時器就會溢出而產(chǎn)生復(fù)位信號使系統(tǒng)復(fù)位。
6、S3C2440的Watchdog模塊提供了三個寄存器來對Watchdog進(jìn)行操作,他們分別是:定時器控制寄存器WTCON、 定時器數(shù)據(jù)寄存器WTDAT和定時器計數(shù)寄存器WTCNT。注意:在對定時器數(shù)據(jù)寄存器WTDAT進(jìn)行操作時必須在定時 器控制寄存器WTCON使能之前寫入一個計數(shù)目標(biāo)值,當(dāng)Watchdog使能開啟后,WTDAT中的值會自動被加載到計數(shù)寄 存器WTCNT中,然后Watchdog從CPU內(nèi)部的時鐘分頻和時鐘除數(shù)因子得到一個工作周期,當(dāng)每個周期結(jié)束時計數(shù)寄 存器WTCNT中的值會1,直到遞減為0時,如果還不重新往WTCNT中寫入新的計數(shù)目標(biāo)值(即“喂狗”),則Watchdog就 產(chǎn)生
7、復(fù)位信號使系統(tǒng)復(fù)位。關(guān)于這些寄存器的功能和寄存器的各個位的操作值請參考數(shù)據(jù)手冊。2、Watchdog驅(qū)動程序具體實(shí)現(xiàn)步驟(建立驅(qū)動文件my2440_watchdog.c):注意:在每步中,為了讓代碼邏輯更加有條理和容易理解,就沒有考慮代碼的順序,比如函數(shù)要先定義后調(diào)用。如 果要編譯此代碼,請嚴(yán)格按照C語言的規(guī)范來調(diào)整代碼的順序。依然是驅(qū)動程序的最基本結(jié)構(gòu):Watchdog驅(qū)動的初始化和卸載部分及其他,如下:#include #include #include #include /*Watchdog平臺驅(qū)動結(jié)構(gòu)體,平臺驅(qū)動結(jié)構(gòu)體定義在platform_device.h中,該結(jié)構(gòu)體內(nèi)的接口函數(shù)在第
8、 步中實(shí)現(xiàn)*/static struct platform_driver watchdog_driver =.probe = watchdog_probe, /*Watchdog 探測函數(shù),在第步中實(shí)現(xiàn) */.remove = _devexit_p(watchdog_remove),/*Watchdog 移除函數(shù),在第步中實(shí)現(xiàn)*/.shutdown = watchdog_shutdown, /*Watchdog 關(guān)閉函數(shù),在第步中實(shí)現(xiàn) */.suspend = watchdog_suspend, /*Watchdog 掛起函數(shù),在第步中實(shí)現(xiàn) */.resume = watchdog_resum
9、e, /*Watchdog 恢復(fù)函數(shù),在第步中實(shí)現(xiàn) */.driver =/*注意這里的名稱一定要和系統(tǒng)中定義平臺設(shè)備的地方一致,這樣才能把平臺設(shè)備與該平臺設(shè)備的驅(qū)動關(guān)聯(lián)起 來*/.name = s3c2410-wdt,.owner = THIS_MODULE,;static int _init watchdog_init(void)/*將Watchdog注冊成平臺設(shè)備驅(qū)動*/return platform_driver_register(&watchdog_driver);static void _exit watchdog_exit(void)/*注銷Watchdog平臺設(shè)備驅(qū)動*/pla
10、tform_driver_unregister(&watchdog_driver);module_init(watchdog_init);module_exit(watchdog_exit);/*驅(qū)動程序模塊參數(shù),如果在加載驅(qū)動模塊時沒有設(shè)定這些參數(shù),則這些參數(shù)將采用默認(rèn)值,這些參數(shù)在接下來的步驟中將被一一用到,參數(shù)具體作用也將在各步驟中來說明7module_param(tmr_margin, int, 0);module_param(tmr_atboot, int, 0);module_param(nowayout, int, 0);module_param(soft_noboot,int,
11、 0);MODULE_LICENSE(GPL);MODULE_AUTHOR(Huang Gang);MODULE_DESCRIPTION(My2440 Watchdog Driver);、Watchdog平臺驅(qū)動結(jié)構(gòu)中探測函數(shù)watchdog_probe的實(shí)現(xiàn)。探測就意味著在系統(tǒng)總線中去檢測設(shè)備的存在, 然后獲取設(shè)備有用的相關(guān)資源信息,以便我們使用這些信息。代碼如下:#include #include #include #include #include #include /*定義了一個用來保存watchdog的IO端口占用的IO空間和經(jīng)過虛擬映射后的內(nèi)存地址*/static struct r
12、esource *wdt_mem;static void _iomem *wdt_base;/*保存watchdog中斷號,NORQ宏定義在irq.h中*/static int wdt_irqno = NO_IRQ;/*保存從平臺時鐘隊列中獲取watchdog的時鐘*/static struct clk *wdt_clock;#define CONFIG_WATCHDOG_ATBOOT (0)#define CONFIG_WATCHDOG_DEFAULT_TIME (15)static int tmr_atboot = CONFIG_WATCHDOG_ATBOOT;static int tmr
13、_margin = CONFIG_WATCHDOG_DEFAULT_TIME;static int soft_noboot;static unsigned int wdt_count;/*用于保存經(jīng)計算后得到的計數(shù)寄存器WTCNT的計數(shù)值*/*申明并初始化一個自旋鎖wdt_pie_lock,對Watchdog資源進(jìn)行互斥訪問*/static DEFINE_SPINLOCK(wdt_pie_lock);static int _devinit watchdog_probe(struct platform_device *pdev)int ret;int started = 0;struct res
14、ource *res;/*定義一個資源,用來保存獲取的watchdog的IO資源*/*在系統(tǒng)定義的watchdog平臺設(shè)備中獲取watchdog中斷號platform_get_irq 定義在 platform_device.h 中*/wdt_irqno = platform_get_irq(pdev, 0);if(wdt_irqno dev, no irq for watchdogn);return -ENOENT;/*申請Watchdog中斷服務(wù),這里使用的是快速中斷:IRQF_DISABLED。中斷服務(wù)程序為:wdt_irq,將Watchdog平臺設(shè)備pdev做參數(shù)傳遞過去了*/ret =
15、 request_irq(wdt_irqno, wdt_irq, IRQF_DISABLED, pdev-name, pdev);if(ret)/*錯誤處理*/dev_err(dev, IRQ%d error %dn, wdt_irqno, ret);return ret;/*獲取watchdog平臺設(shè)備所使用的IO端口資源,注意這個IORESOURCE_MEM標(biāo)志和watchdog平臺設(shè) 備定義中的一致*/res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res = NULL)/*錯誤處理*/dev_err(&pdev-dev,
16、 failed to get memory region resourcen);return -ENOENT;/*從平臺時鐘隊列中獲取watchdog的時鐘,這里為什么要取得這個時鐘,因為看門狗定時器的工作周期是由 這個時鐘和時鐘除數(shù)因子得到的。注意這里的watchdog參數(shù)要與系統(tǒng)中定義的時鐘名稱一致才能獲取得到,也就 是說,系統(tǒng)必須先定義得有watchdogo系統(tǒng)的一些時鐘定義在arch/arm/plat-s3c24xx/s3c2410-clock.c中*/wdt_clock = clk_get(&pdev-dev, watchdog);if (IS_ERR(wdt_clock)/*錯誤處
17、理*/dev_err(&pdev-dev, failed to find watchdog clock sourcen);return PTR_ERR(wdt_clock);/*時鐘獲取后要使能后才可以使用,clk_enable定義在arch/arm/plat-s3c/clock.c中*/clk_enable(wdt_clock);/*申請watchdog的IO端口資源所占用的IO空間(要注意理解IO空間和內(nèi)存空間的區(qū)別),request_mem_region 定義在 ioport.h 中*/wdt_mem = request_mem_region(res-start, res-end - r
18、es-start + 1, pdev-name);if (wdt_mem = NULL)/*錯誤處理*/dev_err(&pdev-dev, failed to reserve memory regionn);ret = -ENOENT;goto err_noclk;/*將watchdog的IO端口占用的這段IO空間映射到內(nèi)存的虛擬地址,ioremap定義在io.h中。注意:IO空間要映射后才能使用,以后對虛擬地址的操作就是對IO空間的操作,*/wdt_base = ioremap(res-start, res-end - res-start + 1);if (wdt_base = NULL)
19、/*錯誤處理*/dev_err(&pdev-dev, failed ioremap()n);ret = -EINVAL;goto err_noreq;/*好了,通過上面的步驟已經(jīng)將watchdog的資源都準(zhǔn)備好了,下面就開始使用啦*/*這里是計算并設(shè)置看門狗定時器時鐘周期值,wdt_set_heartbeat定義在下面。符合數(shù)據(jù)手冊中要求的,在看門狗定時器開始工作之前,一個初始值必須先寫入看門狗定時器計數(shù)寄存器WTCNT中七其實(shí)這里就是初始化看門狗 定時器*/if (wdt_set_heartbeat(pdev, tmr_margin)/*這里調(diào)用兩次的意思是看能不能設(shè)置成期望的值,如果不能就
20、設(shè)置默認(rèn)的值*/started = wdt_set_heartbeat(pdev, CONFIG_WATCHDOG_DEFAULT_TIME);/*打印設(shè)置的值信息*/if (started = 0)dev_info(&pdev-dev, tmr_margin value out of range, default %d usedn, CONFIG_WATCHDOG_DEFAULT_TIME);elsedev_info(&pdev-dev, default timer value is out of range, cannot startn);/*device_init_wakeup該函數(shù)定義
21、在pm_wakeup.h中,定義如下:static inline void device_init_wakeup(struct device *dev, int val)dev-power.can_wakeup = dev-power.should_wakeup = !val;顯然這個函數(shù)是讓驅(qū)動支持電源管理的,這里只要知道,can_wakeup為1時表明這個設(shè)備可以被喚醒,設(shè)備驅(qū)動 為了支持Linux中的電源管理,有責(zé)任調(diào)用device_init_wakeup()來初始化can_wakeup,而should_wakeup則是在設(shè) 備的電源狀態(tài)發(fā)生變化的時候被device_may_wakeup
22、()用來測試,測試它該不該變化,因此can_wakeup表明的是一種能力,而should_wakeup表明的是有了這種能力以后去不去做某件事。好了,我們沒有必要深入研究電源管理的內(nèi) 容了,要不就扯遠(yuǎn)了,電源管路以后再講*/device_init_wakeup(&pdev-dev, 1);/*把看門狗設(shè)備又注冊成為misc設(shè)備,misc_register定義在miscdevice.h中wdt_miscdev結(jié)構(gòu)體定義及內(nèi)部接口函數(shù)在第步中講*/ret = misc_register(&wdt_miscdev);if (ret)/*錯誤處理*/dev_err(&pdev-dev, cannot r
23、egister miscdev on minor=%d (%d)n, WATCHDOG_MINOR, ret);goto err_nomap;/*函數(shù)wdt_start_or_stop定義在下面*/if (tmr_atboot & started = 0)wdt_start_or_stop(1);/*參數(shù)1表示啟動看門狗定時器*/else if (!tmr_atboot)wdt_start_or_stop(0);/*參數(shù)0表示停止看門狗定時器*/return 0;以下是上面錯誤處理的跳轉(zhuǎn)點(diǎn)err_noclk:clk_disable(wdt_clock);clk_put(wdt_clock);e
24、rr_noreq:release_resource(wdt_mem);kfree(wdt_mem);err_nomap:iounmap(wdt_base);return ret;/*看門狗定時器中斷服務(wù)程序*/static irqreturn_t wdt_irq(int irq, void *argv)/*主要要做的事情是在看門狗定時器計數(shù)寄存器值遞減到0之前重新寫入新值(即:“喂狗”廣/wdt_keepalive();return IRQ_HANDLED;/*看門狗定時器“喂狗”*/static void wdt_keepalive(void)spin_lock(&wdt_lock);/*獲
25、取自旋鎖保護(hù)臨界區(qū)資源*/writel(wdt_count, wdt_base + S3C2410_WTCNT);/*往計數(shù)寄存器 WTCNT 重新寫入計數(shù)值*/spin_unlock(&wdt_lock);/* 釋放自旋鎖,即解鎖 */*計算并設(shè)置看門狗定時器時鐘周期值并初始化看門狗定時器*/static int wdt_set_heartbeat(struct platform_device *pdev, int timeout)unsigned int freq = clk_get_rate(wdt_clock);unsigned int count;unsigned int divis
26、or = 1;unsigned long wtcon;if (timeout = 0 x10000)for (divisor = 1; divisor = 0 x100; divisor+)if (count / divisor) = 0 x10000)dev_err(&pdev-dev, timeout %d too bign, timeout);return -EINVAL;tmr_margin = timeout;count /= divisor;wdt_count = count;wtcon = readl(wdt_base + S3C2410_WTCON);/* wtcon=1000
27、000000100001 這是控制寄存器的默認(rèn)值,看 數(shù)據(jù)手冊得到*/wtcon &= S3C2410_WTCON_PRESCALE_MASK; /* wtcon=1000000000100001 & -1111111100000000 = 0000000000100001 */*S3C2410_WTCON_PRESCALE宏是將divisor-1的值向左位移8位,也就是說該值的右8位都為0,則計算 如下:wtcon=0000000000100001 | (xxxxxxxx)00000000 = (xxxxxxxx)00100001*/wtcon |= S3C2410_WTCON_PRESCA
28、LE(divisor-1);/*設(shè)置看門狗定時器數(shù)據(jù)寄存器WTDAT的值,然后WTDAT的值會自動加載到WTCNT中*/writel(count, wdt_base + S3C2410_WTDAT);/*根據(jù)數(shù)據(jù)手冊和上面計算的wtcon值可得,下面是設(shè)置看門狗定時控制寄存器WTCON為:看門狗定時器輸出使能有效、一個保留位默認(rèn)0、中斷使能無效、時鐘除數(shù)因子為16、看門狗定時器使能有效、兩個保留位默認(rèn)00、預(yù)定標(biāo)器值為xxxxxxxx的內(nèi)容。*/writel(wtcon, wdt_base + S3C2410_WTCON);return 0;/*根據(jù)標(biāo)志flag的值來啟動或者停止看門狗定時器,
29、1表示啟動,0表示停止*/static void wdt_start_or_stop(int flag)unsigned long wtcon;spin_lock(&wdt_pie_lock);/*獲取自旋鎖保護(hù)臨界區(qū)資源*/*停止看門狗定時器,以下各寄存器的位操作請參照數(shù)據(jù)手冊*/wtcon = readl(wdt_base + S3C2410_WTCON);wtcon &= (S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN);writel(wtcon, wdt_base + S3C2410_WTCON);if(!flag)wtcon = readl(w
30、dt_base + S3C2410_WTCON);wtcon |= S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128;if (soft_noboot)wtcon |= S3C2410_WTCON_INTEN;wtcon &= S3C2410_WTCON_RSTEN;elsewtcon &= S3C2410_WTCON_INTEN;wtcon |= S3C2410_WTCON_RSTEN;writel(wdt_count, wdt_base + S3C2410_WTDAT);writel(wdt_count, wdt_base + S3C2410_WTCNT
31、);writel(wtcon, wdt_base + S3C2410_WTCON);spin_unlock(&wdt_pie_lock);/* 釋放自旋鎖,即解鎖 */實(shí)現(xiàn)misc設(shè)備中對設(shè)備文件的操作,代碼如下:#include #include #include /*申明并初始化一個信號量open_clock,對Watchdog資源進(jìn)行互斥訪問,注意:這里的信號量和第笏中的 自旋鎖的區(qū)別,雖然都是達(dá)到資源互斥訪問的目的,但信號量是進(jìn)程級的,也就是說信號量是用在多個進(jìn)程 中對同一資源的互斥訪問,下面的使用會在wdt_open和wdt_release兩個進(jìn)程中對Watchdog資源進(jìn)行互斥 訪
32、問。對于自旋鎖和信號量的具體區(qū)別,請在網(wǎng)上找,這里不再多說了 */static DECLARE_MUTEX(open_clock);/*用來表示 Linux內(nèi)核配置選項中配不配置 CONFIG_WATCHDOG_NOWAYOUT項, WATCHDOG_NOWAYOUT定義在 watchdog.h 中*/static int nowayout = WATCHDOG_NOWAYOUT;typedef enum close_stateCLOSE_STATE_NOT,CLOSE_STATE_ALLOW = 0 x4021 close_state_t;static close_state_t allow
33、_close; /*用于記錄看門狗定時器的當(dāng)前的操作狀態(tài)*/*misc設(shè)備結(jié)構(gòu)體實(shí)現(xiàn)*/static struct miscdevice wdt_miscdev = .minor = WATCHDOG_MINOR, /*WATCHDOG_MINOR次設(shè)備號定義在 miscdevice.h 中為 130*/.name = watchdog, /* 設(shè)備名稱 */.fops = &wdt_fops, /*實(shí)現(xiàn)字符設(shè)備的相關(guān)操作*/;/*字符設(shè)備的相關(guān)操作實(shí)現(xiàn)*/static const struct file_operations wdt_fops = .owner = THIS_MODULE,.
34、open = wdt_open,.release = wdt_release,.write = wdt_write,.ioctl = wdt_ioctl,.llseek = no_llseek, /*定義為不可定位,即屏蔽seek操作,no_llseek定義在fs.h中*/;/*看門狗設(shè)備驅(qū)動的打開接口函數(shù)*/static int wdt_open(struct inode *inode, struct file *file)/*試著獲取信號量(即:加鎖),如果獲取不成功,說明其他進(jìn)程此時占用了,就返回忙*/if(down_trylock(&open_clock)return -EBUSY;i
35、f(nowayout)/*如果內(nèi)核配置了 CONFIG_WATCHDOG_NOWAYOUT項,則使模塊使用計數(shù)加1*/_module_get(THIS_MODULE);/*開始記錄看門狗定時器的當(dāng)前操作狀態(tài)為:無狀態(tài)*/allow_close = CLOSE_STATE_NOT;/*啟動看門狗定時器*/wdt_start_or_stop(1);/*表示返回的這個設(shè)備文件是不可以被seek操作的,nonseekable_open定義在fs.h中*/return nonseekable_open(inode, file);/*看門狗設(shè)備驅(qū)動的關(guān)閉接口函數(shù)*/static int wdt_relea
36、se(struct inode *inode, struct file *file)/*如果判斷到當(dāng)前操作狀態(tài)是可以關(guān)閉看門狗定時器時就關(guān)閉,否則就是喂狗”狀態(tài)*/if(allow_close = CLOSE_STATE_ALLOW)wdt_start_or_stop(0);/* 關(guān)閉 */elsewdt_keepalive();/* “喂狗 ”*/*恢復(fù)看門狗定時器的當(dāng)前操作狀態(tài)為:無狀態(tài)*/allow_close = CLOSE_STATE_NOT;/*釋放獲取的信號量(即:解鎖),與wdt_open中加鎖相對應(yīng)*/up(&open_lock);return 0;/*看門狗設(shè)備驅(qū)動的寫數(shù)據(jù)
37、接口函數(shù)*/static ssize_t wdt_write(struct file *file, const char _user *buff, size_t len, loff_t *ppos)if(len)/*判斷有數(shù)據(jù)寫入*/if(!nowayout)/*如果沒有配置內(nèi)核 CONFIG_WATCHDOG_NOWAYOUT選項*/size_t i;/*設(shè)看門狗定時器的當(dāng)前操作狀態(tài)為:無狀態(tài)*/allow_close = CLOSE_STATE_NOT;for (i = 0; i != len; i+)char c;if (get_user(c, data + i)return -EFAU
38、LT;if (c = V)/*判斷寫入的數(shù)據(jù)是V時,則設(shè)看門狗定時器的當(dāng)前操作狀態(tài)為關(guān)閉*/allow_close = CLOSE_STATE_ALLOW;/*上面的意思是想要看門狗定時器可以被關(guān)閉,則內(nèi)核不要配置CONFIG_WATCHDOG_NOWAYOUT選項, 對于下面這里還要“喂狗”一次,我剛開始覺得不需要,因為在看門狗定時器中斷里面不斷的在“喂狗”。后來想想,這里還必須要“喂狗”一次,因為當(dāng)上面我們判斷到寫入的數(shù)據(jù)是V時,看門狗定時器的當(dāng)前操作狀態(tài)馬上被設(shè)置為關(guān)閉,再當(dāng)驅(qū)動去調(diào)用看門狗設(shè)備驅(qū)動的關(guān)閉接口函數(shù)時,看門狗定時器中斷被禁止,無法再實(shí)現(xiàn)“喂狗”,所以這里要手動“喂狗”一次,
39、否則定時器溢出系統(tǒng)被復(fù)位*/wdt_keepalive();return len;/*用于支持看門狗IO控制中獲取看門狗信息的命令WDIOC_GETSUPPORT,下面的宏和看門狗信息結(jié)構(gòu)體定義在watchdog.h中*/#define OPTIONS WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE static const struct watchdog_info wdt_ident =.options = OPTIONS,.firmware_version = 0,.identity = S3C2440 Watchdog,
40、;/*看門狗設(shè)備驅(qū)動的IO控制接口函數(shù)*/static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)void _user *argp = (void _user *)arg;int _user *p = argp;int new_margin;/*以下對看門狗定時器IO控制的命令定義在watchdog.h中*/switch (cmd)case WDIOC_GETSUPPORT: /獲取看門狗的支持信息,wdt_ident定義在上面*/return copy_to_user(argp, &wdt_id
41、ent, sizeof(wdt_ident) ? -EFAULT : 0;case WDIOC_GETSTATUS:case WDIOC_GETBOOTSTATUS:/獲取看門夠狀態(tài) */return put_user(0, p);case WDIOC_KEEPALIVE:/* 喂狗命令 */wdt_keepalive();return 0;case WDIOC_SETTIMEOUT:/*設(shè)置定時器溢出時間值命令(時間單位為秒廣/if (get_user(new_margin, p)/* 獲取時間值 */return -EFAULT;if (wdt_set_heartbeat(new_marg
42、in)/*設(shè)置到計數(shù)寄存器 WTCNT 中*/return -EINVAL;wdt_keepalive();/* 喂狗 */return put_user(tmr_margin, p);case WDIOC_GETTIMEOUT:/*讀取定時器默認(rèn)溢出時間值命令(時間單位為秒廣/return put_user(tmr_margin, p);default:return -ENOTTY;.Watchdog平臺驅(qū)動的設(shè)備移除、掛起和恢復(fù)接口函數(shù)的實(shí)現(xiàn),代碼如下:/*Watchdog平臺驅(qū)動的設(shè)備移除接口函數(shù)的實(shí)現(xiàn)*/static int _devexit wdt_remove(struct pla
43、tform_device *dev)/*釋放獲取的Watchdog平臺設(shè)備的IO資源*/release_resource(wdt_mem);kfree(wdt_mem);wdt_mem = NULL;/*同watchdog_probe中中斷的申請相對應(yīng),在那里申請中斷,這里就釋放中斷*/free_irq(wdt_irqno, dev);wdt_irq = NULL;/*釋放獲取的Watchdog平臺設(shè)備的時鐘*/clk_disable(wdt_clock);clk_put(wdt_clock);wdt_clock = NULL;/*釋放Watchdog設(shè)備虛擬地址映射空間*/iounmap(w
44、dt_base);/*注銷misc設(shè)備*/misc_deregister(&wdt_miscdev);return 0;/*Watchdog平臺驅(qū)動的設(shè)備關(guān)閉接口函數(shù)的實(shí)現(xiàn)*/static void wdt_shutdown(struct platform_device *dev)/*停止看門狗定時器*/wdt_start_or_stop(0);/*對Watchdog平臺設(shè)備驅(qū)動電源管理的支持。CONFIG_PM這個宏定義在內(nèi)核中,當(dāng)配置內(nèi)核時選上電源管理,則Watchdog平臺驅(qū)動的設(shè)備掛起和恢復(fù)功能均有效,這時候你應(yīng)該明白了在第步中為什么要有device_init_wakeup(&pdev-dev, 1這句吧! ! */#ifdef CONFIG_PM/*定義兩個變量來分別保存掛起時的WTCON和WTDAT值,到恢復(fù)的時候使用*/static unsigned long wtcon_save;static unsigned long wtdat_save;/*Watchdog平臺驅(qū)動的設(shè)備掛起接口函數(shù)的實(shí)現(xiàn)*/static int wdt_suspend(struct platform_device *dev, pm_message_t state)/*保
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 提升社區(qū)服務(wù)效率的策略計劃
- 小學(xué)機(jī)器人編程課 1.《抽油機(jī)》活動教學(xué)設(shè)計
- 人教版初中歷史與社會七年級上冊 1.2 .1鄉(xiāng)村聚落教學(xué)設(shè)計
- 員工參與感與歸屬感提升計劃
- 音樂家的新年個人工作計劃
- 2025年美術(shù)《烏龜》標(biāo)準(zhǔn)教案
- 藝術(shù)行業(yè):平面設(shè)計師求職信簡歷
- 2025年籃球運(yùn)球教學(xué)標(biāo)準(zhǔn)教案
- 三病母嬰阻斷知識
- 2025年南平貨運(yùn)從業(yè)資格證考試模擬
- 正確識記現(xiàn)代漢語常用字字形課件
- 化工機(jī)械安裝維修
- 讀后續(xù)寫微技巧情感描寫
- 2023年《中華人民共和國婦女權(quán)益保障法》知識競賽試題及答案
- 夏天、煙火和我的尸體
- AI工業(yè)信息化高價值、高普及、高認(rèn)可之路
- 2023英語新課標(biāo)義務(wù)教育英語課程標(biāo)準(zhǔn)
- 高考作文模擬寫作:“雷鋒精神的時代價值”導(dǎo)寫及范文
- 魯科版高中化學(xué)必修2全冊教案
- GB/T 9239.1-2006機(jī)械振動恒態(tài)(剛性)轉(zhuǎn)子平衡品質(zhì)要求第1部分:規(guī)范與平衡允差的檢驗
- GB/T 6183.1-2000非金屬嵌件六角法蘭面鎖緊螺母
評論
0/150
提交評論