rtthread內核介紹


以下流程主要取自RT-Rhread官方文檔

RT-Thread啟動流程

  RT-Thread支持多種平台和多種編譯器,而rtthread_startup()函數是RT-Thread規定的同意啟動入口。一般執行順序是:系統先從啟動文件開始運行,然后進入RT-Thread的啟動rtthread_startup(),最后進入用戶入口main(),如下圖所示:

以MDK-ARM為例,用戶程序入口為main()函數,位於main.c文件中。系統啟動后先從匯編代碼startup_stm32f103xe.s開始運行,然后跳轉到C代碼,進行RT-Thread系統啟動,最后進入用戶程序入口main()。

為了在進入main()之前完成RT-Thread系統功能初始化,我們使用了MDK的擴展功能$Sub$和$Super$。可以給main添加$$Sub$$main,這個$$Sub$$main可以先調用一些要補充在main之前的功能函數(這里添加RT-Tread系統啟動,進行系統一系列初始化),再調用$Super$$main轉到main()函數執行,這樣可以讓用戶不用去管main()之前的系統初始化操作。

RT-Thread程序內存分布

一般MCU包含的存儲空間有:片內Flash與片內RAM,RAM相當於內存,Flash相當於硬盤。編譯器會將一個程序分類為好幾個部分,分別存儲再MCU不同的存儲區。

Keil工程再編譯完之后,會有相應的程序所占用的空間提示信息,其中:

1)Code:代碼段,存放程序的代碼部分;
2)RO-data:只讀數據段,存放程序中定義的常量;
3)RW-data:讀寫數據段,存放初始化為非0值的全局變量;
4)ZI-data:0數據段,存放未初始化的全局變量及初始化為0的變量;

編譯完工程會生成一個.map的文件,該文件說明了各個函數占用的尺寸和地址,再文件的最后幾行也說明了上面幾個字段的關系:
1)RO Size包含了Code及RO-data,表示程序占用Flash空間的大小;
2)RW Size包含了RW-data及ZI-data,表示運行時占用的RAM的大小;
3)ROM Size包含了Code、RO Data已經RW Data,表示燒寫程序所占用的Flash空間的大小;

程序運行之前,需要有文件實體被燒錄到STM32的Flash中,一般是bin或者hex文件,該被燒錄文件成為可執行映像文件。如下圖所示,是可執行映像文件燒錄到STM32后的內存分布,它包含RO段和RW段兩個部分:其中RO段中保存了Code、RO-data的數據,RW段保存了RW-data的數據,由於ZI-data都是0,所以未包含再映像文件中。

STM32再上電之后默認從Flash啟動,啟動之后會將RW段中RW-data(初始化為全局變量)搬運到RAM中,但不會搬運RO段,即CPU的執行代碼從Flash中讀取,另外根據編譯器給出的ZI地址和大小分配出ZI段,並將RAM區域清零。

其中動態內存堆為未使用的RAM空間,應用程序申請和釋放的內存塊來自該空間。

RT-Thread自動初始化機制

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

再系統啟動流程圖中,有兩個函數: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_BORAD_EXPORT(fn)聲明的初始化函數表,並調用各個函數 。

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

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM