RTT學習之啟動流程


  1. 總結RT-Thread的啟動流程。
  2. 非運行時與運行時的image文件分別是什么樣的,請畫下來。是誰將 RW 段中的  RW-data(初始化的全局變量)搬運到 RAM 中?
  3. MDK環境下各種數據段存儲的什么數據?
  4. 在RT-Thread啟動時,關了中斷,那么在什么時候開啟的中斷?
  5. 總結自動初始化原理。
  6. 總結BSP制作過程。

1RT-Thread啟動流程

 

 

 

 

 

 

這部分啟動代碼,大致可以分為四個部分:

(1) 初始化與系統相關的硬件;

(2) 初始化系統內核對象,例如定時器、調度器、信號;

(3) 創建 main 線程,在 main 線程中對各類模塊依次進行初始化;

(4) 初始化定時器線程、空閑線程,並啟動調度器。

啟動流程中藍色部分是自動初始化的數據段,使用自動初始化宏導出的函數放置到相應的數據段,在啟動流程中對函   數進行遍歷初始化。2、加載時地址與運行時地址映射

image文件

 

 

 

 

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

分散裝載配置文件里會有配置,關於code的地址,有兩個設置,一個是存儲地址(這個地址配置的是燒寫器把代碼  段寫到flashrom的何處),一個是裝載運行地址,也就是你程序在什么地方運行

【如果想要深入了解的話,可以看看arm的連接器手冊,或者是《ARM體系結構與編程》中也講到了】

 

3MDK環境下各種數據段存儲的什么數據?

code:代碼段,存放程序

RO:只讀數據段,存放程序中定義的常量RW:讀寫數據段,存放非0全局變量

ZI:0數據段,存放未初始化的全局變量與初始化為0的變量

MDK 在編譯完成之后

Total RO Size (Code + RO Data) 53668 ( 52.41kB) Total RW Size (RW Data + ZI Data) 2728 ( 2.66kB)

Total ROM Size (Code + RO Data + RW Data) 53780 ( 52.52kB)

1) RO Size 包含了 Code  RO-data,表示程序占用 Flash 空間的大小;

2) RW Size 包含了 RW-data  ZI-data,表示運行時占用的 RAM 的大小;

3) ROM Size 包含了 Code、RO Data 以及 RW Data,表示燒寫程序所占用的 Flash 空間的大小;

4、在RT-Thread啟動時,關了中斷,那么在什么時候開啟的中斷?

在啟動調度器,切換到第一個線程時開啟的中斷【直接使用CPSIE I 開了中斷的】。代碼詳見:

rt_system_scheduler_start() rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp);

 

 

 5、總結自動初始化原理。

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 符號段中的所有函數在系統初始化時會被自動調用。

原理:

在rtdef.h中,使用SECTION(x)定義: 

#define SECTION(x)  attribute ((section(x)))

     attribute ((section("name"))):將作用的函數或數據放入指定名為"name"的輸入段中。(在不同的編譯器中實現的方式也有所不同。)

將SECTION(".rti_fn."level)使用 INIT_EXPORT(fn, level) 這個宏進行定義,fn是函數  

#define INIT_EXPORT(fn, level)  RT_USED const init_fn_t rt_init_##fn SECTION(".rti_fn."level) = fn

分段:

 compnents.c中:

static int rti_start(void)
{
return 0;
}
INIT_EXPORT(rti_start, "0");


static int rti_board_start(void)
{
return 0;
}
INIT_EXPORT(rti_board_start, "0.end");


static int rti_board_end(void)
{
return 0;
}
INIT_EXPORT(rti_board_end, "1.end");


static int rti_end(void)
{
return 0;
}
INIT_EXPORT(rti_end, "6.end");

所以就有: 

段名

函數指針/

.rti_fn.0

    rt_init_rti_start

.rti_fn.0.end

    rt_init_rti_board_start

.rti_fn.1

INIT_BOARD_EXPORT(fn)

.rti_fn.1.end

    rt_init_rti_board_end

.rti_fn.2

INIT_PREV_EXPORT(fn)

.rti_fn.3

INIT_DEVICE_EXPORT(fn)

.rti_fn.4

INIT_COMPONENT_EXPORT(fn)

.rti_fn.5

INIT_ENV_EXPORT(fn)

.rti_fn.6

INIT_APP_EXPORT(fn)

.rti_fn.6.end

    rt_init_rti_end

非調試模式下rt_components_board_init():for循環會遍歷位於 rt_init_rti_board_start 到

     rt_init_rti_board_end 之間保存的函數指針,然后依次執行這些函數

void rt_components_board_init(void)
{
const init_fn_t *fn_ptr;


for (fn_ptr = & rt_init_rti_board_start; fn_ptr < & rt_init_rti_board_end; fn_ptr++)
{
(*fn_ptr)();
}
#endif
}

非調試模式下rt_components_init():for循環會遍歷位於  rt_init_rti_board_end 到  rt_init_rti_end 之間保存的函數指針,然后依次執行這些函數

void rt_components_init(void)
{
const init_fn_t *fn_ptr;


for (fn_ptr = & rt_init_rti_board_end; fn_ptr < & rt_init_rti_end; fn_ptr ++)
{
(*fn_ptr)();
}
#endif
}

舉例:

main函數中添加了函數pin_beep_sample(),並使用INIT_APP_EXPORT()進行自動初始化。  

INIT_APP_EXPORT(pin_beep_sample);

那么,展開為:

INIT_APP_EXPORT(pin_beep_sample) INIT_EXPORT(pin_beep_sample, "6")

也就是  

const init_fn_t rt_init_pin_beep_sample SECTION(".rti_fn.""6") = pin_beep_sample

表示把函數pin_beep_sample的地址賦值給常量函數指針 rt_init_pin_beep_sample,然后放入名稱為".rti_fn.6"的數據段中。(其中init_fn_t是一個函數指針類型,原型為typedef int (*init_fn_t)(void) 。)

在編譯后的.map文件中可以查看到:

Symbol Name Value Ov Type Size Object(Section)

 

  


免責聲明!

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



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