郭小梅
(南京曉莊學院,南京210001)
郭小梅(副教授),主要研究領(lǐng)域計算機軟件與理論、嵌入式應用技術(shù)。
當今的電子消費領(lǐng)域,重力感應技術(shù)正以其迅猛的速度在發(fā)展。它在游戲機、移動存儲設(shè)備、智能電動車中有著廣泛的應用;在高端智能手機、平板電腦等嵌入式移動產(chǎn)品中,其應用也越來越普及,它將給人們帶來更為方便、有趣、實用、豐富的全新體驗。
MX51是飛思卡爾半導體基于ARM Cortex-A8內(nèi)核的高端ARM嵌入式多媒體處理器,它支持豐富的多媒體功能組合和外圍設(shè)備,處理器接口支持與所有常用外部存儲的連接,在工作和各種低功耗模式下實現(xiàn)最小的系統(tǒng)功耗,滿足操作系統(tǒng)和游戲系統(tǒng)越來越多的MIPS需求。嵌入式Linux操作系統(tǒng)以其免費、開源及功能強大等特點,被廣泛應用于各類便攜式產(chǎn)品中,由于 Linux操作系統(tǒng)只提供相關(guān)設(shè)備的驅(qū)動接口,實際應用中,需針對具體芯片開發(fā)相關(guān)的驅(qū)動程序。本文以 Linux2.6.31內(nèi)核和MX51為系統(tǒng)的軟、硬件平臺,討論了重力感應驅(qū)動程序的實現(xiàn)技術(shù)。
G-sensor表示重力傳感器,它是一種可以將運動或重力轉(zhuǎn)換為電信號的傳感器。重力感應利用壓電效應實現(xiàn),通過測量內(nèi)部一片重物(重物和壓電片做成一體)重力正交兩個方向的分力大小,來判斷水平方向。G-sensor內(nèi)置3軸(X、Y和Z軸)加速計,實際應用中通常以這3個軸(或任意兩個軸)所構(gòu)成的角度來計算物體的傾斜角度,從而計算出重力加速度的值。
當物體位置發(fā)生變化,如晃動、跌落、旋轉(zhuǎn)、上升、下降時,其所產(chǎn)生的加速力被G-sensor轉(zhuǎn)化為電信號,通過微處理器的計算分析后,可完成設(shè)計中的特定功能。重力感應技術(shù)應用在移動存儲設(shè)備上,利用重力加速度原理,一旦偵測到意外,能在摔落的瞬間將磁頭撤至安全停泊區(qū),有效確保工作狀態(tài)下的產(chǎn)品安全。在手機中應用此項技術(shù),可以根據(jù)使用者的動作實現(xiàn)屏幕圖像翻轉(zhuǎn)、功能選擇、游戲控制等。
本設(shè)計采用飛思卡爾半導體的MX51多媒體應用處理器開發(fā)板。處理器集成了3個I2C接口:I2C1和I2C2是普通I2C總線,HSI2C是高速I2C總線。G-sensor芯片LIS33DE通過I2C2接口連接到MX51的總線上。圖1為硬件連接圖。

圖1 LⅠS33DE的硬件平臺
LIS33DE是ST(意法半導體)公司的重力感應芯片,這是一款超緊湊,低功耗的三維線性加速度傳感器。芯片采用LGA封裝,16引腳,3×3×1 mm3大小,要求的額定輸入電壓范圍為2.16~3.6 V,電路中的供電電壓為2.775 V。LIS33DE的功耗小于1 mW,控制接口支持I2C和SPI接口。設(shè)計中采用I2C接口進行數(shù)據(jù)通信。LIS33DE內(nèi)置可編程中斷發(fā)生器,軟件可采用中斷或查詢方式讀取重力感應的狀態(tài)信息。
LIS33DE的主要寄存器包括控制寄存器CTRL_REG1~CTRL_REG3,狀態(tài)寄存器 STATUS_REG,數(shù)據(jù)寄存器OUT_X、OUT_Y和 OUT_Z。它們用來控制G-sensor的行為,存放加速度的值。系統(tǒng)通過I2C接口訪問這些寄存器。
控制寄存器CTRL_REG1(20h):DR位(bit7)控制輸出數(shù)據(jù)的速率,可以選擇100 Hz或400 Hz;PD位(bit6)控制芯片的工作狀態(tài):power down或active;Zen、Yen和Xen位(bit2~0),控制Z、Y和X軸的使能:1為enable,0為disable。
控制寄存器CTRL_REG2(21h):BOOT位(bit6)控制為復位寄存器內(nèi)容,0為正常模式,1為復位寄存器內(nèi)容。BOOT位用來恢復LIS33DE寄存器的默認值。
控制寄存器CTRL_REG3(22h):IHL位(bit7)控制中斷有效電平,0為高電平有效,1為低電平有效。
狀態(tài)寄存器STATUS_REG(27h):高4位表示X、Y、Z軸的數(shù)據(jù)是否有溢出,低4位表示X、Y、Z軸的數(shù)據(jù)是否有效。
數(shù)據(jù)寄存器OUT_X(29h):以二進制補碼格式存儲X軸數(shù)據(jù)。
數(shù)據(jù)寄存器OUT_Y(2Bh):以二進制補碼格式存儲Y軸數(shù)據(jù)。
數(shù)據(jù)寄存器OUT_Z(2Dh):以二進制補碼格式存儲Z軸數(shù)據(jù)。
當物體位置發(fā)生變化時,LIS33DE實時檢測、判斷出各個方向軸上重力加速度的變化,并將其值存入數(shù)據(jù)寄存器OUT_X、OUT_Y和OUT_Z。驅(qū)動程序裝載運行后,以查詢方式定時調(diào)用工作隊列中的任務(wù)處理函數(shù):讀數(shù)據(jù)寄存器,向系統(tǒng)報告事件及變化的坐標值。MX51通過I2C2接口與LIS33DE芯片進行數(shù)據(jù)通信,使用一個總線設(shè)備,除了為其設(shè)計驅(qū)動程序,還須向Linux內(nèi)核注冊此設(shè)備。
在 arch/arm/mach-mx51/mx51_3stack.c中,定義struct i2c_board_info結(jié)構(gòu)變量,用于描述I2C設(shè)備特性:

其中type為定義的I2C設(shè)備名稱,addr為I2C設(shè)備地址。然后,調(diào)用如下函數(shù)注冊此設(shè)備:
i2c_register_board_info(1,mxc_i2c1_board_info,ARRAY_SIZE(mxc_i2c1_board_info));
系統(tǒng)初始化時,會根據(jù)板級I2C設(shè)備配置信息,創(chuàng)建I2C客戶端設(shè)備i2c_client,并將其添加到I2C子系統(tǒng)中。
I2C總線上的數(shù)據(jù)通信由I2C設(shè)備驅(qū)動實施,設(shè)備驅(qū)動通過I2C總線與具體設(shè)備進行交互。一個設(shè)備驅(qū)動需由2個結(jié)構(gòu)struct i2c_driver和struct i2c_client來描述。其中i2c_driver表示一個I2C設(shè)備驅(qū)動,i2c_client表示使用i2c_driver驅(qū)動的設(shè)備。
在drivers/i2c/chips/lis33de.c中作如下定義:

lis33de_driver表示管理I2C設(shè)備的驅(qū)動程序。在驅(qū)動入口函數(shù) lis33de_init中調(diào)用函數(shù)i2c_add_driver(&lis33de_driver)注冊這個設(shè)備驅(qū)動。驅(qū)動成功加載后,系統(tǒng)會自動調(diào)用探測函數(shù)lis33de_probe,該函數(shù)原型如下:
static int lis33de_probe(struct i2c_client*client,const struct i2c_device_id*id);
其中參數(shù)i2c_client*client表示此前已向系統(tǒng)注冊過的I2C設(shè)備,即lis33de芯片。
Linux內(nèi)核提供了輸入子系統(tǒng)(Input Subsystem),常用輸入設(shè)備如鍵盤、鼠標、觸摸屏等都可以利用輸入子系統(tǒng)的接口函數(shù)來實現(xiàn)設(shè)備驅(qū)動,重力感應驅(qū)動亦可納入輸入子系統(tǒng)框架。輸入子系統(tǒng)由核心層、驅(qū)動層和事件處理層三部分組成,它們之間通過事件進行通信。我們將重力感應芯片LIS33DE作為一個輸入設(shè)備,利用輸入子系統(tǒng)實現(xiàn)重力感應驅(qū)動,需做以下工作:
◆在驅(qū)動模塊加載函數(shù)中申請一個輸入設(shè)備。
◆設(shè)置輸入子系統(tǒng)所支持的事件類型。
◆設(shè)置坐標的取值范圍。
◆注冊輸入設(shè)備。
◆報告發(fā)生的事件及對應的坐標。
通過輸入子系統(tǒng)實現(xiàn)重力感應驅(qū)動,需要在drivers/i2c/chips/lis33de.c中定義設(shè)備結(jié)構(gòu),對 lis33de進行描述:

結(jié)構(gòu)input_dev定義在<Linux/input.h>中,用于描述輸入設(shè)備的驅(qū)動結(jié)構(gòu),主要包括響應的事件類型、按鍵內(nèi)容、數(shù)據(jù)相對值的范圍及一些處理函數(shù)。設(shè)備驅(qū)動的主要任務(wù)在以下函數(shù)中完成。
3.4.1探測函數(shù)lis33de_probe
在入口函數(shù)lis33de_init中成功加載設(shè)備驅(qū)動后,探測函數(shù)lis33de_probe開始執(zhí)行。函數(shù)主要實現(xiàn)以下操作:
①定義結(jié)構(gòu)指針“struct lis33de_data*sensor_data;”和“struct input_dev*input;” ,申請設(shè)備所需空間 。

②設(shè)置事件類型。

④注冊輸入設(shè)備。

⑤創(chuàng)建工作隊列,構(gòu)建任務(wù)并提交到工作隊列。

其中g(shù)lb_sensor為已定義的全局struct lis33de_data類型的指針,glb_sensor-﹥gsensor_work為任務(wù)名稱,sensor_workqueue_func為函數(shù)名,表示執(zhí)行該任務(wù)時從工作隊列中調(diào)用的函數(shù)。用queue_delayed_work函數(shù)提交任務(wù)到工作隊列,LONG_DELAY_TIME為指定的delay,定義為HZ*12,在lis33de_probe函數(shù)調(diào)用12 s后,自動執(zhí)行任務(wù)處理函數(shù)sensor_workqueue_func。
⑥電源管理。在嵌入式手持設(shè)備里,電源管理的實現(xiàn)和節(jié)電非常重要,重力感應驅(qū)動需要很好的電源管理。由于LIS33DE屬于輸入設(shè)備,我們需要實現(xiàn)early suspend和late resume。對已定義的全局變量“struct early_suspend gsensor_early_suspend;”進行初始化:

lis33de_early_suspend()和 lis33de_late_resume()函數(shù)是相應電源管理系統(tǒng)休眠時和喚醒后分別調(diào)用的函數(shù)。在lis33de_early_suspend()函數(shù)中,首先使LIS33DE進入Power Down狀態(tài),然后取消對應的工作隊列。

在lis33de_late_resume()函數(shù)中,首先寫LIS33DE的寄存器0x20,使其進入active模式,然后把工作隊列加入工作隊列。

3.4.2數(shù)據(jù)處理函數(shù)sensor_workqueue_func
lis33de_probe函數(shù)執(zhí)行12 s后,隊列中的任務(wù)處理函數(shù)sensor_workqueue_fun被首次調(diào)用。函數(shù)的主要任務(wù)是讀取G-sensor數(shù)據(jù)寄存器中的重力感應數(shù)據(jù),經(jīng)處理后向上層發(fā)送:

讀取的值在變量DX8、DY8、DZ8中,用以下代碼對坐標值進行處理。

通過input_report_abs()向上層發(fā)送。

為了持續(xù)不斷地查詢下去,在sensor_workqueue_func()函數(shù)的最后,再次提交任務(wù)到工作隊列:
queue_delayed_work(glb_sensor-﹥gsensor_wq,&glb_sensor-﹥gsensor_work,DELAY_TIME);其中 DELAY_TIME定義為40 ms。以后,系統(tǒng)以固定的時間間隔(40 ms)反復調(diào)用任務(wù)處理函數(shù),只要系統(tǒng)運行,就存在重力感應的輸入數(shù)據(jù)報告。
3.4.3 設(shè)備初始化函數(shù)lis_init
函數(shù)主要實現(xiàn)對LIS33DE寄存器初始化。

在android 2.2系統(tǒng)下進行重力感應驅(qū)動測試。打開gallery圖片瀏覽程序,旋轉(zhuǎn)平板電腦,可以發(fā)現(xiàn),圖片也隨之旋轉(zhuǎn),能夠始終保持正確的瀏覽姿態(tài)。
MX51處理器通過I2C接口與LIS33DE重力感應芯片連接,以Linux輸入設(shè)備驅(qū)動形式開發(fā)該驅(qū)動,設(shè)計中使用了查詢、隊列等技術(shù)。本文對重力感應驅(qū)動程序的架構(gòu)及主要實現(xiàn)技術(shù)進行了討論,該驅(qū)動有著較為清晰的結(jié)構(gòu),針對具體硬件,修改底層初始化和坐標讀取代碼,可以方便地移植到多種嵌入式Linux系統(tǒng)平臺。
[1]Linux設(shè)備驅(qū)動程序[M].魏永明,譯.3版.北京:中國電力出版社,2006.
[2]Linux內(nèi)核編程指南[M].張瑜,等譯.3版.北京:清華大學出版社,2004.
[3]劉淼.嵌入式系統(tǒng)接口設(shè)計與Linux驅(qū)動程序開發(fā)[M].北京:北京航空航天大學出版社,2006.
[4]潘巨龍,黃寧,姚伏天,等.ARM9嵌入式Linux系統(tǒng)構(gòu)建與應用[M].北京:北京航空航天大學出版社,2006.
[5]馮國進.嵌入式 Linux驅(qū)動程序設(shè)計[M].北京:清華大學出版社,2008.