嵌入式系統(tǒng)中實時時問的獲取
Linux系統(tǒng)中有三種類型的設(shè)備:字符設(shè)備、塊設(shè)備和網(wǎng)絡(luò)設(shè)備。字符設(shè)備是指發(fā)送和接收數(shù)據(jù)以字符的形式進行,無需緩沖直接存取,在對字符設(shè)備發(fā)出讀寫請求后,實際的硬件I/0隨即發(fā)生;而塊設(shè)備則是對數(shù)據(jù)緩沖區(qū)進行讀寫并可以隨機訪問,操作是以塊為單位。而網(wǎng)絡(luò)設(shè)備與字符設(shè)備、塊設(shè)備有很大的不同,用于對網(wǎng)絡(luò)設(shè)備的控制和管理。DSl302顯然屬于字符設(shè)備。
2.6版本的Linux內(nèi)核和2.4版本存在很大的不同,在模塊的開發(fā)和設(shè)計上也是如此。在這里使用的內(nèi)核版本是Linux一2.6.13。首先,驅(qū)動程序作為一個模塊可以動態(tài)加載進內(nèi)核也可以動態(tài)的從內(nèi)核中卸載掉,在加載和卸載的過程中實際伴隨的是驅(qū)動程序向內(nèi)核的注冊與注銷。在驅(qū)動程序的代碼中會有兩個函數(shù)分別在模塊加載和卸載過程中調(diào)用DSl302_init()、DSl302_exit(),在其中再調(diào)用register_chrdev()、unregister_chrdev()用以向內(nèi)核注冊和注銷一個設(shè)備驅(qū)動程序。在2.6內(nèi)核版本中,用如下方法聲明這兩個函數(shù)給內(nèi)核:
Module_init(DS1302_init):
Module_exit(DSl302_exit):
在DSl302_init()函數(shù)中除調(diào)用字符設(shè)備的注冊函數(shù)外,還有一個重要任務(wù),就是配置需要用到的三條I/0口線:PBO、PBl0、PBll。配置過程包括:B端口控制器時鐘使能、通用I/O口使能、輸出使能、上拉電阻使能、三個口線上的同步數(shù)據(jù)輸出使能,另外通過置PIOB_CODR寄存器使三個引腳輸出低電平。代碼如下:本文引用地址:http://www.ex-cimer.com/article/152515.htm
其中va_sys是一個結(jié)構(gòu)體,包含了AT9lRM9200處理器內(nèi)的全部寄存器,通過一條語句:AT91PS_SYS va_sys=(AT91PS SYS)AT91C_VA_BASE_SYS,把所有寄存器的最低地址賦給va_sys,這樣結(jié)構(gòu)體中的寄存器名稱就和實際的地址對應(yīng)起來了。注意:這里用到的地址都是經(jīng)過映射過的虛擬地址,在實際運行中會通過處理器內(nèi)部的MMU單元轉(zhuǎn)換為實際的物理地址發(fā)往地址總線。上述代碼中的AT91C_PI0_PBO等等是一些常數(shù)的宏定義用于寄存器賦值,比如:#define AT9lC_PIO_PBO(10),它們定義在AT91RM9200.h頭文件中。
在驅(qū)動程序中,file_operations是一個重要的結(jié)構(gòu)體,通過它把針對設(shè)備的具體操作注冊給內(nèi)核的統(tǒng)一接口。結(jié)構(gòu)體中全是函數(shù)指針,DSl302驅(qū)動程序中用到的函數(shù)有:open、release、ioctl,用于設(shè)備的打開與釋放、設(shè)備的讀寫以及設(shè)備的控制。對DSl302的讀寫都是在dsl302_ioctl()中調(diào)用相應(yīng)的讀寫函數(shù)實現(xiàn)的。
下面具體分析一下驅(qū)動程序中向DSl302發(fā)送單個字
代碼中用到的at91_set_gpi0_value()函數(shù)定義在內(nèi)核的Gpio.c文件中,最終是對10控制器的PIO_SODR(置位輸出數(shù)據(jù)寄存器)或PIO_CODR(清零輸出數(shù)據(jù)寄存器)賦值以使相應(yīng)引腳輸出需要的電平。
經(jīng)過測試,短時間內(nèi)誤差不明顯,但時鐘芯片存在積累誤差并且易受環(huán)境影響,連續(xù)幾天運行下來,誤差有數(shù)秒之多。所以,嵌入式系統(tǒng)需要通過某種方法定期使用標準時間向時鐘芯片對時,以消除誤差。下面要介紹的GPS接收機方案就可以做到這點。
評論