RM新时代网站-首页

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

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

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

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

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

本文導(dǎo)讀

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

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

本章導(dǎo)讀

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

13.1 通用接口的定義

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

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

13.1.1 接口命名

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

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

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

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

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

13.1.2 接口參數(shù)

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

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

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

13.1.3 返回值

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

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

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

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

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

圖13.1 LED接口類圖

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

13.2 接口的實現(xiàn)

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

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

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

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

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

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

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

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

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

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

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

13.2.2 LED抽象方法

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

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

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

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

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

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

顯然,__g_led_gpio_drv_funcs和__g_led_uart_drv_funcs分別是使用GPIO和UART控制LED的具體實現(xiàn),它們在形式上是兩個不同的結(jié)構(gòu)體常量,在同一系統(tǒng)中是可以共存的。

13.2.3 抽象的LED服務(wù)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

13.2.4 Method機制

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

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

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

1. 定義一個Method類型

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

其中,method為定義的Method類型名,string為一個描述字符串,描述字符串僅在定義時對method類型進行描述,可以是任意字符串,其它地方不會被使用到。

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

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

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

2. 定義一個具體的Method對象

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

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

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

程序清單13.12 定義Method對象范例程序

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

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

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

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

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

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

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

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

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

5. 得到一個已定義的Method類型的ID

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

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

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

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

例如,有一個p_dev指向的設(shè)備,要查找其是否能夠提供LED服務(wù),則可以通過該接口實現(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對象,若存在,則得到了一個有效的入口函數(shù),最后使用該入口函數(shù)即可得到一個LED服務(wù)。

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

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

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

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

由此可見,awbl_iterate_func_t是一個函數(shù)指針類型,其指向的函數(shù)有兩個形參:p_dev和p_arg,返回值為標(biāo)準(zhǔn)的錯誤號。p_dev指向當(dāng)前遍歷到的設(shè)備,同樣起到一個p_this的作用,當(dāng)前遍歷到哪個設(shè)備,在哪個設(shè)備上運行pfunc_action函數(shù),傳入的p_dev就為指向該設(shè)備的指針;p_arg為遍歷時提供的附加參數(shù),其值與調(diào)用awbl_dev_iterate()函數(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ū)動時,才能夠變成一個實例,被系統(tǒng)正常使用,而如果一個設(shè)備沒有與之匹配的驅(qū)動,該設(shè)備將變成一個孤兒設(shè)備,由于沒有與之匹配的驅(qū)動,因此系統(tǒng)暫時無法使用孤兒設(shè)備。AWBL_ITERATE_INSTANCES表示表示需要遍歷所有實例,即具有相應(yīng)驅(qū)動的設(shè)備。AWBL_ITERATE_ORPHANS表示需要遍歷所有的孤兒設(shè)備。若要遍歷所有的實例和孤兒設(shè)備,可以使用或運算同時設(shè)定這兩個標(biāo)志。

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

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

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

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

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

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

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

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

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

    關(guān)注

    33

    文章

    8575

    瀏覽量

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

    關(guān)注

    10

    文章

    2878

    瀏覽量

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

    關(guān)注

    38

    文章

    130

    瀏覽量

    37614

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

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

收藏 人收藏

    評論

    相關(guān)推薦

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

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

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

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

    深入理解Android

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

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

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

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

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

    深入理解lte-a

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

    深入理解STM32

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

    對棧的深入理解

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

    為什么要深入理解

    [導(dǎo)讀] 從這篇文章開始,將會不定期更新關(guān)于嵌入式C語言編程相關(guān)的個人認(rèn)為比較重要的知識點,或者踩過的坑。為什么要深入理解棧?做C語言開發(fā)如果棧設(shè)置不合理或者使用不對,棧就會溢出,溢出就會遇到無法
    發(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對設(shè)備進行管理時,無論設(shè)備處于 AWBus-lite拓?fù)浣Y(jié)構(gòu)中的哪個位置,只要其能夠提供某種標(biāo)準(zhǔn)服務(wù),就可以使用相應(yīng)的通用接口對其進行操作。本文將從接口
    的頭像 發(fā)表于 07-02 09:20 ?5306次閱讀
    基于<b class='flag-5'>AWBus-lite</b>總線拓?fù)浣Y(jié)構(gòu)的設(shè)備管理框架

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

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

    兩個方面講解電子連接器知識

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