如何快速理解一個全新的嵌入式操作系統(續)

上一篇《如何快速理解一個全新的嵌入式操作系統》我們已經分析瞭如何快速理解OSAL的任務調度和任務間通信(其實OSAL只是酷似多任務操作系統的單任務系統),再理解好OASL的消息產生和處理過程,我們就能夠進行快速開發了。

一、消息的來源

嵌入式系統的消息包括兩種,一是系統消息,包括低電、熱插拔等,由系統進程去處理;二是用戶消息,包括Timer、按鍵、串口、繪圖等消息,由各應用進程進行處理。對於TI CC254x的OSAL,我們理解好Timer、key、UART就已足夠。

二、HAL

OSAL向用戶提供HAL硬件抽象層,對CC254x的所支持的硬件模塊進行了封裝抽象,如timer、key、UART、LED、LCD、flash、ADC等等,並向用戶提供硬件模塊的操作接口。

CC254x是低功耗藍牙集成芯片,用戶的產品和電路設計一般都會參考官方的典型電路,而OSAL爲官方針對典型電路所設計的系統庫和接口,用戶的代碼編程就只需要按照其提供的HAL接口進行調用就可以實現功能,而不需要通過GPIO級別的驅動編程來實現模塊的功能。

針對CC254x的編程是應用編程,關注的是HAL接口,可以認爲是基於硬件功能的API接口,而且電路的外設的功能也相對固定,如LED、LCD、UART所使用的pin腳都是相對固定的,因此調用簡單的HAL層接口即可實現功能;而驅動編程則是針對SOC片上資源來進行開發,需要根據SOC的datasheet明確的物理地址資源進行訪問和控制,並向用戶提供API接口。從兩者的區別可以理解HAL硬件抽象層的含義。當然,透傳理解SOC datasheet也有助於HAL接口編程。

三、Timer

對於Timer定時器接口,一般是設置定時器、編寫定時器時間到達時的回調函數。而定時器模塊的初始化函數一般由系統初始化完成。

OSAL對於Timer的HAL層代碼對用戶並不透明,我們可以理解Timer的HAL層是設置Timer模塊的硬件相關操作,並且實現了Timer中斷時的服務處理過程。OSAL的Timer的封裝接口實際上是在HAL層的基礎進行再次封裝。其主要提供的接口如下:

uint8osal_start_timerEx( uint8 taskID, uint16 event_id, uint32 timeout_value )

taskID標識哪個目標任務來處理這個定時到達消息,即當定時完成時,定時器中斷服務器函數會往這個目標任務的taskEvents[taskID]寫入event_id這個消息;event_id可以由用戶自定義;timeout_value是定時時間,1毫秒爲單位。

可見這個定時接口並沒有設置定時完成時的回調函數,而是在定時完成時向這個目標任務發送一個事件。而在目標任務的執行過程中要檢測這個事件並執行相應的處理。

四、UART

       UARTHAL層代碼對用戶是透明的,對於用戶編程來說,最重要的就是串口的初始化(波特率)、串口輸入、串口輸出。

1.     串口初始化

voidNPI_InitTransport( npiCBack_t npiCBack )

串口的初始化並沒有帶taskId這個參數,可見其是一個全局的系統級的接口。串口的使用一般是使用中斷串口輸入,非中斷直接串口輸出。該函數裏面設置波特率是115200.

npiCBack是串口HAL提供給用戶的一個回調函數,即在串口中斷時會調用該回調函數。而串口中斷有以下幾種事件:

一般我們都會在該回調函數中實現串口接收,如實現串口透傳模式。回調接口聲明如下:

typedefvoid (*npiCBack_t) ( uint8 port, uint8 event )

       port是UART0或者UART1,而event即是串口中斷事件。

2.     串口輸入

uint16NPI_ReadTransport( uint8 *buf, uint16 len )

3.     串口輸出

uint16NPI_WriteTransport( uint8 *buf, uint16 len )

從這些接口來看其前綴是NPI,真實的意義是Network Processor Interface (NPI),表示所謂的網絡傳輸層。其實只是更高一層的數據輸入輸出罷了。NPI的底層可以是UART、SPI或者USB等等。我們這裏默認是使用UART。

五、按鍵消息來源和處理

1. 代碼理解前的思考

1)按鍵消息按理是跟應用相關的,因此其必然是跟某個taskId綁定。在這種簡單的嵌入式系統中,一般是由一個稱爲UI的任務來統一處理按鍵的消息。

2)按照上一篇文章和上一節Timer的分析,OSAL的設計是將事件event_id發往目標task,即設置taskEvents[tasked]。我們可以想象在按鍵中斷(或者按鍵輪詢)時檢測到按鍵會往目標task發一個按鍵事件。但是,我們再細想,發一個KEY事件夠了嗎?很明顯taskEvents的元素纔是16bit,每個bit表示一個事件,最多隻能代表16種事件,就算這16事件都用來表示不同的按鍵,也顯得不夠。因爲系統可能有更多的按鍵啊,如果這樣設計擴展性就太差了。事實上,它只是發了一個KEY_CHANGE事件,而鍵值是以MSG消息的形式發到系統的消息隊列,而該消息也會帶上目標taskId的標識。

3)以上兩點是OSAL的KEY處理機制。對於用戶快速開發,則需要知曉如何增加一個按鍵,或者改變一個按鍵對應的GPIO;處理按鍵的過程在哪裏實現?

帶着以上問題,我們從頭到尾跟蹤一次KEY處理的過程。OSAL對KEY的處理機制有點繞,但封裝得挺有意思的。

對Key處理機制真正的理解過程應該是倒序的,即從按鍵的處理一步一步往前推,在現場教學時,對着代碼反跟蹤能夠更加體現本文的方法論。爲了表述更加有條理性,這裏就從頭到尾正序闡述。

2. 初始化

       1)main->HalDriverInit->HalKeyInit

 

2)main->InitBoard( OB_READY )

OnboardKeyIntEnable= HAL_KEY_INTERRUPT_ENABLE;

HalKeyConfig(OnboardKeyIntEnable, OnBoard_KeyCallback);

 

相關的代碼在hal_keys.c和hal_keys.h,若要增加按鍵或者修改按鍵設置即修改這裏。

OnBoard_KeyCallback是按鍵中斷的回調函數。我們在下一步再展開其實現過程,現在跟蹤在哪裏會調用這個回調。我們從中斷的源頭開始跟蹤。

3. 中斷的執行過程

 

4.     HAL層任務的處理過程

 

pHalKeyProcessFunction即是之前在HalKeyConfig接口中設置的OnBoard_KeyCallback,繼續跟蹤這個函數的實現:

這個 registeredKeysTaskID是什麼,就是處理按鍵消息的任務Id。在哪裏被初始化呢?

5.     按鍵處理任務的初始化

main-> osal_init_system-> osalInitTasks-> SimpleBLEPeripheral_Init

-> RegisterForKeys( simpleBLEPeripheral_TaskID )

即在這個函數裏面將simpleBLEPeripheral_TaskID賦值給registeredKeysTaskID,即SimpleBLEPeripheral對應的任務來處理這個消息。

6.     按鍵的處理

 

用戶添加的按鍵處理即在simpleBLEPeripheral_HandleKeys函數中。

請一步步地印證第一點,代碼理解前的思考。

 

節日快樂!

更多原創嵌入式Linux,IOT、藍牙wifi開發技術分享請關注微信公衆號:嵌入式企鵝圈

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章