<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                -基于TI CC254X OSAL的分析 當工具鏈配置完成后,SourceInsight向你展示一份源碼工程,不借助百度和開發文檔,能否在一兩個小時內理解源碼的組成框架和接口,進行快速開發? 上一篇《[如何快速理解一個全新的嵌入式操作系統](http://blog.csdn.net/yueqian_scut/article/details/48781937)》我們已經分析了如何快速理解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提供給用戶的一個回調函數,即在串口中斷時會調用該回調函數。而串口中斷有以下幾種事件: ![](https://box.kancloud.cn/2016-01-12_5694d4a2aefa5.jpg) 一般我們都會在該回調函數中實現串口接收,如實現串口透傳模式。回調接口聲明如下: 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 ![](https://box.kancloud.cn/2016-01-12_5694d4a2bdf87.jpg) 2)main->InitBoard( OB_READY ) OnboardKeyIntEnable= HAL_KEY_INTERRUPT_ENABLE; HalKeyConfig(OnboardKeyIntEnable, OnBoard_KeyCallback); ![](https://box.kancloud.cn/2016-01-12_5694d4a2d36e1.jpg) 相關的代碼在hal_keys.c和hal_keys.h,若要增加按鍵或者修改按鍵設置即修改這里。 OnBoard_KeyCallback是按鍵中斷的回調函數。我們在下一步再展開其實現過程,現在跟蹤在哪里會調用這個回調。我們從中斷的源頭開始跟蹤。 **3. 中斷的執行過程** ![](https://box.kancloud.cn/2016-01-12_5694d4a2e440b.jpg) **4.HAL層任務的處理過程** ![](https://box.kancloud.cn/2016-01-12_5694d4a302f16.jpg) pHalKeyProcessFunction即是之前在HalKeyConfig接口中設置的OnBoard_KeyCallback,繼續跟蹤這個函數的實現: ![](https://box.kancloud.cn/2016-01-12_5694d4a31aba4.jpg) 這個 registeredKeysTaskID是什么,就是處理按鍵消息的任務Id。在哪里被初始化呢? **5.按鍵處理任務的初始化** main-> osal_init_system-> osalInitTasks-> SimpleBLEPeripheral_Init -> RegisterForKeys( simpleBLEPeripheral_TaskID ) 即在這個函數里面將simpleBLEPeripheral_TaskID賦值給registeredKeysTaskID,即SimpleBLEPeripheral對應的任務來處理這個消息。 **6.按鍵的處理** ![](https://box.kancloud.cn/2016-01-12_5694d4a3313be.jpg) 用戶添加的按鍵處理即在simpleBLEPeripheral_HandleKeys函數中。 請一步步地印證第一點,代碼理解前的思考。 節日快樂! 更多原創嵌入式Linux,IOT、藍牙wifi開發技術分享請關注微信公眾號:嵌入式企鵝圈 ![](https://box.kancloud.cn/2016-01-12_5694d4a143a64.jpg)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看