![I2C驅(qū)動(dòng)開發(fā)實(shí)例_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/5/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c1.gif)
![I2C驅(qū)動(dòng)開發(fā)實(shí)例_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/5/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c2.gif)
![I2C驅(qū)動(dòng)開發(fā)實(shí)例_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/5/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c3.gif)
![I2C驅(qū)動(dòng)開發(fā)實(shí)例_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/5/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c4.gif)
![I2C驅(qū)動(dòng)開發(fā)實(shí)例_第5頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/5/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c/e5dd89f5-3abb-4d95-ab62-a3ec037eb07c5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、I2C 驅(qū)動(dòng)開發(fā) 文檔一、開發(fā)背景開發(fā)環(huán)境:DM355開發(fā)板內(nèi)核版本: 2.6.10二、BQ27501 驅(qū)動(dòng)開發(fā)的需求BQ27501是一個(gè)鋰電池管理的芯片,可以向外提供鋰電池的有關(guān)的信息。在用戶空間用戶不能直接訪問 bq27501 的寄存器,所以要為其編寫驅(qū)動(dòng),該驅(qū)動(dòng)能夠根據(jù)用戶空間的命令,返回對(duì)應(yīng)的電池信息。三、I2C 驅(qū)動(dòng)的架構(gòu)bq27501是通過I2C總線與DM355通信的,故bq27501的驅(qū)動(dòng)實(shí)際上就是 bq27501的I2C讀寫的驅(qū)動(dòng)Linux 內(nèi)核中的 i2c 驅(qū)動(dòng)程序可以分為三個(gè)層次,如下圖所示:圖1 Linux I2C 體系結(jié)構(gòu)1) i2c 驅(qū)動(dòng)框架i2c框架主要有i2c.h
2、和i2c-core.c 文件實(shí)現(xiàn)。它們定義驅(qū)動(dòng)中使用的核心數(shù)據(jù)結(jié)構(gòu),完成i2c適配器和設(shè)備驅(qū)動(dòng)的注冊(cè),注銷,并且實(shí)現(xiàn) i2c驅(qū)動(dòng)的algorithm 。 i2c驅(qū)動(dòng)中的algorithm 與適配器無關(guān),它 屬于上層代碼,還包括探測(cè)設(shè)備、檢測(cè)設(shè)備地址的上層代碼。另外,i2c-dev.c 還用于對(duì)i2c設(shè)備節(jié)點(diǎn)的創(chuàng)建,并完成其訪問方法的實(shí)現(xiàn)等。2) i2c 總線驅(qū)動(dòng)總線驅(qū)動(dòng)的職責(zé),是為系統(tǒng)中每個(gè)I2C總線增加相應(yīng)的讀寫方法。但是總線驅(qū)動(dòng)本身并不會(huì)進(jìn)行任何的通訊,它只是存在那里,等待設(shè)備驅(qū)動(dòng)調(diào)用其函數(shù)。在系統(tǒng)開機(jī)時(shí),首先裝載的是I2C總線驅(qū)動(dòng)。一個(gè)總線驅(qū)動(dòng)用于支持一條特定的I2C總線的讀寫。這部分
3、主要定義i2c_adapter和i2c_algorithm數(shù)據(jù)結(jié)構(gòu),前者用來描述具體的i2c總線適配器,后者則描述i2c總線的通信方法。一般總線驅(qū)動(dòng)由平臺(tái)提供實(shí)現(xiàn), davinci的i2c總線驅(qū)動(dòng)在i2c-davinci.c文件中定義了,然后通過i2c_davinci_init函數(shù)調(diào)用i2c_add_adapter(i2c_davinci_adap)將這個(gè)兩個(gè)模塊注冊(cè)到操作系統(tǒng)中,總線驅(qū)動(dòng)就裝上了。cpp view plaincopy1. static struct i2c_adapter i2c_davinci_adap = 2. .owner = THIS_MODULE,3. .name
4、= "DAVINCI I2C adapter",4. .id = I2C_ALGO_EXP,5. .algo = &i2c_davinci_algo,6. .algo_data = NULL,7. .client_register = NULL,8. .client_unregister = NULL,9. ;10. static struct i2c_algorithm i2c_davinci_algo = 11. .name = "DAVINCI I2Calgorithm",12. .id = I2C_ALGO_EXP,13. .master
5、_xfer = i2c_davinci_xfer,14. .smbus_xfer = NULL,15. .slave_send = NULL,16. .slave_recv = NULL,17. .algo_control = NULL,18. .functionality = i2c_davinci_func,19. ;3) i2c設(shè)備驅(qū)動(dòng)設(shè)備驅(qū)動(dòng)則是與掛在I2C總線上的具體的設(shè)備通訊的驅(qū)動(dòng)。通過I2C總線驅(qū)動(dòng)提供的函數(shù),設(shè)備驅(qū)動(dòng)可以忽略不同總線控制器的差異,不考慮其實(shí)現(xiàn)細(xì)節(jié)地與硬件設(shè)備通訊。它實(shí)現(xiàn)對(duì)具體的i2c設(shè)備的描述,另 外還包括一些可能用到的數(shù)據(jù)結(jié)構(gòu)。它借助i2c框架中的i2c_pr
6、obe 函數(shù)實(shí)現(xiàn)設(shè)備的attach_adapter 方法,完成設(shè)備檢測(cè)成功后i2c_client數(shù)據(jù)結(jié)構(gòu)回調(diào)函數(shù)的創(chuàng)建。實(shí)際操作過程中可以跳過i2c_probe函數(shù)直接調(diào)用實(shí)現(xiàn)i2c_client的函數(shù),這樣可以不必遵循調(diào)用i2c_probe固有的參數(shù)格式,從而可以提高效率和節(jié)省存儲(chǔ)空間。bq27501的驅(qū)動(dòng)加載流程如下圖2所示。圖2 bq27501的i2c驅(qū)動(dòng)加載流程圖bq27501_init()函數(shù)為該驅(qū)動(dòng)模塊的模塊初始化函數(shù),當(dāng)在linux下使用insmod命令裝載該模塊時(shí)會(huì)執(zhí)行該函數(shù)。在初始化函數(shù)中,對(duì)i2c_driver結(jié)構(gòu)體變量初始化,然后調(diào)用register_chrdev()函數(shù)
7、注冊(cè)字符設(shè)備。接著調(diào)用i2c_add_driver()函數(shù)添加一個(gè)i2c的driver。i2c_add_driver函數(shù)的執(zhí)行會(huì)引發(fā)i2c_driver 中attach_adapter 指向的函數(shù)bq27501_i2c_probe_adapter()函數(shù)的執(zhí)行,該函數(shù)是用來探測(cè)物理設(shè)備的。它需要通過調(diào)用_i2c_attach_client函數(shù)來實(shí)現(xiàn)探測(cè),并且在 _i2c_attach_client 函數(shù)內(nèi)調(diào)用i2c_attach_client函數(shù)在總線上附加一個(gè)新的client ;或者 調(diào)用i2c-core.c 中的i2c_probe 函數(shù),由i2c_probe函數(shù)再調(diào)用探測(cè)物理設(shè)備的函數(shù),b
8、q27501驅(qū)動(dòng)中是采用的第一種方式。四、實(shí)現(xiàn)I2C驅(qū)動(dòng)編寫方式 最新的內(nèi)核支持兩種編寫i2c驅(qū)動(dòng)的方式,一個(gè)是“ Adapter方式(legacy )” ,另一個(gè)是“ Probe方式(newstyle )"。兩種方式的區(qū)別在于i2c_driver 結(jié)構(gòu)體不同,“ Adapter方式”的i2c_driver 結(jié)構(gòu)是:cpp view plaincopy1. struct i2c_driver 2. structmodule *owner;3. charname32;4. intid;5. unsignedint class;6. unsignedint flags;7. int(*a
9、ttach_adapter)(struct i2c_adapter*);8. int(*detach_adapter)(struct i2c_adapter*);9. int(*detach_client)(struct i2c_client*);10. int(*command)(struct i2c_client*client,unsigned int cmd, void *arg);11. structdevice_driver driver;12. structlist_head list;13. ;“Probe方式”的i2c_driver 結(jié)構(gòu)是:cpp view plaincopy
10、1. struct i2c_driver 2. unsignedint class;3. int(*attach_adapter)(struct i2c_adapter*);4. int(*detach_adapter)(struct i2c_adapter*);5. int (*probe)(struct i2c_client *, const struct i2c_device_id*);6. int (*remove)(struct i2c_client *);7. void(*shutdown)(struct i2c_client *);8. int(*suspend)(struct
11、i2c_client *,pm_message_t mesg);9. int(*resume)(struct i2c_client *);10. int(*command)(struct i2c_client*client, unsignedint cmd, void *arg);11. structdevice_driver driver;12. const struct i2c_device_id *id_table;13. int(*detect)(struct i2c_client *,int kind, struct i2c_board_info*);14. conststruct
12、i2c_client_address_data*address_data;15. structlist_head clients;16. ;兩種方式i2c_driver結(jié)構(gòu)主要的不同是后者添加了probe和remove函數(shù)指針和id_table 。 bq27501使用的Ti- davinci內(nèi)核是較早版本的,只支持Adapter方式,不支持Probe方式,所以bq27501采用的是Adapter 方式。Adapter方式編寫的流程就是上節(jié)中所描述的i2c驅(qū)動(dòng)加載的流程相同。至于Probe方式,在本次驅(qū)動(dòng)編寫中沒有使用,所以在此不作詳細(xì)的介紹。兩種方式的對(duì)比可以參加網(wǎng)頁資料http:/www.e
13、/Column/Column213.htm 。五、BQ27501的 I2C 驅(qū)動(dòng)編寫要使 bq27501 的 i2c 驅(qū)動(dòng)模塊能夠運(yùn)行,必須至少要編寫兩個(gè)文件,第一個(gè)是驅(qū)動(dòng)的源文件,第二個(gè)是編 譯源文件的 Makefile 文件。另外該驅(qū)動(dòng)的兩個(gè)關(guān)鍵點(diǎn)是 i2c 通信和與用戶空間交互數(shù)據(jù)。1) Makefile 文件編寫#如果已定義KERNELRELEASBW說明是從內(nèi)核構(gòu)造系統(tǒng)調(diào)用的,因此可以利用其內(nèi)建語句。ifneq($(KERNELRELEASE),)obj-m := bq27501.o#否則,是直接從命令開始調(diào)用的,這時(shí)要調(diào)用內(nèi)核構(gòu)造系統(tǒng)。elseKDIR ?=/ho
14、me/zl/ti-davinciPWD := $(shellpwd)CROSS_COMPILE=arm-v5t-le-CC=$(CROSS_COMPILE)gccdefault:make -C $(KDIR) M=$(PWD) modulesendifclean:rm -rf *.o *.cmd *.mod.c *.sysmvers注:1. Makefile 文件的文件名中M定要大寫。這是因?yàn)榫幾g的時(shí)候首先看環(huán)境變量KERNELRELEASE否定義,如果沒定義則調(diào)用 Linux 內(nèi)核編 譯 build 腳本。該腳本會(huì)首先編譯內(nèi)核,其間會(huì)創(chuàng)建環(huán)境變量 KERNELRELEASE著編譯當(dāng)前工作目錄
15、下的hello模塊,此時(shí)會(huì)第二遍讀取Makefile,再次判斷環(huán)境變量KERNELRELEAS是否定義,已經(jīng)定義的情況下開始編譯hello模塊。2. Makefile 文件中的命令行,以 Tab 鍵開頭(不能是空格),例如make, clean 。依賴條件頂格,例如default , clean 。3. KDIR :指向嵌入系統(tǒng)的 linux 內(nèi)核,而不是正在運(yùn)行的系統(tǒng)的內(nèi)核。4. CR0SS_C0MPILE交叉編譯環(huán)境,也就是安裝的dvdsdk。5. CC :指明編譯器,加上 CROSS_COMPI|_Et義了一個(gè)交叉編譯器。6. clean :當(dāng)時(shí)使用 makeclean 命令時(shí)清除編譯的
16、結(jié)果。7. default :當(dāng)使用make命令后面不加任何參數(shù)時(shí),默認(rèn)執(zhí)行的語句。將驅(qū)動(dòng)代碼的源文件和 Makefile文件放到同一個(gè)文件夾下面。在終端進(jìn)入到目錄下,使用make命令對(duì)其進(jìn)行編譯。2) 模塊編程為了 bq27501 驅(qū)動(dòng)測(cè)試的方便,所以采用模塊編程的方式來實(shí)現(xiàn)。將 bq27501 驅(qū)動(dòng)作為一個(gè)內(nèi)核模 塊動(dòng)態(tài)加載到內(nèi)核中,而不是采用在內(nèi)核樹中添加代碼實(shí)現(xiàn)這種靜態(tài)的方法實(shí)現(xiàn)的。第一,模塊編程的程序的頭文件。#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h&
17、gt;這三個(gè)頭文件是編寫內(nèi)核模塊程序必須包含的 3 個(gè)頭文件。第二,內(nèi)核模塊必須包含兩個(gè)函數(shù)。一個(gè)是加載時(shí)模塊初始化函數(shù),另一個(gè)是模塊卸載時(shí)卸載的函數(shù)。 bq27501 的初始化函數(shù)為 staticint_initbq27501_init(void);module_init(bq27501_init); 初始化函數(shù)聲明為 static ,因?yàn)槌跏蓟瘮?shù)在特定文件文件之外沒有其他意義,并且驅(qū)動(dòng)初始化函數(shù)前面加 上_init 標(biāo)記,這表明該函數(shù)僅在初始化期 間使用。在模塊被裝載之后,模塊裝載器就會(huì)將初始化函數(shù) 扔掉,這樣可以將該函數(shù)占用的內(nèi)存釋放出來以作他用 (注,不能在初始化之后仍要使用的函數(shù),
18、 或者數(shù) 據(jù) 結(jié)構(gòu))。 module_init 這個(gè)宏會(huì)在模塊的目標(biāo)代碼中增加一個(gè)特殊的段,用于說明內(nèi)核初始化函數(shù)所在的 位置。如果沒有這個(gè)定義,那么初始化函數(shù) bq27501 將不會(huì)被調(diào)用。所以是必須使用的 module_init 。bq27501 的卸載函數(shù)為 staticvoid_exit bq27501_exit(void) ;module_exit(bq27501_exit) ;該函數(shù)在模塊被卸載前注銷接口并向系統(tǒng)中返回所有資源。卸 載函數(shù)沒有返回值,故要聲明為 void 。 _exit 標(biāo)記 表示該代碼用于模塊卸載。如果模塊被直接內(nèi)核的配置不允許卸載模塊,則被標(biāo)記為_exit 的函
19、 數(shù)將被簡單地丟棄。所以被標(biāo)記為 _exit 的函數(shù)只能在模塊被卸載或者系統(tǒng)關(guān)閉時(shí)被調(diào)用,其他任何用法都是錯(cuò) 誤的。和 module_init 類 似, module_exit 用于內(nèi)核可以找到模塊的卸載函數(shù)。如果模塊沒有定義卸載函 數(shù),那么內(nèi)核不允許卸載該模塊。第三,模塊的聲明與描述。M0DULE_LICENSE("GPLv2")描述內(nèi)核模塊的許可權(quán)限,如果不聲明LICENSE模塊被加載時(shí),將收到 內(nèi)核的警告。 在Linux2.6內(nèi)核中,可接受的 口CENSE包括“ GPL(任一版本的 GNU通用公共許可證),“ GPL v2'( GPL版本 2),“ GPLan
20、d additional rights ”( MPL/GPL 雙重許可證),“DualBSD/GPL (雙重許可證),“DuaIMPL/GPL,“Proprietary ”。MODULE_AUTHOR("zl");聲明該模塊的作者。MODULE_DESCRIPTION("BQ27501Driver")對(duì)該模塊功能簡單的描述。以上是內(nèi)核模塊編程的三個(gè)特點(diǎn)。其他函數(shù)的編寫和調(diào)用和普通的GNU C一樣。3)bq27501 的 i2c 通信bq27501驅(qū)動(dòng)的核心和關(guān)鍵就是完成 i2c的通信,對(duì)于不同的設(shè)備i2c通信的消息格式可能不同,需要查閱對(duì)應(yīng)的數(shù)據(jù)手冊(cè)。從
21、 bq27501的數(shù)據(jù)手冊(cè)中獲得與其通信的message的格式,如下圖(3)所示:QJ Host generated| bq2700/1 generate a(a 1-byte wrtteS ADDR0廠昵CMD7:0(c) 1- b/te readib quick fG£DATA7;0)S| ADDRG:C S j|ACIM07 力|Sr| ADDR6:0) IHAI"TA化OJ|A|S| ADDR6:0 5a CMD 7:0a DATA 7:0aP|ADDR6:0 |f| A(d) incrementEl readieO incremental write(S = St
22、art Sr = Fepeatec Start, A = Ackrwwleoge. N = No Acknowledge-. and P = Stop5圖(3)bq27501的i2c通信消息格式選擇1-byte read消息格式,ADDR+CM為一條寫消息,ADDR+DAT為一條讀消息。CMD為要讀信息的command code,DATA是返回的數(shù)據(jù)。例如電壓voltage 的commandcode為0x08/0x09兩個(gè)字節(jié),返回值為一個(gè)unsignedint型的值,即也為兩個(gè)字節(jié),所以要讀取電壓值,要執(zhí)行兩次1-byte read 。構(gòu)造的i2c_msg格式如下面的代碼片段所示。cpp v
23、iew plaincopy1. /the first "write" message:ADDR+CMD12. msg.addr= client->addr;3. msg.flags= 0; / the "write" flag4. msg.len= I2C_ONE_BYTE_TRANSFER;5. msg.buf= &cmd_data;6. cmd_data= reg;7. err= i2c_transfer(client->adapter,&msg, 1);9./thefirst "read" messa
24、ge: ADDR+DATA110.msg.addr=client->addr;11.msg.flags=I2C_M_RD; /the"read" flag12.msg.len=I2C_ONE_BYTE_TRANSFER;13.msg.buf= &data1;14.err=i2c_transfer(client->adapter, &msg, 1);15.if(err>=0)16./thesecond "write" message: ADDR+CMD217.msg.addr= client->addr;18.msg
25、.flags= 0;19.msg.len= I2C_ONE_BYTE_TRANSFER;20.msg.buf= &cmd_data;21.cmd_data= reg+1;22.err= i2c_transfer(client->adapter,&msg, 1);23.if(err>=0)24./thesecond "read" message: ADDR+DATA225.msg.addr=client->addr;26.msg.flags=I2C_M_RD;27.msg.len=I2C_ONE_BYTE_TRANSFER;28.msg.bu
26、f= &data2;29.err=i2c_transfer(client->adapter, &msg, 1);30.if(err>=0)31.*val= (data2& I2C_TXRX_DATA_MASK)32.<<I2C_TXRX_DATA_SHIFT)33.|(data1 & I2C_TXRX_DATA_MASK);7.38.8.if(err>=0)4) 驅(qū)動(dòng)與用戶空間的數(shù)據(jù)交互內(nèi)核中的數(shù)據(jù)與用戶空間數(shù)據(jù)交互常用的函數(shù)有 copy_to_user , copy_from_user ,和宏定義 put_us
27、er ,get_user ,_put_user ,_get_user 。 copy_from_user 和 copy_to_user 函數(shù)復(fù)制塊 數(shù)據(jù),如 數(shù)組,結(jié)構(gòu)體; put_user , get_user ,_put_user ,_get_user 復(fù)制的內(nèi)存是簡單類型,如 char , int , long ,而且只能復(fù)制 1,2,4,8 個(gè)字節(jié)。 put_user , get_user ,_put_user ,_get_user 執(zhí)行 效率比 copy_to_user ,copy_from_user 的效率要高很多。 put_user 和 _put_user 區(qū)別在于, 前者會(huì)調(diào)用
28、access_ok 進(jìn)行內(nèi)核地址的檢查,而后者不進(jìn)行地址檢查。bq27501 驅(qū)動(dòng)的功能是向用戶空間提供電池相關(guān)的信息;而且不需要用戶空間向電池輸入 數(shù)據(jù);另外電池的信息都是很小的數(shù)據(jù),都可以使用 unsigned short 表 示,所以沒有必要使用 copy_to_user 塊數(shù)據(jù)傳遞的函數(shù);另外再根據(jù) Linux 驅(qū)動(dòng)程序書中“大多數(shù)驅(qū)動(dòng)程序代碼中都不需要 access_ok,內(nèi)存管理程序會(huì)處理它",所以選擇_put_user來向用戶空間傳遞電池信息數(shù)據(jù)。put_user(var, ptr) ,var將內(nèi)核中的數(shù)據(jù)var復(fù)制到用戶空間;ptr是用戶地址空間的指針,指向內(nèi)核 空間
29、中ioctl最后一個(gè)參數(shù)。bq27501與用戶空間交互的代碼片段如下:cpp view plaincopy1. static long bq27501_ioctl(struct file*file, unsigned int cmd, unsigned long arg)2. 3. BATT_INFO*pBattlnfo = & BattInfo;4. unsignedshort temp;5. switch(cmd)6. 7. caseGET_RM:8. if(i2c_read_reg(&bq27501_i2c_client,RM_REG_ADDR_L,&pBattl
30、nfo->RemainingCapacity)> =0)9. printk(KERN_ALERT"RaminingCapacityis %u mAh .n",pBattlnfo->RemainingCapacity);10. _put_user(pBattlnfo->RemainingCapacity,(int _user *)arg);11. 12. break;13. 14. 在用戶空間,ioctl系統(tǒng)調(diào)用的原型為:intioctl(int fd, unsigned long cmd, .);這個(gè)原型中的點(diǎn)表示函數(shù)有一個(gè)單個(gè)可選的參數(shù),傳統(tǒng)上標(biāo)識(shí)
31、為char *argp.這些點(diǎn)在那里只是為了阻止在編譯時(shí)的類型檢查。第二個(gè)參數(shù),是用戶向驅(qū)動(dòng)傳遞的命令(如讀取剩余電量值)。第三個(gè)參數(shù)的實(shí)際特點(diǎn)依賴所發(fā)岀 的特定的控制命令,即第二個(gè)參數(shù)。一些命令不用參數(shù),一些用一個(gè)整數(shù)值,以及一些使用指向其他數(shù)據(jù) 的指針。是否使用參數(shù)和指針是根據(jù)打開字符設(shè)備的方式?jīng)Q定,打開設(shè)備的方式有三種,在fcntl.h 有其宏定義,只讀,只寫,讀 寫,如下所示:cpp view plaincopy1. #define O_RDONLY002. #define O_WRONLY013. #define O_RDWR 024. 用戶空間讀取驅(qū)動(dòng)中參數(shù)代碼片段如下:5. if
32、(fd = open('7dev/bq27501",2) = -1)6. perror("device open err!n");7. return -1;8. 9. printf("open ok!n");10. ioctl(fd,atoi(argv1),&v); v是一個(gè)整型,用于保存內(nèi)核空間傳遞過來的數(shù)據(jù)11. printf("(2)cmd = %d,val = %dn",atoi(argv1),v);六、 bq27501 驅(qū)動(dòng)的測(cè)試1. 測(cè)試目的:驗(yàn)證 bq27501 驅(qū)動(dòng)能否讀取寄存器的值,和用戶空
33、間的交互。2. 測(cè)試過程和結(jié)果:bq27501 驅(qū)動(dòng)的測(cè)試是要在用戶空間編寫測(cè)試程序。 Linux 將所有設(shè)備都作為文件來處理的, 所以 在用戶空間必須打開 bq27501 設(shè)備文件。 fd =open("/dev/bq27501",2) ;這里使用 open 打開在 dev 下創(chuàng)建 的bq27501的字符設(shè)備,“ 2”表示以讀寫的方式打開(也可以用O_RDW這個(gè)宏來表示),fd用來保存文件句柄。通過 ioctl 向設(shè)備文件發(fā)送命令,并接收返回的電池統(tǒng)計(jì)信息值, ioctl(fd,atoi(argv1),&v);fd是打開的設(shè)備文件的句柄, atoi(argv1)
34、是將 main 的參數(shù)轉(zhuǎn)換成整型作為參數(shù)傳給驅(qū)動(dòng), v 用來保存驅(qū)動(dòng)返回的數(shù)值。測(cè)試程序編寫完成之后,因?yàn)橐贒M355平臺(tái)上運(yùn)行,所以必須要交叉編譯源文件testbq.c。使用交叉編譯環(huán)境 dvsdk下的命令 arm_v5t_le-gcc testbq.c testbq,生成可執(zhí)行的testbq文件。使用make命令編譯驅(qū)動(dòng)的源文件bq27501.c,生成bq27501.ko文件。在 DM355中使用tftp 命令“tftp- g-r bq27501.ko 38 ”下載 bq27501.ko 到開發(fā)板上(38 為 tftp 服務(wù)器的地址)。使用 i
35、nsmod 命令加載驅(qū)動(dòng) 模塊,即“ insmod bq27501.ko” 。加載成功會(huì)打印添加的信息如 下:registersucceed!.bq27501_driver->id225 I2C:detect address is 55 .Adaptername is DAVINCI I2Cadapter.Adddriver succeed!.使用 mknod命令為bq27501創(chuàng)建一個(gè)設(shè)備節(jié)點(diǎn),即命令“ mknod /dev/bq27501 c 225 0 "。節(jié)點(diǎn)的名稱為 bq27501,是在/dev目錄下創(chuàng)建的;c表示該節(jié)點(diǎn)是一個(gè)字符設(shè)備; 225表示主設(shè)備號(hào),這個(gè)必須和
36、驅(qū)動(dòng)中 注冊(cè)時(shí)的一樣; 0 表示 從設(shè)備號(hào)。在DM355中使用tftp 命令“tftp - g -r testbq 38 ”下載 testbq 到開發(fā)板上。使用命令“chmod 777 testbq ”修改執(zhí)行的權(quán)限。使用命令“ ./testbq 3 ”執(zhí)行 testbq文件,“ 3”是傳給 main函 數(shù)的參數(shù),表示獲得電池的電壓值。運(yùn)行結(jié)果為“Voltage is 3779 mV .”,即卩3.78v,和電池的額定輸出電壓3.7 一樣。另外還測(cè)試了溫度“ Temperature is 2974 k.”,即 24.25攝氏度;剩余電量可用的時(shí)間“ Time to Empty is 65535 min. ”,即卩65535分鐘,表示電池沒有處于放電狀態(tài),符合實(shí)際情況。根據(jù)測(cè)試的結(jié)果,可以說明bq27501驅(qū)動(dòng)和用戶測(cè)試程序的基本功能點(diǎn)已經(jīng)正確實(shí)現(xiàn)。七、總結(jié)1. 不能省略用戶空間測(cè)試文件的編寫,在初始化函數(shù)中調(diào)用i2c_read_reg函數(shù)測(cè)試驅(qū)動(dòng)i2c通信是否成功。模塊
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 初中數(shù)學(xué)人教版九年級(jí)下冊(cè)同步聽評(píng)課記錄第27章章末復(fù)習(xí)
- 瑜伽私教服務(wù)合同(2篇)
- 甲醛超標(biāo)租賃合同(2篇)
- 湘教版九年級(jí)上冊(cè)聽評(píng)課記錄:4.2 正切
- 湘教版地理七年級(jí)下冊(cè)《第一節(jié) 日本》聽課評(píng)課記錄2
- 四年級(jí)英語聽評(píng)課記錄表
- 五年級(jí)蘇教版數(shù)學(xué)上冊(cè)《認(rèn)識(shí)負(fù)數(shù)》聽評(píng)課記錄(校內(nèi)大組)
- 蘇科版數(shù)學(xué)七年級(jí)上冊(cè)3.2 代數(shù)式教聽評(píng)課記錄
- 湘師大版道德與法治九年級(jí)上冊(cè)4.1《多彩的人類文化》聽課評(píng)課記錄
- 小學(xué)數(shù)學(xué)-六年級(jí)下冊(cè)-3-2-2 圓錐的體積 聽評(píng)課記錄
- 四川省自貢市2024-2025學(xué)年上學(xué)期八年級(jí)英語期末試題(含答案無聽力音頻及原文)
- 2025-2030年中國汽車防滑鏈行業(yè)競(jìng)爭格局展望及投資策略分析報(bào)告新版
- 2025年上海用人單位勞動(dòng)合同(4篇)
- 二年級(jí)上冊(cè)口算題3000道-打印版讓孩子口算無憂
- 2025年生物安全年度工作計(jì)劃
- 人教版數(shù)學(xué)六年級(jí)下冊(cè)全冊(cè)核心素養(yǎng)目標(biāo)教學(xué)設(shè)計(jì)
- 通用電子嘉賓禮薄
- 新概念英語第三冊(cè)課后習(xí)題答案詳解
- 有機(jī)化學(xué)共振論
- 家訪手記(5篇)
- 橋梁工程質(zhì)量保證措施
評(píng)論
0/150
提交評(píng)論