本文導讀
在使用AWBus-lite對設備進行管理時,無論設備處于 AWBus-lite拓撲結構中的哪個位置,只要其能夠提供某種標準服務,就可以使用相應的通用接口對其進行操作。本文將從接口的定義和實現兩個方面,深入理解AWbus-lite工作的原理。
本文為《面向AWorks框架和接口的編程(上)》第三部分軟件篇——第13章——第1~2小節:通用接口的定義和接口的實現。本章導讀
在基于AWBus-lite總線拓撲結構的設備管理框架中,無論一個設備處于AWBus-lite總線拓撲結構中的哪個位置,只要其能夠提供某種標準服務,就可以使用相應的通用接口對其進行訪問。那么,這究竟是怎樣實現的呢?本章將繼續深入探討AWBus-lite,為您揭開AWBus-lite的神秘面紗,使您對AWBus-lite有更加深入的了解,在具有這些足夠的了解后,你將有能力獨立開發一些設備的驅動,當后續遇到一些AWorks暫不支持的設備時,可以自行開發設備相應的驅動。
13.1 通用接口的定義
合理的接口應該是簡潔的、易閱讀的、職責明確的,為了便于維護,通用接口由廣州致遠電子有限公司進行統一的定義,用戶通常不需要自行定義通用接口。目前,常用的功能都已經被標準化,定義了相應的通用接口。
作為一種了解,下面以LED為例,從接口的命名、參數和返回值三個方面闡述在AWorks中定義接口的一般方法。
13.1.1 接口命名
在AWorks中,所有通用接口均以“aw_”開頭,緊接著是操作對象的名字,對于LED控制接口來說,所有接口都應該以“aw_led_”作為前綴。
在接口的前綴定義好之后,應該考慮需要定義哪些功能性接口,然后根據功能完善接口名。對于LED來說,核心的操作是控制LED的狀態,點亮或熄滅LED,為此,可以定義一個設置(set)LED狀態的函數,比如:“aw_led_set”。
使用該接口可以設置LED的狀態,顯然,為了區分是點亮還是熄滅LED,需要通過一個額外的參數來指定具體的操作。
每次開燈或關燈都需要傳遞額外的參數給aw_led_set()接口,顯得比較繁瑣。為了簡化操作,可以為常用的開燈和關燈操作定義專用的接口,這樣就不需要額外的參數來對開燈和關燈操作進行具體的區分了。比如,使用on和off分別表示開燈和關燈,則可以定義開燈的接口名為:“aw_led_on”,關燈的接口名為“aw_led_off”。
在一些特殊的應用場合中,比如,LED閃爍,用戶可能并不關心具體的操作是開燈還是關燈,它僅僅需要LED的狀態發生翻轉。此時,可以定義一個用于翻轉(toggle)LED狀態的專用接口,比如:“aw_led_toggle”
13.1.2 接口參數
在AWorks中,通用接口的第一個參數往往用于表示要操作的具體對象。顯然,在一個系統中,可能存在多個LED,為了區分各個LED,可以為每個LED分配一個唯一編號,即ID號。ID號是一個從0開始的整數,例如,系統中有兩個LED,則編號分別為0、1。基于此,為了指定要操作的具體LED,通用接口的第一個參數可以設定為int類型的id。
對于aw_led_set接口,其除了使用id確定需要控制的LED外,還需要使用一個參數來區分是點亮LED還是熄滅LED,這是一個二選一的操作,對應參數的類型可以使用布爾類型: aw_bool_t。當值為真(AW_TRUE)時,則點亮LED;當值為假(AW_FALSE)時,則熄滅LED。基于此,可以定義aw_led_set()接口的原型為(還未定義返回值):
對于aw_led_on、aw_led_off和aw_led_toggle接口來說,它們的職責單一,僅僅需要指定控制的LED,即可完成點亮、熄滅或翻轉操作,無需其它額外的參數。對于這類接口,參數僅僅需要id,這些接口的原型可以定義如下(還未定義返回值):
13.1.3 返回值
對于用戶來說,調用通用接口后,應該可以獲取到本次執行的結果,是執行成功還是執行失敗,或是一些其它的有用信息。比如,在調用接口時,如果指定的id超過了有效范圍,由于沒有與無效id對應的LED設備,操作必定會失敗,此時必須返回通過返回值告知用戶操作失敗,且操作失敗的原因是id不在有效范圍內,無與之對應的LED設備。
在AWorks中,接口通常返回一個aw_err_t類型的返回值來表示接口執行的結果,返回值的含義已被標準化:若返回值為AW_OK,則表示操作成功;若返回值為負數,則表示操作失敗,此時,用戶可根據具體的返回值,查找aw_errno.h文件中定義的宏,根據宏的含義確定失敗的原因;若返回值為正數,其含義與具體接口相關,由具體接口定義,無特殊說明則表示不會返回正數。AW_OK是在aw_common.h文件中定義的宏,其定義如下:
錯誤號在aw_errno.h文件中定義,幾個常見錯誤號的定義詳見表6.2。比如,在調用LED通用接口時,若id不在有效范圍內,則該id沒有對應的LED設備,此時接口應該返回-AW_ENODEV。注意:AW_ENODEV的前面有一個負號,以表示負值。
基于此,將所有LED通用接口的返回值類型定義為aw_err_t,LED控制接口的完整定義詳見表13.1,其對應的類圖詳見圖13.1。
表13.1 LED通用接口(aw_led.h)
圖13.1 LED接口類圖
這些接口都已經在aw_led.h文件中完成了定義,無需用戶再自行定義。上述從接口命名、參數和返回值三個方面詳細闡述了一套接口定義的方法,旨在讓用戶了解接口的由來,加深對接口的理解。實際中,定義接口并不是一件容易的事情,需要盡可能考慮到所有的情況,接口作為與用戶交互的途徑,一旦定義完成,如非必要,都應該避免再對接口進行修改。否則,所有依賴于該接口的應用程序都將受到影響。因此,當前并不建議用戶自定義通用接口,通用接口的定義應由廣州致遠電子有限公司統一規劃、定義、維護和管理。
13.2 接口的實現
作為一種范例,下面以實現LED接口為例,詳細介紹AWorks中實現接口的一般方法。
13.2.1 實現接口初探
在AWorks中,硬件設備和驅動統一由AWBus-lite進行管理,因此,對于LED這一類硬件設備,其實現是屬于AWBus-lite的一部分。LED有4個通用接口函數,其中的aw_led_on()和aw_led_off()接口可以直接基于aw_led_set()接口實現,詳見程序清單13.1。
程序清單13.1 aw_led_on()和aw_led_off()接口的實現
實現接口的核心是實現aw_led_set()和aw_led_toggle()這兩個接口。對于不同的底層硬件設備,LED實際控制方式是不同的,比如,最常見的,通過GPIO直接控制一個LED,簡單范例詳見程序清單13.2。
程序清單13.2 aw_led_set()的實現(GPIO控制LED)
也有可能是通過串口控制一個LED設備。例如,通過發送字符串命令控制LED的狀態,命令格式為:set
程序清單13.3 aw_led_set()的實現(UART控制LED)
總之,底層硬件設備是多種多樣的,不同類型的LED設備對應的控制方式也會不同。
定義通用接口的目的在于屏蔽底層硬件的差異性,即無論底層硬件如何變化,用戶都可以使用通用接口控制LED。顯然,如果直接類似程序清單13.2和程序清單13.3這樣實現一個通用接口,那么隨著LED設備種類的增加,同一個接口的實現代碼將有越來越多不同的版本。
在一個應用程序中,一個接口不能同時具有多種不同的實現,因此,這樣的做法有著非常明顯的缺點:多個不同種類的LED設備不能在一個應用中共存,更換硬件設備,就必須更換通用接口的實現,使用何種設備就加入相應設備的控制代碼進行編譯。 例如,系統中有幾個直接通過GPIO控制的LED,同時也存在幾個通過UART控制的LED,那么,類似程序清單13.2和程序清單13.3這樣直接實現通用接口的方法,就無法組織代碼了,因為不可能同時將程序清單13.2和程序清單13.3所示的代碼加入工程編譯。顯然,需要更好的辦法來解決這個問題。
13.2.2 LED抽象方法
在使用幾種控制方式不同的LED硬件設備時,雖然它們對應的aw_led_set()和aw_led_toggle()接口的具體實現方法并不相同,但它們要實現的功能卻是一樣的,這是它們的共性:均要實現設置LED狀態和翻轉LED狀態的功能。由于一個接口的實現代碼只能有一份,因此,這些功能的實現不能直接作為通用接口的實現代碼。為此,可以在通用接口和具體實現之間增加一個抽象層,以對共性進行抽象,將兩種功能的實現抽象為如下兩個方法:
相對于通用接口來說,抽象方法多了一個p_cookie參數。在面向對象的編程語言中(如C++),對象中的方法都能通過隱式指針p_this訪問對象自身,引用自身的一些私有數據。而在C語言中則需要顯式的聲明,這里的p_cookie就有類似的作用,當前設置為void *類型主要是由于具體對象的類型還并不確定。
為了節省內存空間,同時方便管理,可以將所有抽象方法放在一個結構體中,形成一張虛函數表,比如:
由于LED的實現屬于AWBus-lite的一部分,因此,命名使用"awbl_"作為前綴。這里定義了一個虛函數表,包含了兩個方法,分別用于設置LED的狀態和翻轉LED。針對不同的硬件設備,都可以根據自身特性實現這兩個方法。GPIO控制LED的偽代碼詳見程序清單13.4,UART控制LED的偽代碼詳見程序清單13.5。
程序清單13.4 抽象方法的實現(GPIO控制LED)
程序清單13.5 抽象方法的實現(UART控制LED)
顯然,__g_led_gpio_drv_funcs和__g_led_uart_drv_funcs分別是使用GPIO和UART控制LED的具體實現,它們在形式上是兩個不同的結構體常量,在同一系統中是可以共存的。
13.2.3 抽象的LED服務
當對不同的LED硬件設備抽象了相同的pfn_led_set和pfn_led_toggle方法后,在通用接口aw_led_set()和aw_led_toggle()的實現中,就無需再處理與硬件相關的具體事務,只需要找到相應設備提供的相應方法,然后調用這些具體硬件設備提供的方法即可。
在調用設備提供的方法時,由于方法的第一個參數為p_cookie,p_cookie代表了具體的設備對象,調用方法時,需要傳遞一個p_cookie給下層,用于在具體實現時,訪問設備對象中的具體成員,起到“p_this”的作用。由于在aw_led_set()接口的實現中,并不需要直接操作具體設備,因此,無需知道p_cookie的具體類型,僅需起到一個傳遞的作用:在調用相應的方法時,傳遞給下層驅動使用。
既然要傳遞p_cookie,那么,必然要獲得一個p_cookie并保存下來,顯然,p_cookie代表了具體設備,只能由具體設備提供,同時,抽象方法也是由具體設備提供的,為此,可以將抽象方法和p_cookie定義在一起,形成一個新的類型,以便在具體設備提供的抽象方法的實現時,將p_cookie一并提供,即:
為了便于描述,將其稱之為 “LED服務”。其中包含了由驅動實現的抽象方法和傳遞給驅動函數的p_cookie。其中,p_servfuncs為指向驅動虛函數表的指針,比如,指向__g_led_gpio_drv_funcs或__g_led_uart_drv_funcs,p_cookie為指向具體設備的指針,即傳遞給驅動函數的第一個參數。此時,在aw_led_set()接口的實現中,無需再完成底層硬件相關的操作,僅需調用LED服務中包含的pfn_led_set方法即可,其范例程序詳見程序清單13.6。
程序清單13.6 aw_led_set()實現(1)
程序中,使用了一個全局變量__gp_led_serv指向當前一個有效的LED服務,顯然,其只有在賦值后才能使用,暫不考慮其如何賦值,僅用以展示pfn_led_set方法的調用形式。
實際中,具體的LED設備往往不止一個。比如,使用GPIO控制的LED設備和使用UART控制的LED設備,它們都可以向系統提供LED服務,這就需要系統具有管理多個LED服務的能力。由于LED設備的數目無法確定,可能動態變化,因此,選用單向鏈表進行動態管理。為此,在struct awbl_led_service中增加一個p_next成員,用于指向下一個LED服務。即:
此時,系統中的多個LED服務使用鏈表的形式進行管理。那么,在通用接口的實現中,如何確定具體該使用哪個LED服務呢?在定義通用接口時,使用了ID號區分不同的LED,ID號是唯一的,顯然,某一ID的LED必然屬于某一確定的硬件設備,若一個硬件設備在提供LED服務時,包含了該硬件設備中所有LED的ID號信息,那么,在通用接口的實現中,就可以根據ID找到對應的LED服務,然后使用驅動中提供的方法完成LED的操作。為此,可以在LED服務中再增加一個ID信息,以表示對應硬件設備中所有LED的ID號。
在一個LED硬件設備中,可能包含多個LED,例如,MiniPort-LED擴展板,包含了8個LED,但一般來講,一個LED硬件設備中所有LED的編號是連續分配的,基于此,僅需知道一個硬件設備中LED的起始編號和結束編號,就可以獲得該硬件設備中所有LED對應的編號,例如,一個硬件設備中LED的起始編號為2、結束編號為9,則表示在該硬件設備中,各個LED的編號分別為:2、3、4、5、6、7、8、9,共計8個LED。為此,可以定義一個LED服務信息結構體類型,專門用于提供LED服務相關的信息,例如:
由此可見,在LED服務信息中,當前僅包含起始編號和結束編號兩個信息。LED服務信息是與具體設備相關的,因此,可以在LED服務中新增一個指向LED服務信息的指針,以便在具體設備在提供p_cookie和抽象方法的實現時,將設備支持的LED編號信息一并提供,LED服務的完整定義詳見程序清單13.7。
程序清單13.7 完整的LED服務類型定義(awbl_led.h)
由于在LED服務中新增了LED編號信息,那么,在通用接口的實現中,就可以根據設備提供的LED編號信息,找到id對應的LED服務。基于此,aw_led_set()函數的實現詳見程序清單13.8。
程序清單13.8 aw_led_set()實現(2)
程序中,調用了__led_id_to_serv()函數以獲取ID號對應的LED服務。__led_id_to_serv()函數通過遍歷LED服務鏈表,將id與各個LED服務中的ID信息進行對比,直到找到id對應的LED服務(即id處于該LED服務的起始編號和結束編號之間),具體實現范例詳見程序清單13.9。
程序清單13.9 獲取ID號對應的LED服務
其中,__gp_led_serv_head是一個模塊內部使用的全局變量,初始值為NULL,表示初始時系統中無任何有效的LED服務。同理,可實現aw_led_toggle()接口,詳見程序清單13.10。
程序清單13.10 aw_led_toggle()實現
至此,實現了所有通用接口。顯然,由于當前并不存在任何有效的LED服務,因此,__gp_led_serv_head的值為NULL,致使__led_id_to_serv()的返回值為NULL,最終導致通用接口的返回值始終為-AM_ENODEV。
13.2.4 Method機制
為了使通用接口能夠操作到具體有效的LED,必須通過某種方法,將當前系統中所有LED設備提供的LED服務加入到以__gp_led_serv_head為頭的LED服務鏈表中。
AWbus-lite提供了一種特殊的“Method機制”,其是一種系統上層和硬件底層相互“交流”的一種方式,可用于系統發現各個硬件設備提供的服務。AWBus-lite提供了Method相關的宏,詳見表13.2。
表13.2 Method相關的宏(awbus_lite.h)
1. 定義一個Method類型
AWBL_METHOD_DEF()用于定義一個Method類型,其原型為:
其中,method為定義的Method類型名,string為一個描述字符串,描述字符串僅在定義時對method類型進行描述,可以是任意字符串,其它地方不會被使用到。
Method類型具有唯一性,不可定義兩個相同的Method類型。Method類型可以看作一個“唯一標識”,用于標記某一類操作,在底層驅動的實現中,凡是能夠完成該類操作的設備,都可以使用該“唯一標識”標記一個入口函數,該入口函數即用于完成相應的操作,這樣一來,系統就可以通過該“唯一標識”查找所有被標記的入口函數,并依次調用它們,完成某種特定功能。例如,對于LED,為了獲取當前系統中所有設備提供的LED服務,可以定義一個獲取LED服務的Method類型,范例程序詳見程序清單13.11。
程序清單13.11 定義Method類型范例程序
如此一來,即定義了一個名為awbl_ledserv_get的Method類型,該Method類型即表示了一類操作:獲取LED服務。后續在底層設備驅動的實現中,只要一個設備能夠提供LED服務,則表示系統可以從中獲取到一個LED服務,此時,該驅動就可以提供一個入口函數,用于獲取LED服務,并使用該Method類型對入口函數進行標記。這樣,在系統啟動時,就可以通過查找系統中所有被該Method類型標記的入口函數,然后一一調用它們,以此獲得所有設備提供的LED服務。
2. 定義一個具體的Method對象
定義Method對象的本質就是使用Method類型標記一個入口函數,使系統知道該入口函數可以完成某種特定的功能,以便系統在合適的時機調用。為便于描述,在AWBus-lite中,將使用Method類型標記的入口函數稱之為一個Method對象。AWBus-lite提供了定義Method對象的輔助宏,其原型為:
其中,name為使用AWBL_METHOD_DEF()定義的Method類型名,handler為用于完成某種特定功能的入口函數。例如,定義awbl_ledserv_get類型的目的是獲取LED服務,因此,該類型的Method對象對應的handler應該能夠獲取到一個LED服務。handler的類型為awbl_method_handler_t,其定義如下(awbus_lite.h):
由此可見,awbl_method_handler_t是一個函數指針類型,其指向的函數有兩個形參:p_dev和p_arg,返回值為標準的錯誤號。p_dev指向設備自身,同樣起到一個p_this的作用,該handler運行在哪個設備上,傳入p_dev的值就應該為指向該設備的指針;p_arg為void *類型的參數,其具體類型與該入口函數需要完成的功能相關,如果功能為獲取一個LED服務,p_arg的實際類型就為struct awbl_led_service **,即一個指向LED服務的指針的地址,以便在函數內部改變指向LED服務的指針的值,使其指向設備提供的LED服務,從而完成LED服務的獲取。例如,在GPIO控制LED的設備中,其能夠提供LED服務,則應在對應的驅動中,定義一個具體的Method對象,便于系統得到LED服務。范例詳見程序清單13.12。
程序清單13.12 定義Method對象范例程序
其中,__g_led_gpio_dev_methods為該設備能夠提供的Method對象列表,一個設備提供的Method對象統一存放在一個列表中。該列表的具體使用以及入口函數的具體實現,將在LED驅動的實現中進一步介紹。這里僅用于展示系統上層獲取LED服務的原理。
3. Method對象列表結束標記
在程序清單13.12中,將Method對象定義在了一個列表中,AWBL_METHOD_END用于定義一個特殊的標志,表示Method對象列表的結束。其原型為:
該宏無需傳入任何參數,其僅用于標識一個Method對象列表的結束。例如,GPIO控制的LED設備只能提供一個Method對象,用于系統上層獲取LED服務,那么,在該對象之后,應該使用AWBL_METHOD_END表示列表結束。范例程序詳見程序清單13.13。
程序清單13.13 AWBL_METHOD_END使用范例程序
4. 導入(聲明)一個在外部定義的Method類型
當需要使用一個已定義的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類型相當于一個“唯一標識”,有時候,需要判斷某一Method對象是否為指定的Method類型。為了便于比較判斷,或將“Method類型”作為參數傳遞給其它接口函數,可以通過該宏獲得一個Method類型對應的ID,ID作為一個常量,可以用于比較或參數傳遞。獲取Method類型的ID對應的宏原型為:
其中,method為使用AWBL_METHOD_DEF()定義的Method類型名,返回值為該Method類型的ID,其類型為:awbl_method_id_t,該類型的具體定義用戶無需關心,ID可以用作比較,只要兩個Method類型的ID相同,就表示兩個Method類型是相同的,ID也可以作為參數傳遞給其它接口,以指定一種Method類型。
例如,在AWbus-lite中,提供了一個工具函數,用于查找設備中是否存在指定類型的Method對象,其函數原型為(awbus_lite.h):
其中,p_dev指定了要查找的設備,即在該設備中查找是否存在指定類型的Method對象,method用于指定Method類型的ID。若查找到該ID對應的method對象,則返回該method對象的入口函數,否則,返回NULL。
例如,有一個p_dev指向的設備,要查找其是否能夠提供LED服務,則可以通過該接口實現,范例程序詳見程序清單13.15。
程序清單13.15 AWBL_METHOD_ CALL()使用范例程序
程序中,使用AWBL_METHOD_ CALL()得到Method類型awbl_ledserv_get的ID,然后傳遞給awbl_dev_method_get()函數以查找設備中是否存在相應的Method對象,若存在,則得到了一個有效的入口函數,最后使用該入口函數即可得到一個LED服務。
13.2.5 LED服務鏈表的初始化
通過程序清單13.15所示的一個流程,若一個設備能夠提供LED服務,則可以從中獲取到相應的LED服務。若對每個設備都執行一遍上述流程,并在獲得一個設備提供的LED服務后,就將其添加到以__gp_led_serv_head為頭的LED服務鏈表中,則可以收集到系統中所有的LED服務,完成LED服務鏈表的初始構建。為了便于對所有設備執行某一操作,AWBus-lite提供了一個用于遍歷所有設備的接口,其函數原型為:
其中,pfunc_action表示要在每個設備上執行的操作,p_arg為傳遞給pfunc_action的附加參數,flags為遍歷設備的標志,返回值為標準錯誤號。
pfunc_action的類型為awbl_iterate_func_t,該類型的具體定義如下(awbus_lite.h):
由此可見,awbl_iterate_func_t是一個函數指針類型,其指向的函數有兩個形參:p_dev和p_arg,返回值為標準的錯誤號。p_dev指向當前遍歷到的設備,同樣起到一個p_this的作用,當前遍歷到哪個設備,在哪個設備上運行pfunc_action函數,傳入的p_dev就為指向該設備的指針;p_arg為遍歷時提供的附加參數,其值與調用awbl_dev_iterate()函數時傳入的p_arg參數相同。
flags為遍歷設備的標志,其決定了需要遍歷哪些設備,以及pfunc_action函數的返回值是否能夠終止遍歷過程。可用標志詳見表13.3。
表13.3 遍歷設備標志宏(awbus_lite.h)
其中,AWBL_ITERATE_INSTANCES和AWBL_ITERATE_ORPHANS標志用于指定需要遍歷的設備,即在哪些設備上執行pfunc_action函數。在硬件設備列表中,定義了當前系統中所有的硬件設備,當設備具有與之匹配的驅動時,才能夠變成一個實例,被系統正常使用,而如果一個設備沒有與之匹配的驅動,該設備將變成一個孤兒設備,由于沒有與之匹配的驅動,因此系統暫時無法使用孤兒設備。AWBL_ITERATE_INSTANCES表示表示需要遍歷所有實例,即具有相應驅動的設備。AWBL_ITERATE_ORPHANS表示需要遍歷所有的孤兒設備。若要遍歷所有的實例和孤兒設備,可以使用或運算同時設定這兩個標志。
AWBL_ITERATE_INTRABLE標志用于指定pfunc_action 的返回值是否可以終止遍歷,若設定了該標志,則在某一設備上運行pfunc_action函數的返回值將可以決定是否終止整個遍歷過程:返回值為AW_OK時,不終止遍歷,繼續遍歷其它設備;否則,遍歷過程被終止,不會再繼續遍歷其它設備。若未設定該標志,則遍歷過程不受返回值影響,直到遍歷完所有需要遍歷的設備后結束。
為了獲得所有設備提供的LED服務,需要遍歷所有實例,并在pfunc_action中執行如程序清單13.15所示的流程,并將各個設備提供的LED服務添加到以__gp_led_serv_head為頭的LED服務鏈表中。完整的范例程序詳見程序清單13.16。
程序清單13.16 獲取所有設備提供的LED服務
程序中,由于孤兒設備沒有對應的驅動,無法正常使用,顯然無法提供LED服務,因此僅需遍歷所有實例,遍歷標志設定為了:AWBL_ITERATE_INSTANCES。該程序的目的是完成LED服務鏈表的初始構建,是一種初始化操作,因此,將其入口函數命名為了awbl_led_init(),若需使用LED,則應確保在系統啟動時,該函數被自動調用。通常情況下,并不需要由用戶手動調用該函數,而是將該函數的調用放在模板工程下的aw_prj_config.c文件中,具體位于aw_prj_early_init()函數中,該函數在系統啟動時會被自動調用,從而使系統在啟動時自動調用awbl_led_init()函數,詳見詳見程序清單13.17。
程序清單13.17 awbl_led_init()在系統啟動時被自動調用的原理
在aw_prj_params.h工程配置文件中,只要使能了某一LED設備,比如,AW_DEV_GPIO_LED,則表示要使用LED,此時,將自動完成AW_COM_AWBL_LED的定義,以此確保當使用LED時,awbl_led_init()會在系統啟動過程中被自動調用。核心的原理性程序詳見程序清單13.18。
程序清單13.18 自動定義AW_COM_AWBL_LED宏的原理(aw_prj_params.h)
至此,完成了LED服務鏈表的初始化,若系統中存在LED服務,則鏈表將不為空,在LED通用接口的實現中,只要傳入的id正確,__led_id_to_serv()的返回值就不為NULL,進而返回一個有效的LED服務,接著,通過LED服務中實現的抽象方法,即可完成LED相關的操作,例如,設置LED狀態、翻轉LED狀態等。
-
接口
+關注
關注
33文章
8526瀏覽量
150863 -
總線
+關注
關注
10文章
2869瀏覽量
87997 -
周立功
+關注
關注
38文章
130瀏覽量
37589
原文標題:AWorks軟件篇 — 深入理解 AWbus-lite(接口的定義和實現)
文章出處:【微信號:Zlgmcu7890,微信公眾號:周立功單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論