0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從接口定義和實(shí)現(xiàn)兩個(gè)方面,深入理解AWbus-lite

UtFs_Zlgmcu7890 ? 來源:互聯(lián)網(wǎng) ? 作者:佚名 ? 2018-07-23 09:08 ? 次閱讀

本文導(dǎo)讀

在使用AWBus-lite對(duì)設(shè)備進(jìn)行管理時(shí),無論設(shè)備處于 AWBus-lite拓?fù)浣Y(jié)構(gòu)中的哪個(gè)位置,只要其能夠提供某種標(biāo)準(zhǔn)服務(wù),就可以使用相應(yīng)的通用接口對(duì)其進(jìn)行操作。本文將從接口的定義和實(shí)現(xiàn)兩個(gè)方面,深入理解AWbus-lite工作的原理。

本文為《面向AWorks框架和接口的編程(上)》第三部分軟件篇——第13章——第1~2小節(jié):通用接口的定義和接口的實(shí)現(xiàn)。

本章導(dǎo)讀

在基于AWBus-lite總線拓?fù)浣Y(jié)構(gòu)的設(shè)備管理框架中,無論一個(gè)設(shè)備處于AWBus-lite總線拓?fù)浣Y(jié)構(gòu)中的哪個(gè)位置,只要其能夠提供某種標(biāo)準(zhǔn)服務(wù),就可以使用相應(yīng)的通用接口對(duì)其進(jìn)行訪問。那么,這究竟是怎樣實(shí)現(xiàn)的呢?本章將繼續(xù)深入探討AWBus-lite,為您揭開AWBus-lite的神秘面紗,使您對(duì)AWBus-lite有更加深入的了解,在具有這些足夠的了解后,你將有能力獨(dú)立開發(fā)一些設(shè)備的驅(qū)動(dòng),當(dāng)后續(xù)遇到一些AWorks暫不支持的設(shè)備時(shí),可以自行開發(fā)設(shè)備相應(yīng)的驅(qū)動(dòng)。

13.1 通用接口的定義

合理的接口應(yīng)該是簡(jiǎn)潔的、易閱讀的、職責(zé)明確的,為了便于維護(hù),通用接口由廣州致遠(yuǎn)電子有限公司進(jìn)行統(tǒng)一的定義,用戶通常不需要自行定義通用接口。目前,常用的功能都已經(jīng)被標(biāo)準(zhǔn)化,定義了相應(yīng)的通用接口。

作為一種了解,下面以LED為例,從接口的命名、參數(shù)和返回值三個(gè)方面闡述在AWorks中定義接口的一般方法。

13.1.1 接口命名

在AWorks中,所有通用接口均以“aw_”開頭,緊接著是操作對(duì)象的名字,對(duì)于LED控制接口來說,所有接口都應(yīng)該以“aw_led_”作為前綴。

在接口的前綴定義好之后,應(yīng)該考慮需要定義哪些功能性接口,然后根據(jù)功能完善接口名。對(duì)于LED來說,核心的操作是控制LED的狀態(tài),點(diǎn)亮或熄滅LED,為此,可以定義一個(gè)設(shè)置(set)LED狀態(tài)的函數(shù),比如:“aw_led_set”。

使用該接口可以設(shè)置LED的狀態(tài),顯然,為了區(qū)分是點(diǎn)亮還是熄滅LED,需要通過一個(gè)額外的參數(shù)來指定具體的操作。

每次開燈或關(guān)燈都需要傳遞額外的參數(shù)給aw_led_set()接口,顯得比較繁瑣。為了簡(jiǎn)化操作,可以為常用的開燈和關(guān)燈操作定義專用的接口,這樣就不需要額外的參數(shù)來對(duì)開燈和關(guān)燈操作進(jìn)行具體的區(qū)分了。比如,使用on和off分別表示開燈和關(guān)燈,則可以定義開燈的接口名為:“aw_led_on”,關(guān)燈的接口名為“aw_led_off”。

在一些特殊的應(yīng)用場(chǎng)合中,比如,LED閃爍,用戶可能并不關(guān)心具體的操作是開燈還是關(guān)燈,它僅僅需要LED的狀態(tài)發(fā)生翻轉(zhuǎn)。此時(shí),可以定義一個(gè)用于翻轉(zhuǎn)(toggle)LED狀態(tài)的專用接口,比如:“aw_led_toggle”

13.1.2 接口參數(shù)

在AWorks中,通用接口的第一個(gè)參數(shù)往往用于表示要操作的具體對(duì)象。顯然,在一個(gè)系統(tǒng)中,可能存在多個(gè)LED,為了區(qū)分各個(gè)LED,可以為每個(gè)LED分配一個(gè)唯一編號(hào),即ID號(hào)。ID號(hào)是一個(gè)從0開始的整數(shù),例如,系統(tǒng)中有兩個(gè)LED,則編號(hào)分別為0、1?;诖?,為了指定要操作的具體LED,通用接口的第一個(gè)參數(shù)可以設(shè)定為int類型的id。

對(duì)于aw_led_set接口,其除了使用id確定需要控制的LED外,還需要使用一個(gè)參數(shù)來區(qū)分是點(diǎn)亮LED還是熄滅LED,這是一個(gè)二選一的操作,對(duì)應(yīng)參數(shù)的類型可以使用布爾類型: aw_bool_t。當(dāng)值為真(AW_TRUE)時(shí),則點(diǎn)亮LED;當(dāng)值為假(AW_FALSE)時(shí),則熄滅LED。基于此,可以定義aw_led_set()接口的原型為(還未定義返回值):

對(duì)于aw_led_on、aw_led_off和aw_led_toggle接口來說,它們的職責(zé)單一,僅僅需要指定控制的LED,即可完成點(diǎn)亮、熄滅或翻轉(zhuǎn)操作,無需其它額外的參數(shù)。對(duì)于這類接口,參數(shù)僅僅需要id,這些接口的原型可以定義如下(還未定義返回值):

13.1.3 返回值

對(duì)于用戶來說,調(diào)用通用接口后,應(yīng)該可以獲取到本次執(zhí)行的結(jié)果,是執(zhí)行成功還是執(zhí)行失敗,或是一些其它的有用信息。比如,在調(diào)用接口時(shí),如果指定的id超過了有效范圍,由于沒有與無效id對(duì)應(yīng)的LED設(shè)備,操作必定會(huì)失敗,此時(shí)必須返回通過返回值告知用戶操作失敗,且操作失敗的原因是id不在有效范圍內(nèi),無與之對(duì)應(yīng)的LED設(shè)備。

在AWorks中,接口通常返回一個(gè)aw_err_t類型的返回值來表示接口執(zhí)行的結(jié)果,返回值的含義已被標(biāo)準(zhǔn)化:若返回值為AW_OK,則表示操作成功;若返回值為負(fù)數(shù),則表示操作失敗,此時(shí),用戶可根據(jù)具體的返回值,查找aw_errno.h文件中定義的宏,根據(jù)宏的含義確定失敗的原因;若返回值為正數(shù),其含義與具體接口相關(guān),由具體接口定義,無特殊說明則表示不會(huì)返回正數(shù)。AW_OK是在aw_common.h文件中定義的宏,其定義如下:

錯(cuò)誤號(hào)在aw_errno.h文件中定義,幾個(gè)常見錯(cuò)誤號(hào)的定義詳見表6.2。比如,在調(diào)用LED通用接口時(shí),若id不在有效范圍內(nèi),則該id沒有對(duì)應(yīng)的LED設(shè)備,此時(shí)接口應(yīng)該返回-AW_ENODEV。注意:AW_ENODEV的前面有一個(gè)負(fù)號(hào),以表示負(fù)值。

基于此,將所有LED通用接口的返回值類型定義為aw_err_t,LED控制接口的完整定義詳見表13.1,其對(duì)應(yīng)的類圖詳見圖13.1。

表13.1 LED通用接口(aw_led.h)

圖13.1 LED接口類圖

這些接口都已經(jīng)在aw_led.h文件中完成了定義,無需用戶再自行定義。上述從接口命名、參數(shù)和返回值三個(gè)方面詳細(xì)闡述了一套接口定義的方法,旨在讓用戶了解接口的由來,加深對(duì)接口的理解。實(shí)際中,定義接口并不是一件容易的事情,需要盡可能考慮到所有的情況,接口作為與用戶交互的途徑,一旦定義完成,如非必要,都應(yīng)該避免再對(duì)接口進(jìn)行修改。否則,所有依賴于該接口的應(yīng)用程序都將受到影響。因此,當(dāng)前并不建議用戶自定義通用接口,通用接口的定義應(yīng)由廣州致遠(yuǎn)電子有限公司統(tǒng)一規(guī)劃、定義、維護(hù)和管理。

13.2 接口的實(shí)現(xiàn)

作為一種范例,下面以實(shí)現(xiàn)LED接口為例,詳細(xì)介紹AWorks中實(shí)現(xiàn)接口的一般方法。

13.2.1 實(shí)現(xiàn)接口初探

在AWorks中,硬件設(shè)備和驅(qū)動(dòng)統(tǒng)一由AWBus-lite進(jìn)行管理,因此,對(duì)于LED這一類硬件設(shè)備,其實(shí)現(xiàn)是屬于AWBus-lite的一部分。LED有4個(gè)通用接口函數(shù),其中的aw_led_on()和aw_led_off()接口可以直接基于aw_led_set()接口實(shí)現(xiàn),詳見程序清單13.1。

程序清單13.1 aw_led_on()和aw_led_off()接口的實(shí)現(xiàn)

實(shí)現(xiàn)接口的核心是實(shí)現(xiàn)aw_led_set()和aw_led_toggle()這兩個(gè)接口。對(duì)于不同的底層硬件設(shè)備,LED實(shí)際控制方式是不同的,比如,最常見的,通過GPIO直接控制一個(gè)LED,簡(jiǎn)單范例詳見程序清單13.2。

程序清單13.2 aw_led_set()的實(shí)現(xiàn)(GPIO控制LED)

也有可能是通過串口控制一個(gè)LED設(shè)備。例如,通過發(fā)送字符串命令控制LED的狀態(tài),命令格式為:set ,其中,id為L(zhǎng)ED編號(hào),on為設(shè)置LED的狀態(tài),要點(diǎn)亮LED0,則發(fā)送字符串:"set 0 1"。這種情況下,aw_led_set()的實(shí)現(xiàn)范例詳見程序清單13.3。

程序清單13.3 aw_led_set()的實(shí)現(xiàn)(UART控制LED)

總之,底層硬件設(shè)備是多種多樣的,不同類型的LED設(shè)備對(duì)應(yīng)的控制方式也會(huì)不同。

定義通用接口的目的在于屏蔽底層硬件的差異性,即無論底層硬件如何變化,用戶都可以使用通用接口控制LED。顯然,如果直接類似程序清單13.2和程序清單13.3這樣實(shí)現(xiàn)一個(gè)通用接口,那么隨著LED設(shè)備種類的增加,同一個(gè)接口的實(shí)現(xiàn)代碼將有越來越多不同的版本。

在一個(gè)應(yīng)用程序中,一個(gè)接口不能同時(shí)具有多種不同的實(shí)現(xiàn),因此,這樣的做法有著非常明顯的缺點(diǎn):多個(gè)不同種類的LED設(shè)備不能在一個(gè)應(yīng)用中共存,更換硬件設(shè)備,就必須更換通用接口的實(shí)現(xiàn),使用何種設(shè)備就加入相應(yīng)設(shè)備的控制代碼進(jìn)行編譯。 例如,系統(tǒng)中有幾個(gè)直接通過GPIO控制的LED,同時(shí)也存在幾個(gè)通過UART控制的LED,那么,類似程序清單13.2和程序清單13.3這樣直接實(shí)現(xiàn)通用接口的方法,就無法組織代碼了,因?yàn)椴豢赡芡瑫r(shí)將程序清單13.2和程序清單13.3所示的代碼加入工程編譯。顯然,需要更好的辦法來解決這個(gè)問題。

13.2.2 LED抽象方法

在使用幾種控制方式不同的LED硬件設(shè)備時(shí),雖然它們對(duì)應(yīng)的aw_led_set()和aw_led_toggle()接口的具體實(shí)現(xiàn)方法并不相同,但它們要實(shí)現(xiàn)的功能卻是一樣的,這是它們的共性:均要實(shí)現(xiàn)設(shè)置LED狀態(tài)和翻轉(zhuǎn)LED狀態(tài)的功能。由于一個(gè)接口的實(shí)現(xiàn)代碼只能有一份,因此,這些功能的實(shí)現(xiàn)不能直接作為通用接口的實(shí)現(xiàn)代碼。為此,可以在通用接口和具體實(shí)現(xiàn)之間增加一個(gè)抽象層,以對(duì)共性進(jìn)行抽象,將兩種功能的實(shí)現(xiàn)抽象為如下兩個(gè)方法:

相對(duì)于通用接口來說,抽象方法多了一個(gè)p_cookie參數(shù)。在面向?qū)ο蟮木幊陶Z(yǔ)言中(如C++),對(duì)象中的方法都能通過隱式指針p_this訪問對(duì)象自身,引用自身的一些私有數(shù)據(jù)。而在C語(yǔ)言中則需要顯式的聲明,這里的p_cookie就有類似的作用,當(dāng)前設(shè)置為void *類型主要是由于具體對(duì)象的類型還并不確定。

為了節(jié)省內(nèi)存空間,同時(shí)方便管理,可以將所有抽象方法放在一個(gè)結(jié)構(gòu)體中,形成一張?zhí)摵瘮?shù)表,比如:

由于LED的實(shí)現(xiàn)屬于AWBus-lite的一部分,因此,命名使用"awbl_"作為前綴。這里定義了一個(gè)虛函數(shù)表,包含了兩個(gè)方法,分別用于設(shè)置LED的狀態(tài)和翻轉(zhuǎn)LED。針對(duì)不同的硬件設(shè)備,都可以根據(jù)自身特性實(shí)現(xiàn)這兩個(gè)方法。GPIO控制LED的偽代碼詳見程序清單13.4,UART控制LED的偽代碼詳見程序清單13.5。

程序清單13.4 抽象方法的實(shí)現(xiàn)(GPIO控制LED)

程序清單13.5 抽象方法的實(shí)現(xiàn)(UART控制LED)

顯然,__g_led_gpio_drv_funcs和__g_led_uart_drv_funcs分別是使用GPIO和UART控制LED的具體實(shí)現(xiàn),它們?cè)谛问缴鲜莾蓚€(gè)不同的結(jié)構(gòu)體常量,在同一系統(tǒng)中是可以共存的。

13.2.3 抽象的LED服務(wù)

當(dāng)對(duì)不同的LED硬件設(shè)備抽象了相同的pfn_led_set和pfn_led_toggle方法后,在通用接口aw_led_set()和aw_led_toggle()的實(shí)現(xiàn)中,就無需再處理與硬件相關(guān)的具體事務(wù),只需要找到相應(yīng)設(shè)備提供的相應(yīng)方法,然后調(diào)用這些具體硬件設(shè)備提供的方法即可。

在調(diào)用設(shè)備提供的方法時(shí),由于方法的第一個(gè)參數(shù)為p_cookie,p_cookie代表了具體的設(shè)備對(duì)象,調(diào)用方法時(shí),需要傳遞一個(gè)p_cookie給下層,用于在具體實(shí)現(xiàn)時(shí),訪問設(shè)備對(duì)象中的具體成員,起到“p_this”的作用。由于在aw_led_set()接口的實(shí)現(xiàn)中,并不需要直接操作具體設(shè)備,因此,無需知道p_cookie的具體類型,僅需起到一個(gè)傳遞的作用:在調(diào)用相應(yīng)的方法時(shí),傳遞給下層驅(qū)動(dòng)使用。

既然要傳遞p_cookie,那么,必然要獲得一個(gè)p_cookie并保存下來,顯然,p_cookie代表了具體設(shè)備,只能由具體設(shè)備提供,同時(shí),抽象方法也是由具體設(shè)備提供的,為此,可以將抽象方法和p_cookie定義在一起,形成一個(gè)新的類型,以便在具體設(shè)備提供的抽象方法的實(shí)現(xiàn)時(shí),將p_cookie一并提供,即:

為了便于描述,將其稱之為 “LED服務(wù)”。其中包含了由驅(qū)動(dòng)實(shí)現(xiàn)的抽象方法和傳遞給驅(qū)動(dòng)函數(shù)的p_cookie。其中,p_servfuncs為指向驅(qū)動(dòng)虛函數(shù)表的指針,比如,指向__g_led_gpio_drv_funcs或__g_led_uart_drv_funcs,p_cookie為指向具體設(shè)備的指針,即傳遞給驅(qū)動(dòng)函數(shù)的第一個(gè)參數(shù)。此時(shí),在aw_led_set()接口的實(shí)現(xiàn)中,無需再完成底層硬件相關(guān)的操作,僅需調(diào)用LED服務(wù)中包含的pfn_led_set方法即可,其范例程序詳見程序清單13.6。

程序清單13.6 aw_led_set()實(shí)現(xiàn)(1)

程序中,使用了一個(gè)全局變量__gp_led_serv指向當(dāng)前一個(gè)有效的LED服務(wù),顯然,其只有在賦值后才能使用,暫不考慮其如何賦值,僅用以展示pfn_led_set方法的調(diào)用形式。

實(shí)際中,具體的LED設(shè)備往往不止一個(gè)。比如,使用GPIO控制的LED設(shè)備和使用UART控制的LED設(shè)備,它們都可以向系統(tǒng)提供LED服務(wù),這就需要系統(tǒng)具有管理多個(gè)LED服務(wù)的能力。由于LED設(shè)備的數(shù)目無法確定,可能動(dòng)態(tài)變化,因此,選用單向鏈表進(jìn)行動(dòng)態(tài)管理。為此,在struct awbl_led_service中增加一個(gè)p_next成員,用于指向下一個(gè)LED服務(wù)。即:

此時(shí),系統(tǒng)中的多個(gè)LED服務(wù)使用鏈表的形式進(jìn)行管理。那么,在通用接口的實(shí)現(xiàn)中,如何確定具體該使用哪個(gè)LED服務(wù)呢?在定義通用接口時(shí),使用了ID號(hào)區(qū)分不同的LED,ID號(hào)是唯一的,顯然,某一ID的LED必然屬于某一確定的硬件設(shè)備,若一個(gè)硬件設(shè)備在提供LED服務(wù)時(shí),包含了該硬件設(shè)備中所有LED的ID號(hào)信息,那么,在通用接口的實(shí)現(xiàn)中,就可以根據(jù)ID找到對(duì)應(yīng)的LED服務(wù),然后使用驅(qū)動(dòng)中提供的方法完成LED的操作。為此,可以在LED服務(wù)中再增加一個(gè)ID信息,以表示對(duì)應(yīng)硬件設(shè)備中所有LED的ID號(hào)。

在一個(gè)LED硬件設(shè)備中,可能包含多個(gè)LED,例如,MiniPort-LED擴(kuò)展板,包含了8個(gè)LED,但一般來講,一個(gè)LED硬件設(shè)備中所有LED的編號(hào)是連續(xù)分配的,基于此,僅需知道一個(gè)硬件設(shè)備中LED的起始編號(hào)和結(jié)束編號(hào),就可以獲得該硬件設(shè)備中所有LED對(duì)應(yīng)的編號(hào),例如,一個(gè)硬件設(shè)備中LED的起始編號(hào)為2、結(jié)束編號(hào)為9,則表示在該硬件設(shè)備中,各個(gè)LED的編號(hào)分別為:2、3、4、5、6、7、8、9,共計(jì)8個(gè)LED。為此,可以定義一個(gè)LED服務(wù)信息結(jié)構(gòu)體類型,專門用于提供LED服務(wù)相關(guān)的信息,例如:

由此可見,在LED服務(wù)信息中,當(dāng)前僅包含起始編號(hào)和結(jié)束編號(hào)兩個(gè)信息。LED服務(wù)信息是與具體設(shè)備相關(guān)的,因此,可以在LED服務(wù)中新增一個(gè)指向LED服務(wù)信息的指針,以便在具體設(shè)備在提供p_cookie和抽象方法的實(shí)現(xiàn)時(shí),將設(shè)備支持的LED編號(hào)信息一并提供,LED服務(wù)的完整定義詳見程序清單13.7。

程序清單13.7 完整的LED服務(wù)類型定義(awbl_led.h)

由于在LED服務(wù)中新增了LED編號(hào)信息,那么,在通用接口的實(shí)現(xiàn)中,就可以根據(jù)設(shè)備提供的LED編號(hào)信息,找到id對(duì)應(yīng)的LED服務(wù)?;诖耍琣w_led_set()函數(shù)的實(shí)現(xiàn)詳見程序清單13.8。

程序清單13.8 aw_led_set()實(shí)現(xiàn)(2)

程序中,調(diào)用了__led_id_to_serv()函數(shù)以獲取ID號(hào)對(duì)應(yīng)的LED服務(wù)。__led_id_to_serv()函數(shù)通過遍歷LED服務(wù)鏈表,將id與各個(gè)LED服務(wù)中的ID信息進(jìn)行對(duì)比,直到找到id對(duì)應(yīng)的LED服務(wù)(即id處于該LED服務(wù)的起始編號(hào)和結(jié)束編號(hào)之間),具體實(shí)現(xiàn)范例詳見程序清單13.9。

程序清單13.9 獲取ID號(hào)對(duì)應(yīng)的LED服務(wù)

其中,__gp_led_serv_head是一個(gè)模塊內(nèi)部使用的全局變量,初始值為NULL,表示初始時(shí)系統(tǒng)中無任何有效的LED服務(wù)。同理,可實(shí)現(xiàn)aw_led_toggle()接口,詳見程序清單13.10。

程序清單13.10 aw_led_toggle()實(shí)現(xiàn)

至此,實(shí)現(xiàn)了所有通用接口。顯然,由于當(dāng)前并不存在任何有效的LED服務(wù),因此,__gp_led_serv_head的值為NULL,致使__led_id_to_serv()的返回值為NULL,最終導(dǎo)致通用接口的返回值始終為-AM_ENODEV。

13.2.4 Method機(jī)制

為了使通用接口能夠操作到具體有效的LED,必須通過某種方法,將當(dāng)前系統(tǒng)中所有LED設(shè)備提供的LED服務(wù)加入到以__gp_led_serv_head為頭的LED服務(wù)鏈表中。

AWbus-lite提供了一種特殊的“Method機(jī)制”,其是一種系統(tǒng)上層和硬件底層相互“交流”的一種方式,可用于系統(tǒng)發(fā)現(xiàn)各個(gè)硬件設(shè)備提供的服務(wù)。AWBus-lite提供了Method相關(guān)的宏,詳見表13.2。

表13.2 Method相關(guān)的宏(awbus_lite.h)

1. 定義一個(gè)Method類型

AWBL_METHOD_DEF()用于定義一個(gè)Method類型,其原型為:

其中,method為定義的Method類型名,string為一個(gè)描述字符串,描述字符串僅在定義時(shí)對(duì)method類型進(jìn)行描述,可以是任意字符串,其它地方不會(huì)被使用到。

Method類型具有唯一性,不可定義兩個(gè)相同的Method類型。Method類型可以看作一個(gè)“唯一標(biāo)識(shí)”,用于標(biāo)記某一類操作,在底層驅(qū)動(dòng)的實(shí)現(xiàn)中,凡是能夠完成該類操作的設(shè)備,都可以使用該“唯一標(biāo)識(shí)”標(biāo)記一個(gè)入口函數(shù),該入口函數(shù)即用于完成相應(yīng)的操作,這樣一來,系統(tǒng)就可以通過該“唯一標(biāo)識(shí)”查找所有被標(biāo)記的入口函數(shù),并依次調(diào)用它們,完成某種特定功能。例如,對(duì)于LED,為了獲取當(dāng)前系統(tǒng)中所有設(shè)備提供的LED服務(wù),可以定義一個(gè)獲取LED服務(wù)的Method類型,范例程序詳見程序清單13.11。

程序清單13.11 定義Method類型范例程序

如此一來,即定義了一個(gè)名為awbl_ledserv_get的Method類型,該Method類型即表示了一類操作:獲取LED服務(wù)。后續(xù)在底層設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)中,只要一個(gè)設(shè)備能夠提供LED服務(wù),則表示系統(tǒng)可以從中獲取到一個(gè)LED服務(wù),此時(shí),該驅(qū)動(dòng)就可以提供一個(gè)入口函數(shù),用于獲取LED服務(wù),并使用該Method類型對(duì)入口函數(shù)進(jìn)行標(biāo)記。這樣,在系統(tǒng)啟動(dòng)時(shí),就可以通過查找系統(tǒng)中所有被該Method類型標(biāo)記的入口函數(shù),然后一一調(diào)用它們,以此獲得所有設(shè)備提供的LED服務(wù)。

2. 定義一個(gè)具體的Method對(duì)象

定義Method對(duì)象的本質(zhì)就是使用Method類型標(biāo)記一個(gè)入口函數(shù),使系統(tǒng)知道該入口函數(shù)可以完成某種特定的功能,以便系統(tǒng)在合適的時(shí)機(jī)調(diào)用。為便于描述,在AWBus-lite中,將使用Method類型標(biāo)記的入口函數(shù)稱之為一個(gè)Method對(duì)象。AWBus-lite提供了定義Method對(duì)象的輔助宏,其原型為:

其中,name為使用AWBL_METHOD_DEF()定義的Method類型名,handler為用于完成某種特定功能的入口函數(shù)。例如,定義awbl_ledserv_get類型的目的是獲取LED服務(wù),因此,該類型的Method對(duì)象對(duì)應(yīng)的handler應(yīng)該能夠獲取到一個(gè)LED服務(wù)。handler的類型為awbl_method_handler_t,其定義如下(awbus_lite.h):

由此可見,awbl_method_handler_t是一個(gè)函數(shù)指針類型,其指向的函數(shù)有兩個(gè)形參:p_dev和p_arg,返回值為標(biāo)準(zhǔn)的錯(cuò)誤號(hào)。p_dev指向設(shè)備自身,同樣起到一個(gè)p_this的作用,該handler運(yùn)行在哪個(gè)設(shè)備上,傳入p_dev的值就應(yīng)該為指向該設(shè)備的指針;p_arg為void *類型的參數(shù),其具體類型與該入口函數(shù)需要完成的功能相關(guān),如果功能為獲取一個(gè)LED服務(wù),p_arg的實(shí)際類型就為struct awbl_led_service **,即一個(gè)指向LED服務(wù)的指針的地址,以便在函數(shù)內(nèi)部改變指向LED服務(wù)的指針的值,使其指向設(shè)備提供的LED服務(wù),從而完成LED服務(wù)的獲取。例如,在GPIO控制LED的設(shè)備中,其能夠提供LED服務(wù),則應(yīng)在對(duì)應(yīng)的驅(qū)動(dòng)中,定義一個(gè)具體的Method對(duì)象,便于系統(tǒng)得到LED服務(wù)。范例詳見程序清單13.12。

程序清單13.12 定義Method對(duì)象范例程序

其中,__g_led_gpio_dev_methods為該設(shè)備能夠提供的Method對(duì)象列表,一個(gè)設(shè)備提供的Method對(duì)象統(tǒng)一存放在一個(gè)列表中。該列表的具體使用以及入口函數(shù)的具體實(shí)現(xiàn),將在LED驅(qū)動(dòng)的實(shí)現(xiàn)中進(jìn)一步介紹。這里僅用于展示系統(tǒng)上層獲取LED服務(wù)的原理。

3. Method對(duì)象列表結(jié)束標(biāo)記

在程序清單13.12中,將Method對(duì)象定義在了一個(gè)列表中,AWBL_METHOD_END用于定義一個(gè)特殊的標(biāo)志,表示Method對(duì)象列表的結(jié)束。其原型為:

該宏無需傳入任何參數(shù),其僅用于標(biāo)識(shí)一個(gè)Method對(duì)象列表的結(jié)束。例如,GPIO控制的LED設(shè)備只能提供一個(gè)Method對(duì)象,用于系統(tǒng)上層獲取LED服務(wù),那么,在該對(duì)象之后,應(yīng)該使用AWBL_METHOD_END表示列表結(jié)束。范例程序詳見程序清單13.13。

程序清單13.13 AWBL_METHOD_END使用范例程序

4. 導(dǎo)入(聲明)一個(gè)在外部定義的Method類型

當(dāng)需要使用一個(gè)已定義的Method類型時(shí),若Method類型是在其它文件中定義的,此時(shí)就需要在使用前對(duì)該Method類型進(jìn)行聲明,類似于C語(yǔ)言中的extern。其原型為:

其中,name為使用AWBL_METHOD_DEF()定義的Method類型名。例如,在程序清單13.13中,定義了Method對(duì)象列表,其中使用到了Method類型:awbl_ledserv_get。在使用前,需要對(duì)該Method類型進(jìn)行聲明,范例程序詳見程序清單13.14。

程序清單13.14 AWBL_METHOD_IMPORT()使用范例程序

5. 得到一個(gè)已定義的Method類型的ID

Method類型相當(dāng)于一個(gè)“唯一標(biāo)識(shí)”,有時(shí)候,需要判斷某一Method對(duì)象是否為指定的Method類型。為了便于比較判斷,或?qū)ⅰ癕ethod類型”作為參數(shù)傳遞給其它接口函數(shù),可以通過該宏獲得一個(gè)Method類型對(duì)應(yīng)的ID,ID作為一個(gè)常量,可以用于比較或參數(shù)傳遞。獲取Method類型的ID對(duì)應(yīng)的宏原型為:

其中,method為使用AWBL_METHOD_DEF()定義的Method類型名,返回值為該Method類型的ID,其類型為:awbl_method_id_t,該類型的具體定義用戶無需關(guān)心,ID可以用作比較,只要兩個(gè)Method類型的ID相同,就表示兩個(gè)Method類型是相同的,ID也可以作為參數(shù)傳遞給其它接口,以指定一種Method類型。

例如,在AWbus-lite中,提供了一個(gè)工具函數(shù),用于查找設(shè)備中是否存在指定類型的Method對(duì)象,其函數(shù)原型為(awbus_lite.h):

其中,p_dev指定了要查找的設(shè)備,即在該設(shè)備中查找是否存在指定類型的Method對(duì)象,method用于指定Method類型的ID。若查找到該ID對(duì)應(yīng)的method對(duì)象,則返回該method對(duì)象的入口函數(shù),否則,返回NULL。

例如,有一個(gè)p_dev指向的設(shè)備,要查找其是否能夠提供LED服務(wù),則可以通過該接口實(shí)現(xiàn),范例程序詳見程序清單13.15。

程序清單13.15 AWBL_METHOD_ CALL()使用范例程序

程序中,使用AWBL_METHOD_ CALL()得到Method類型awbl_ledserv_get的ID,然后傳遞給awbl_dev_method_get()函數(shù)以查找設(shè)備中是否存在相應(yīng)的Method對(duì)象,若存在,則得到了一個(gè)有效的入口函數(shù),最后使用該入口函數(shù)即可得到一個(gè)LED服務(wù)。

13.2.5 LED服務(wù)鏈表的初始化

通過程序清單13.15所示的一個(gè)流程,若一個(gè)設(shè)備能夠提供LED服務(wù),則可以從中獲取到相應(yīng)的LED服務(wù)。若對(duì)每個(gè)設(shè)備都執(zhí)行一遍上述流程,并在獲得一個(gè)設(shè)備提供的LED服務(wù)后,就將其添加到以__gp_led_serv_head為頭的LED服務(wù)鏈表中,則可以收集到系統(tǒng)中所有的LED服務(wù),完成LED服務(wù)鏈表的初始構(gòu)建。為了便于對(duì)所有設(shè)備執(zhí)行某一操作,AWBus-lite提供了一個(gè)用于遍歷所有設(shè)備的接口,其函數(shù)原型為:

其中,pfunc_action表示要在每個(gè)設(shè)備上執(zhí)行的操作,p_arg為傳遞給pfunc_action的附加參數(shù),flags為遍歷設(shè)備的標(biāo)志,返回值為標(biāo)準(zhǔn)錯(cuò)誤號(hào)。

pfunc_action的類型為awbl_iterate_func_t,該類型的具體定義如下(awbus_lite.h):

由此可見,awbl_iterate_func_t是一個(gè)函數(shù)指針類型,其指向的函數(shù)有兩個(gè)形參:p_dev和p_arg,返回值為標(biāo)準(zhǔn)的錯(cuò)誤號(hào)。p_dev指向當(dāng)前遍歷到的設(shè)備,同樣起到一個(gè)p_this的作用,當(dāng)前遍歷到哪個(gè)設(shè)備,在哪個(gè)設(shè)備上運(yùn)行pfunc_action函數(shù),傳入的p_dev就為指向該設(shè)備的指針;p_arg為遍歷時(shí)提供的附加參數(shù),其值與調(diào)用awbl_dev_iterate()函數(shù)時(shí)傳入的p_arg參數(shù)相同。

flags為遍歷設(shè)備的標(biāo)志,其決定了需要遍歷哪些設(shè)備,以及pfunc_action函數(shù)的返回值是否能夠終止遍歷過程??捎脴?biāo)志詳見表13.3。

表13.3 遍歷設(shè)備標(biāo)志宏(awbus_lite.h)

其中,AWBL_ITERATE_INSTANCES和AWBL_ITERATE_ORPHANS標(biāo)志用于指定需要遍歷的設(shè)備,即在哪些設(shè)備上執(zhí)行pfunc_action函數(shù)。在硬件設(shè)備列表中,定義了當(dāng)前系統(tǒng)中所有的硬件設(shè)備,當(dāng)設(shè)備具有與之匹配的驅(qū)動(dòng)時(shí),才能夠變成一個(gè)實(shí)例,被系統(tǒng)正常使用,而如果一個(gè)設(shè)備沒有與之匹配的驅(qū)動(dòng),該設(shè)備將變成一個(gè)孤兒設(shè)備,由于沒有與之匹配的驅(qū)動(dòng),因此系統(tǒng)暫時(shí)無法使用孤兒設(shè)備。AWBL_ITERATE_INSTANCES表示表示需要遍歷所有實(shí)例,即具有相應(yīng)驅(qū)動(dòng)的設(shè)備。AWBL_ITERATE_ORPHANS表示需要遍歷所有的孤兒設(shè)備。若要遍歷所有的實(shí)例和孤兒設(shè)備,可以使用或運(yùn)算同時(shí)設(shè)定這兩個(gè)標(biāo)志。

AWBL_ITERATE_INTRABLE標(biāo)志用于指定pfunc_action 的返回值是否可以終止遍歷,若設(shè)定了該標(biāo)志,則在某一設(shè)備上運(yùn)行pfunc_action函數(shù)的返回值將可以決定是否終止整個(gè)遍歷過程:返回值為AW_OK時(shí),不終止遍歷,繼續(xù)遍歷其它設(shè)備;否則,遍歷過程被終止,不會(huì)再繼續(xù)遍歷其它設(shè)備。若未設(shè)定該標(biāo)志,則遍歷過程不受返回值影響,直到遍歷完所有需要遍歷的設(shè)備后結(jié)束。

為了獲得所有設(shè)備提供的LED服務(wù),需要遍歷所有實(shí)例,并在pfunc_action中執(zhí)行如程序清單13.15所示的流程,并將各個(gè)設(shè)備提供的LED服務(wù)添加到以__gp_led_serv_head為頭的LED服務(wù)鏈表中。完整的范例程序詳見程序清單13.16。

程序清單13.16 獲取所有設(shè)備提供的LED服務(wù)

程序中,由于孤兒設(shè)備沒有對(duì)應(yīng)的驅(qū)動(dòng),無法正常使用,顯然無法提供LED服務(wù),因此僅需遍歷所有實(shí)例,遍歷標(biāo)志設(shè)定為了:AWBL_ITERATE_INSTANCES。該程序的目的是完成LED服務(wù)鏈表的初始構(gòu)建,是一種初始化操作,因此,將其入口函數(shù)命名為了awbl_led_init(),若需使用LED,則應(yīng)確保在系統(tǒng)啟動(dòng)時(shí),該函數(shù)被自動(dòng)調(diào)用。通常情況下,并不需要由用戶手動(dòng)調(diào)用該函數(shù),而是將該函數(shù)的調(diào)用放在模板工程下的aw_prj_config.c文件中,具體位于aw_prj_early_init()函數(shù)中,該函數(shù)在系統(tǒng)啟動(dòng)時(shí)會(huì)被自動(dòng)調(diào)用,從而使系統(tǒng)在啟動(dòng)時(shí)自動(dòng)調(diào)用awbl_led_init()函數(shù),詳見詳見程序清單13.17。

程序清單13.17 awbl_led_init()在系統(tǒng)啟動(dòng)時(shí)被自動(dòng)調(diào)用的原理

在aw_prj_params.h工程配置文件中,只要使能了某一LED設(shè)備,比如,AW_DEV_GPIO_LED,則表示要使用LED,此時(shí),將自動(dòng)完成AW_COM_AWBL_LED的定義,以此確保當(dāng)使用LED時(shí),awbl_led_init()會(huì)在系統(tǒng)啟動(dòng)過程中被自動(dòng)調(diào)用。核心的原理性程序詳見程序清單13.18。

程序清單13.18 自動(dòng)定義AW_COM_AWBL_LED宏的原理(aw_prj_params.h)

至此,完成了LED服務(wù)鏈表的初始化,若系統(tǒng)中存在LED服務(wù),則鏈表將不為空,在LED通用接口的實(shí)現(xiàn)中,只要傳入的id正確,__led_id_to_serv()的返回值就不為NULL,進(jìn)而返回一個(gè)有效的LED服務(wù),接著,通過LED服務(wù)中實(shí)現(xiàn)的抽象方法,即可完成LED相關(guān)的操作,例如,設(shè)置LED狀態(tài)、翻轉(zhuǎn)LED狀態(tài)等。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8257

    瀏覽量

    149952
  • 總線
    +關(guān)注

    關(guān)注

    10

    文章

    2817

    瀏覽量

    87704
  • 周立功
    +關(guān)注

    關(guān)注

    38

    文章

    130

    瀏覽量

    37438

原文標(biāo)題:AWorks軟件篇 — 深入理解 AWbus-lite(接口的定義和實(shí)現(xiàn))

文章出處:【微信號(hào):Zlgmcu7890,微信公眾號(hào):周立功單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    設(shè)備驅(qū)動(dòng)在AWbus-lite中驅(qū)動(dòng)設(shè)備正常工作

    個(gè)硬件設(shè)備正常工作的前提是系統(tǒng)中存在對(duì)應(yīng)的驅(qū)動(dòng)。AWorks提供了大量常用硬件設(shè)備的驅(qū)動(dòng),用戶通常不需要開發(fā)驅(qū)動(dòng)。本文介紹了設(shè)備驅(qū)動(dòng)相關(guān)的基礎(chǔ)概念,展示了設(shè)備驅(qū)動(dòng)在AWbus-lite中驅(qū)動(dòng)設(shè)備正常工作的原理。
    的頭像 發(fā)表于 06-12 09:06 ?4027次閱讀
    設(shè)備驅(qū)動(dòng)在<b class='flag-5'>AWbus-lite</b>中驅(qū)動(dòng)設(shè)備正常工作

    AWBus-lite的拓?fù)浣Y(jié)構(gòu)及應(yīng)用設(shè)計(jì)

    為了管理系統(tǒng)中各式各樣的硬件設(shè)備(或虛擬硬件設(shè)備),AWorks推出了領(lǐng)先的輕量級(jí)總線管理框架:AWBus-lite,實(shí)現(xiàn)了硬件設(shè)備和驅(qū)動(dòng)的徹底分離,使設(shè)備驅(qū)動(dòng)可以最大限度的得到復(fù)用。本文介紹了AWBus-lite的基礎(chǔ)概念……
    的頭像 發(fā)表于 06-21 09:10 ?5778次閱讀
    <b class='flag-5'>AWBus-lite</b>的拓?fù)浣Y(jié)構(gòu)及應(yīng)用設(shè)計(jì)

    深入理解Android

    深入理解Android
    發(fā)表于 08-20 15:30

    深入理解實(shí)現(xiàn)RTOS_連載

    和trcohili的帖子。深入理解實(shí)現(xiàn)RTOS_連載1_RTOS的前生今世今天發(fā)布的是第一篇,"RTOS的前生今世"。通過軟件系統(tǒng)結(jié)構(gòu)的比對(duì)簡(jiǎn)要的介紹rtos為何而生。如果讀者對(duì)RTOS
    發(fā)表于 05-29 11:20

    深入理解實(shí)現(xiàn)RTOS_連載

    和trcohili的帖子。trochili rtos完全是作者興趣所在,且行且堅(jiān)持,比沒有duo。深入理解實(shí)現(xiàn)RTOS_連載1_RTOS的前生今世今天發(fā)布的是第一篇,"RTOS的前生今世"
    發(fā)表于 05-30 01:02

    深入理解lte-a

    深入理解LTE-A
    發(fā)表于 02-26 10:21

    深入理解STM32

    時(shí)鐘系統(tǒng)是處理器的核心,所以在學(xué)習(xí)STM32所有外設(shè)之前,認(rèn)真學(xué)習(xí)時(shí)鐘系統(tǒng)是必要的,有助于深入理解STM32。下面是網(wǎng)上找的一個(gè)STM32時(shí)鐘框圖,比《STM32中文參考手冊(cè)》里面的是中途看起來清晰一些:重要的時(shí)鐘:PLLCL
    發(fā)表于 08-12 07:46

    對(duì)棧的深入理解

    為什么要深入理解棧?做C語(yǔ)言開發(fā)如果棧設(shè)置不合理或者使用不對(duì),棧就會(huì)溢出,溢出就會(huì)遇到無法預(yù)測(cè)亂飛現(xiàn)象。所以對(duì)棧的深入理解是非常重要的。注:動(dòng)畫如果看不清楚可以電腦看更清晰啥是棧先來看一段動(dòng)畫:沒有
    發(fā)表于 02-15 07:01

    為什么要深入理解

    [導(dǎo)讀] 從這篇文章開始,將會(huì)不定期更新關(guān)于嵌入式C語(yǔ)言編程相關(guān)的個(gè)人認(rèn)為比較重要的知識(shí)點(diǎn),或者踩過的坑。為什么要深入理解棧?做C語(yǔ)言開發(fā)如果棧設(shè)置不合理或者使用不對(duì),棧就會(huì)溢出,溢出就會(huì)遇到無法
    發(fā)表于 02-15 06:09

    深入理解Android》文前

    深入理解Android》文前
    發(fā)表于 03-19 11:23 ?0次下載

    深入理解Android:卷I》

    深入理解Android:卷I》
    發(fā)表于 03-19 11:23 ?0次下載

    深入理解Android網(wǎng)絡(luò)編程

    深入理解Android網(wǎng)絡(luò)編程
    發(fā)表于 03-19 11:26 ?1次下載

    基于AWBus-lite總線拓?fù)浣Y(jié)構(gòu)的設(shè)備管理框架

    在使用AWBus-lite對(duì)設(shè)備進(jìn)行管理時(shí),無論設(shè)備處于 AWBus-lite拓?fù)浣Y(jié)構(gòu)中的哪個(gè)位置,只要其能夠提供某種標(biāo)準(zhǔn)服務(wù),就可以使用相應(yīng)的通用接口對(duì)其進(jìn)行操作。本文將從接口
    的頭像 發(fā)表于 07-02 09:20 ?5228次閱讀
    基于<b class='flag-5'>AWBus-lite</b>總線拓?fù)浣Y(jié)構(gòu)的設(shè)備管理框架

    辨別PCB線路板好壞可以兩個(gè)方面入手

    面對(duì)市面上五花八門的PCB線路板,辨別PCB線路板好壞可以兩個(gè)方面入手;第一種方法就是外觀來分判斷,另一方面就是PCB板本身質(zhì)量規(guī)范要
    的頭像 發(fā)表于 08-28 15:12 ?3438次閱讀

    兩個(gè)方面講解電子連接器知識(shí)

    兩個(gè)方面講解電子連接器知識(shí)”由德索連接器為您整理,采購(gòu)連接器,上德索。功能上定義理解,電子連接器是在一個(gè)電子系統(tǒng)中的
    的頭像 發(fā)表于 01-12 18:13 ?778次閱讀
    <b class='flag-5'>兩個(gè)方面</b>講解電子連接器知識(shí)