RT-Thread 自動初始化機制

自動初始化機制是指初始化函數不需要被顯式調用,只需要在函數定義處通過宏定義的方式進行申明,就會在系統啓動過程中被執行。

例如在串口驅動中調用一個宏定義告知系統初始化需要調用的函數,代碼如下:

int rt_hw_usart_init(void)  /* 串口初始化函數 */
{
     ... ...
     /* 註冊串口 1 設備 */
     rt_hw_serial_register(&serial1, "uart1",
                        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                        uart);
     return 0;
}
INIT_BOARD_EXPORT(rt_hw_usart_init);    /* 使用組件自動初始化機制 */

示例代碼最後的 INIT_BOARD_EXPORT(rt_hw_usart_init) 表示使用自動初始化功能,按照這種方式,rt_hw_usart_init() 函數就會被系統自動調用,那麼它是在哪裏被調用的呢?

在系統啓動流程圖中,有兩個函數:rt_components_board_init() 與 rt_components_init(),其後的帶底色方框內部的函數表示被自動初始化的函數,其中:

  1. “board init functions” 爲所有通過 INIT_BOARD_EXPORT(fn) 申明的初始化函數。

  2. “pre-initialization functions” 爲所有通過 INIT_PREV_EXPORT(fn)申明的初始化函數。

  3. “device init functions” 爲所有通過 INIT_DEVICE_EXPORT(fn) 申明的初始化函數。

  4. “components init functions” 爲所有通過 INIT_COMPONENT_EXPORT(fn)申明的初始化函數。

  5. “enviroment init functions” 爲所有通過 INIT_ENV_EXPORT(fn) 申明的初始化函數。

  6. “application init functions” 爲所有通過 INIT_APP_EXPORT(fn)申明的初始化函數。

rt_components_board_init() 函數執行的比較早,主要初始化相關硬件環境,執行這個函數時將會遍歷通過 INIT_BOARD_EXPORT(fn) 申明的初始化函數表,並調用各個函數。

rt_components_init() 函數會在操作系統運行起來之後創建的 main 線程裏被調用執行,這個時候硬件環境和操作系統已經初始化完成,可以執行應用相關代碼。rt_components_init() 函數會遍歷通過剩下的其他幾個宏申明的初始化函數表。

RT-Thread 的自動初始化機制使用了自定義 RTI 符號段,將需要在啓動時進行初始化的函數指針放到了該段中,形成一張初始化函數表,在系統啓動過程中會遍歷該表,並調用表中的函數,達到自動初始化的目的。

用來實現自動初始化功能的宏接口定義詳細描述如下表所示:

初始化順序 宏接口 描述
1 INIT_BOARD_EXPORT(fn) 非常早期的初始化,此時調度器還未啓動
2 INIT_PREV_EXPORT(fn) 主要是用於純軟件的初始化、沒有太多依賴的函數
3 INIT_DEVICE_EXPORT(fn) 外設驅動初始化相關,比如網卡設備
4 INIT_COMPONENT_EXPORT(fn) 組件初始化,比如文件系統或者 LWIP
5 INIT_ENV_EXPORT(fn) 系統環境初始化,比如掛載文件系統
6 INIT_APP_EXPORT(fn) 應用初始化,比如 GUI 應用

初始化函數主動通過這些宏接口進行申明,如 INIT_BOARD_EXPORT(rt_hw_usart_init),鏈接器會自動收集所有被申明的初始化函數,放到 RTI 符號段中,該符號段位於內存分佈的 RO 段中,該 RTI 符號段中的所有函數在系統初始化時會被自動調用。

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