RT-Thread驅(qū)動移植要點及AT25256驅(qū)動_第1頁
RT-Thread驅(qū)動移植要點及AT25256驅(qū)動_第2頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、RT-Thread驅(qū)動移植要點I/O管理模塊為應(yīng)用提供了一個對設(shè)備進(jìn)行訪問的通用接口,并通過定義的數(shù)據(jù)結(jié)構(gòu)對設(shè)備驅(qū)動程序和設(shè)備信息進(jìn)行管理。從系統(tǒng)整體位置來說I/O管理模塊相當(dāng)于設(shè)備驅(qū)動程序和上層應(yīng)用之間的一個中間層。I/O管理模塊實現(xiàn)了對設(shè)備驅(qū)動程序的封裝:設(shè)備驅(qū)動程序的實現(xiàn)與I/O管理模塊獨立,提高了模塊的可移植性。應(yīng)用程序通過I/O管理模塊提供的標(biāo)準(zhǔn)接口訪問底層設(shè)備,設(shè)備驅(qū)動程序的升級不會對上層應(yīng)用產(chǎn)生影響。這種方式使得與設(shè)備的硬件操作相關(guān)的代碼與應(yīng)用相隔離,雙方只需各自關(guān)注自己的功能,這降低了代碼的復(fù)雜性,提高了系統(tǒng)的可靠性。在RT-Thread中,設(shè)備也被認(rèn)為是一類對象,被納入對象管

2、理器范疇。每個設(shè)備對象都是由基對象派生而來,每個具體設(shè)備都可以繼承其父類對象的屬性,并派生出其私有屬性。下圖即為設(shè)備對象的繼承和派生關(guān)系示意圖。設(shè)備對象的繼承和派生關(guān)系示意圖1.I/O設(shè)備管理控制塊structrtdevicestructrtobjectparent;/*設(shè)備類型*/enumrtdeviceclasstypetype;/*設(shè)備參數(shù)及打開時參數(shù)*/rt_uintl6_tflag,openflag;/*設(shè)備回調(diào)接口*/rt_err_t(*rxindicate)(rt_device_tdev,rt_size_tsize);rt_err_t(*txcomplete)(rt_device

3、_tdev,void*buffer);/*設(shè)備公共接口*/rt_err_t(*init)(rt_device_tdev);rt_err_t(*open)(rt_device_tdev,rt_uint16_toflag);rt_err_t(*close)(rt_device_tdev);rt_size_t(*read)(rt_device_tdev,rt_off_tpos,void*buffer,rt_size_tsize);rt_size_t(*write)(rt_device_tdev,rt_off_tpos,constvoid*buffer,rt_size_tsize);rt_err_t(

4、*control)(rt_device_tdev,rt_uint8_tcmd,void*args);#ifdefRT_USING_DEVICE_SUSPENDrt_err_t(*suspend)(rt_device_tdev);rterrt(*resumed)(rtdevicetdev);#endif/*設(shè)備私有數(shù)據(jù)*/void*private;;當(dāng)前RT-Thread支持的設(shè)備類型包括:enumrt_device_class_typeRT_Device_Class_Char=0,/*字符設(shè)備*/RT_Device_Class_Block,/*塊設(shè)備*/RT_Device_Class_NetI

5、f,/*網(wǎng)絡(luò)接口設(shè)備*/RT_Device_Class_MTD,/*內(nèi)存設(shè)備*/RT_Device_Class_CAN,/*CAN設(shè)備*/RT_Device_Class_Unknown/*未知設(shè)備*/;注意:suspend、resume回調(diào)函數(shù)只會在RT_USING_DEVICE_SUSPEND宏使能的情況下才會有效。接口函數(shù)說明:每一個設(shè)備的驅(qū)動都對應(yīng)著一個設(shè)備管理控制塊,在編寫驅(qū)動的同時要定義該設(shè)備的控制塊結(jié)構(gòu)體,這個結(jié)構(gòu)體中包含了一些私有數(shù)據(jù)和一些公共接口函數(shù),公共設(shè)備接口函數(shù)是設(shè)備必須實現(xiàn)的,其中,當(dāng)設(shè)備使用掛起功能時才需要用到rt_err_t(*suspend)(rt_device_

6、tdev);rt_err_t(*resumed)(rt_device_tdev);這兩個接口函數(shù),其他的六個接口,可以看成是底層設(shè)備驅(qū)動必須提供的接口。rt_err_t(*init)(rt_device_tdev);設(shè)備的初始化。設(shè)備初始化完成后,設(shè)備控制塊的flag會被置成已激活狀態(tài)(RT_DEVICEFLAG_ACTIVATED)。如果設(shè)備控制塊的flag不是已激活狀態(tài),那么在設(shè)備框架調(diào)用rt_device_init_all接口時調(diào)用此設(shè)備驅(qū)動的init接口進(jìn)行設(shè)備初始化。rt_err_t(*open)(rt_device_tdev,rt_uint16_toflag);打開設(shè)備。有些設(shè)備并

7、不是系統(tǒng)一啟動就已經(jīng)打開開始運行的,或者設(shè)備需要進(jìn)行數(shù)據(jù)接收,但如果上層應(yīng)用還未準(zhǔn)備好,設(shè)備也不應(yīng)默認(rèn)已經(jīng)使能開始接收數(shù)據(jù)。所以建議底層驅(qū)動程序,在調(diào)用open接口時進(jìn)行設(shè)備的使能。rt_err_t(*close)(rt_device_tdev);關(guān)閉設(shè)備。在打開設(shè)備時,設(shè)備框架中會自動進(jìn)行打開計數(shù)(設(shè)備控制塊中的ocount數(shù)據(jù)域),只有當(dāng)打開計數(shù)為零的時候,底層設(shè)備驅(qū)動的close接口才會被調(diào)用。rt_size_t(*read)(rt_device_tdev,rt_off_tpos,void*buffer,rt_size_tsize);從設(shè)備中讀取數(shù)據(jù)。參數(shù)pos指出讀取數(shù)據(jù)的偏移量,但是

8、有些設(shè)備并不一定需要制定偏移量,例如串口設(shè)備,那么忽略這個參數(shù)即可。這個接口返回的類型是rt_size_t即讀到的字節(jié)數(shù),如果返回零建議檢查errno值。如果errno值并不是RT_EOK,那么或者已經(jīng)讀取了所有數(shù)據(jù),或者有錯誤發(fā)生。rt_size_t(*write)(rt_device_tdev,rt_off_tpos,constvoid*buffer,rt_size_tsize);往設(shè)備中寫入數(shù)據(jù)。同樣pos參數(shù)在一些情況下是不必要的,略過即可。rt_err_t(*control)(rt_device_tdev,rt_uint8_tcmd,void*args);根據(jù)不同的cmd命令控制設(shè)備

9、。命令往往是由底層設(shè)備驅(qū)動自定義實現(xiàn)的。2.設(shè)備驅(qū)動實現(xiàn)的步驟1. 實現(xiàn)RT-Thread中定義的設(shè)備公共接口,開始可以是空函數(shù)(返回類型是rt_err_t的可默認(rèn)返回RT_EOK)。2. 根據(jù)自己的設(shè)備類型定義自己的私有數(shù)據(jù)域。特別是可以有多個相同設(shè)備的情況下,設(shè)備接口可以用同一套,不同的只是各自的數(shù)據(jù)域(例如寄存器基地址)。3. 按照RT-Thread的對象模型,擴(kuò)展一個對象有兩種方式:(a) 定義自己的私有數(shù)據(jù)結(jié)構(gòu),然后賦值到RT-Thread設(shè)備控制塊的private指針上。(b) 從structrt_device結(jié)構(gòu)中進(jìn)行派生。4. 根據(jù)設(shè)備的類型,注冊到RT-Thread設(shè)備框架中

10、。3.注冊設(shè)備在一個設(shè)備能夠被上層應(yīng)用訪問前,需要先把這個設(shè)備注冊到系統(tǒng)中,并添加一些相應(yīng)的屬性。這些注冊的設(shè)備均可以采用“查找設(shè)備接口”通過設(shè)備名來查找設(shè)備,獲得該設(shè)備控制塊。注冊設(shè)備的原始如下:rt_err_trt_device_register(rt_device_tdev,constchar*name,rt_uint8_tflags)其中調(diào)用的ags參數(shù)支持如下列表中的參數(shù)(可以采用或的方式支持多種參數(shù)):#defineRT_DEVICE_FLAG_DEACTIVATE0x000/*未初始化設(shè)備*/#defineRTDEVICEFLAGRDONLY0x001/*只讀設(shè)備*/#defin

11、eRTDEVICEFLAGWRONIY0x002/*只寫設(shè)備*/#defineRTDEVICEFLAGRDWR0x003/*讀寫設(shè)備*/#defineRT_DEVICE_FLAG_REMOVABLE0x004/*可移除設(shè)備*/#defineRT_DEVICE_FLAG_STANDALONE0x008/*獨立設(shè)備*/#defineRTDEVICEFLAGACTIVATED0x010/*已激活設(shè)備*/#defineRTDEVICEFLAGSUSPENDED0x020/*掛起設(shè)備*/#defineRTDEVICEFLAGSTREAM0x040/*設(shè)備處于流模式*/#defineRTDEVICEFLA

12、GINTRX0x100/*設(shè)備處于中斷接收模式*/#defineRTDEVICEFLAGDMARX0x200/*設(shè)備處于DMA接收模式*/#defineRTDEVICEFLAGINTTX0x400/*設(shè)備處于中斷發(fā)送模式*/#defineRTDEVICEFLAGDMATX0x800/*設(shè)備處于DMA發(fā)送模式*/”時,自動在前面補一個”r”RT_DEVICE_FLAG_STREAM參數(shù)用于向串口終端輸出字符串,當(dāng)輸出的字符是”做分行。4.卸載設(shè)備將設(shè)備從設(shè)備系統(tǒng)中卸載,被卸載的設(shè)備將不能通過“查找設(shè)備接口”找到該設(shè)備,可以通過如下接口完成rt_err_trt_device_unregister(

13、rt_device_tdev)Note:卸載設(shè)備并不會釋放設(shè)備控制塊所占用的內(nèi)存。5.初始化所有設(shè)備初始化所有注冊到設(shè)備對象管理器中的未初始化的設(shè)備,可以通過如下接口完成:rt_err_trt_device_init_all(void)Note:如果設(shè)備的flags域已經(jīng)是RT_DEVICE_FLAG_ACTIVATED,調(diào)用這個接口將不再重復(fù)做初始化,一個設(shè)備初始化完成后它的flags域RT_DEVICE_FLAG_ACTIVATED應(yīng)該被置位。6.查找設(shè)備根據(jù)指定的設(shè)備名稱來查找設(shè)備,可以通過如下接口完成:rt_device_trt_device_find(constchar*name)使

14、用以上接口時,在設(shè)備對象類型所對應(yīng)的對象容器中遍歷尋找設(shè)備對象,然后返回該設(shè)備,如果沒有找到相應(yīng)的設(shè)備對象,則返回RT_NULL。7.打開設(shè)備根據(jù)設(shè)備控制塊來打開設(shè)備,可以通過如下接口完成:rt_err_trt_device_open(rt_device_tdev,rt_uint16_toflags)其中oflags支持以下列表中的參數(shù):#defineRT_DEVICE_OFLAG_RDONIY0x001/*只讀模式訪問*/#defineRT_DEVICE_OFLAG_WRONIY0x002/*只寫模式訪問*/#defineRT_DEVICE_OFLAG_RDWR0x003/*讀寫模式訪問*/

15、Note:如果設(shè)備flags域包含RT_DEVICE_FLAG_STANDALONE參數(shù),將不允許重復(fù)打開。8.關(guān)閉設(shè)備根據(jù)設(shè)備控制塊來關(guān)閉設(shè)備,可以通過如下接口完成:rt_err_trt_device_close(rt_device_tdev)9.讀設(shè)備根據(jù)設(shè)備控制塊來讀取設(shè)備,可以通過如下接口完成:rt_size_trt_device_read(rt_device_tdev,rt_off_tpos,void*buffer,rt_size_tsize)根據(jù)底層驅(qū)動的實現(xiàn),通常這個接口并不會阻塞上層應(yīng)用線程。返回值是讀到數(shù)據(jù)的大小(以字節(jié)為單位),如果返回值是0,需要讀取當(dāng)前線程的errno來

16、判斷錯誤狀態(tài)。10.寫設(shè)備根據(jù)設(shè)備控制塊來寫入設(shè)備,可以通過如下接口完成:rt_size_trt_device_write(rt_device_tdev,rt_off_tpos,constvoid*buffer,rt_size_tsize)根據(jù)底層驅(qū)動的實現(xiàn),通常這個接口并不會阻塞上層應(yīng)用線程。返回值是寫入數(shù)據(jù)的大小(以字節(jié)為單位),如果返回值是0需要讀取當(dāng)前線程的errno來判斷錯誤狀態(tài)。11.控制設(shè)備根據(jù)設(shè)備控制塊來控制設(shè)備,可以通過如下接口完成:rt_err_trtdevicecontrol(rt_device_tdev,rt_uint8_tcmd,void*arg)cmd命令參數(shù)通常是

17、和設(shè)備驅(qū)動程序相關(guān)的。12.設(shè)置數(shù)據(jù)接收指示設(shè)置一個回調(diào)函數(shù),當(dāng)硬件設(shè)備收到數(shù)據(jù)時回調(diào)給應(yīng)用程序以通知有數(shù)據(jù)達(dá)到??梢酝ㄟ^如下接口完成設(shè)置接收指示:rt_err_trt_device_set_rx_indicate(rt_device_tdev,rt_err_t(*rx_ind)(rt_device_tdev,rt_size_tsize)回調(diào)函數(shù)rx_ind由調(diào)用者提供,當(dāng)硬件設(shè)備接收到數(shù)據(jù)時,會回調(diào)這個函數(shù)并把收到的數(shù)據(jù)長度放在size參數(shù)中傳遞給上層應(yīng)用。上層應(yīng)用線程應(yīng)在收到指示時,立刻從設(shè)備中讀取數(shù)據(jù)。13.設(shè)置發(fā)送完成指示在上層應(yīng)用調(diào)用rt_device_write寫入數(shù)據(jù)時,如果底層

18、硬件能夠支持自動發(fā)送,那么上層應(yīng)用可以設(shè)置一個回調(diào)函數(shù)。這個回調(diào)函數(shù)會在底層硬件給出發(fā)送完成時(例如DMA傳送完成或FIFO已經(jīng)寫入完畢產(chǎn)生完成中斷時)被調(diào)用??梢酝ㄟ^如下接口完成設(shè)備發(fā)送完成指示:rt_err_trt_device_set_tx_complete(rt_device_tdev,rt_err_t(*tx_done)(rt_device_tdev,void*buffer)回調(diào)函數(shù)tx_done由調(diào)用者提供,當(dāng)硬件設(shè)備發(fā)送完數(shù)據(jù)時,由驅(qū)動程序回調(diào)這個函數(shù)并把發(fā)送完成的數(shù)據(jù)塊地址buffer做為參數(shù)傳遞給上層應(yīng)用。上層應(yīng)用(線程)在收到指示時應(yīng)根據(jù)發(fā)送buffer的情況,釋放buff

19、er內(nèi)存塊或為下一個寫數(shù)據(jù)做緩存。14.AT25256驅(qū)動例子AT25256概述AT2526是一個SPI總線接口器件,它由片選信號CS,時鐘信號SCK,輸入信號SI,輸出信號SO這四根信號線組成。AT25256的始終信號始終是輸入的,因此它一般作為從設(shè)備。單片機(jī)在選擇該器件工作時必須將CS信號拉低,同時設(shè)置時鐘信號滿足AT25256基本時序要求即可以和單片機(jī)通信。單片機(jī)在選擇AT25256工作時必須先寫入操作碼,使得從設(shè)備來完成相應(yīng)的工作,AT25256的操作碼如下圖:InstructionNameInstructionFormatOperationWREN0000X110SetWriteEn

20、ableLatchWRDI0000X100ResetWriteEnableLatchRDSR0000X101ReadStatusRegisterWRSR0000X001WriteStatusRegisterREAD0000X011ReadDatafromMemoryArrayWRITE0000X010WriteDatatoMemoryArray具體的操作碼對應(yīng)的功能詳解查看AT25256的Datasheet。142內(nèi)核態(tài)AT25256驅(qū)動實現(xiàn)14.2.1設(shè)備類型的定義,在RT-Theard操作系統(tǒng)中定義一個“AT25256”設(shè)備structrt_at256pcstructrt_devicepa

21、rent;/*bufferforreception*/rt_uint8_tread_index,save_index;rt_uint8_trx_bufferRT_UART_RX_BUFFER_SIZE;structrtat256lpcat256device;14.2.2定義并實現(xiàn)RT-Thread中定義的設(shè)備公共接口voidrt_hw_at256_init(void)structrt_at256_lpc*at256;/*getuartdevice*/at256=&at256_device;/*deviceinitialization*/at256->parent.type=RT_

22、Device_Class_Char;/*deviceinterface*/at256->parent.initat256->parent.openat256->parent.closeat256->parent.readat256->parent.writeat256->parent.controlat256->parent.user_data=rt_at256_init;設(shè)備初始化操作=rt_at256_open;打開設(shè)備=rt_at256_close;關(guān)閉設(shè)備=rt_at256_read;/設(shè)備讀操作=rt_at256_write;設(shè)備寫操作=RT

23、_NULL;=RT_NULL;rt_device_register(&at256->parent,"at256",RT_DEVICE_FLAG_RDWRIRT_DEVICE_FLAG_STREAMIRT_DEVICE_FLAG_INT_RX);/注冊設(shè)備初始化函數(shù)主要是實現(xiàn)了內(nèi)核中必須的公共接口函數(shù),這些接口也是上層應(yīng)用通過RT-Thread設(shè)備接口進(jìn)行訪問的實際底層接口,同時向內(nèi)核設(shè)備框架注冊,在一個設(shè)備能夠被上層應(yīng)用訪問前,需要先把這個設(shè)備注冊到系統(tǒng)中,并添加一些相應(yīng)的屬性。這些注冊的設(shè)備均可以采用“查找設(shè)備接口”通過設(shè)備名來查找設(shè)備,獲得該設(shè)備控制塊。r

24、t_at256_init函數(shù)主要實現(xiàn)的是AT25256具體初始化操作函數(shù),包括片選信號CS信號的控制,SCK時鐘信號的設(shè)置。staticrt_err_trt_at256_init(rt_device_tdev)PINSEL_CFG_TypePinCfg;/unsignedcharstate=0;PinCfg.Funcnum=3;PinCfg.OpenDrain=0;PinCfg.Pinmode=0;PinCfg.Portnum=0;PinCfg.Pinnum=15;PINSEL_ConfigPin(&PinCfg);PinCfg.Pinnum=17;PINSEL_ConfigPin(&

25、amp;PinCfg);PinCfg.Pinnum=18;PINSEL_ConfigPin(&PinCfg);PinCfg.Pinnum=16;PinCfg.Funcnum=0;PINSEL_ConfigPin(&PinCfg);/initializeSPIconfigurationstructuretodefaultSPI_ConfigStructInit(&SPI_ConfigStruct);SPI_ConfigStruct.ClockRate=400000;SPI_ConfigStruct.ClockRate=200000;SPI_ConfigStruct.CPH

26、A=SPI_CPHA_FIRST;SPI_ConfigStruct.CPOL=SPI_CPOL_HI;/InitializeSPIperipheralwithparametergiveninstructureaboveSPI_Init(SPI,&SPI_ConfigStruct);/Initialize/CSpintoGPIOfunctionCS_Init();WriteStateRegister(0x02);returnRT_EOK;rtat256open可以為空,默認(rèn)返回RTEOK,因為在設(shè)備初始化完成的時候,該設(shè)備已經(jīng)是處于可工作的狀態(tài)。staticrt_err_trt_at25

27、6_open(rt_device_tdev,rt_uint16_toflag)returnRT_EOK;rtat256close可以為空,默認(rèn)返回RTEOK。staticrt_err_trt_at256_close(rt_device_tdev)returnRT_EOK;rt_at256_read函數(shù)主要實現(xiàn)的是單片機(jī)對AT25256的讀操作函數(shù),即通過該函數(shù),單片機(jī)可以讀取從設(shè)備指定地址的數(shù)據(jù)。staticrt_size_trt_at256_read(rt_device_tdev,unsignedshortaddr,char*readbuf,unsignedcharcount)/voidAd

28、drAdjustRead(unsignedshortaddr,unsignedcharcount,char*readbuf)unsignedshortpage=0;/unsignedcharremaincount=0;unsignedcharpagecount=0;page=(unsignedshort)(addr/PAGE_SIZE);pagecount=START_PAGE_ADDR(page+1)-addr;if(page<PAGE_NUM)if(addr+count)<=START_PAGE_ADDR(page+1)ReadAt25256(addr,readbuf,coun

29、t);elseReadAt25256(addr,readbuf,pagecount);ReadAt25256(START_PAGE_ADDR(page+1),&readbufpagecount,count-pagecount);else最后一個扇區(qū)的操作if(addr+count)<=START_PAGE_ADDR(page+1)ReadAt25256(addr,readbuf,count);elseReadAt25256(addr,readbuf,pagecount);ReadAt25256(START_PAGE_ADDR(0),&readbufpagecount,count-pagecount);return0;rt_at256_write函數(shù)實現(xiàn)的是單片機(jī)對AT25256的寫操作函數(shù),通過該函數(shù),可以實現(xiàn)向從設(shè)備指定地址寫入指定的數(shù)據(jù)。staticrt_size_trt_at256_write(rt_device_tdev,unsignedshortaddr,char*writebuf,unsignedcharcount)/voidAddrAdjustWrite(unsignedshortaddr,unsignedcharcount,char*writebuf)unsignedshortpage=0;/un

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論