在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文詳解RT-Thread自動(dòng)初始化

RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 來(lái)源:陳翠 ? 2019-07-21 10:17 ? 次閱讀

一、前言

在學(xué)RT-Thread時(shí),經(jīng)常能聽(tīng)到這個(gè)詞:自動(dòng)初始化。用起來(lái)也非常容易,一個(gè)宏就解決了,但是原理是什么呢?官網(wǎng)文檔提及到了,

(他們的文檔在這里:https://www.rt-thread.org/document/site/programming-manual/basic/basic/#rt-thread_3),但是寫(xiě)的只是概念層面上的,看完后會(huì)使用但原理還是不太清楚。之前研究過(guò),今天把它總結(jié)下,寫(xiě)出來(lái)分享。

1.1、一般情況的初始化調(diào)用

一般情況下,系統(tǒng)中的初始化會(huì)這樣做,應(yīng)該再熟悉不過(guò)了:

1//偽代碼 2 3voidmain(void) 4{ 5uart_init(); 6led_init(); 7... 8 910while(1)11{12//func113//func214}15}

這樣的顯式調(diào)用初始化函數(shù),有時(shí)可能多達(dá) 十幾到幾十 個(gè),看起來(lái)非常非常繁雜。但是好像沒(méi)啥問(wèn)題,因?yàn)橐呀?jīng)看習(xí)慣了。

1.2 使用自動(dòng)初始化后

舉例一個(gè)自動(dòng)初始化的用法如下:

1//這是led.c文件23voidled_init(void)4{5//省略6}7INIT_APP_EXPORT(led_init)1//這是main.c文件2intmain(void)3{45}

這樣,使用一個(gè)宏,初始化函數(shù)就會(huì)被自動(dòng)初始化,不用在其他地方顯式調(diào)用 led_init() 。代碼瞬間清爽很多。

二、引入

當(dāng)然也不用擔(dān)心一個(gè)初始化必須在另一個(gè)初始化之前的問(wèn)題,因?yàn)檫@里有6個(gè)自動(dòng)初始化等級(jí)可供選擇。

我摳了一張RT-Thread官網(wǎng)文檔的圖,該圖是RT-Thread代碼的啟動(dòng)流程圖,該圖中的藍(lán)色方框部分就是自動(dòng)初始化的6個(gè)等級(jí)以及初始化的先后順序。從圖中可以看出這6部分的初始化是由函數(shù) rt_components_board_init() 與 rt_components_init() 完成的。

在一開(kāi)始的例子中, INIT_APP_EXPORT(led_init) 就位于最后一個(gè)方框的位置,屬于applications init functions。

那么其他等級(jí)分別對(duì)應(yīng)什么宏進(jìn)行初始化的?看下面的表格:

三、自動(dòng)初始化原理

3.1 6個(gè)自動(dòng)初始化宏的定義

查看源碼,這 6 個(gè)宏定義如下:( 不同的段:1 2 3 4 5 6 )

1/*boardinitroutineswillbecalledinboard_init()function*/ 2#defineINIT_BOARD_EXPORT(fn)INIT_EXPORT(fn,"1") 3 4/*pre/device/component/env/appinitroutineswillbecalledininit_thread*/ 5/*componentspre-initialization(puresoftwareinitilization)*/ 6#defineINIT_PREV_EXPORT(fn)INIT_EXPORT(fn,"2") 7/*deviceinitialization*/ 8#defineINIT_DEVICE_EXPORT(fn)INIT_EXPORT(fn,"3") 9/*componentsinitialization(dfs,lwip,...)*/10#defineINIT_COMPONENT_EXPORT(fn)INIT_EXPORT(fn,"4")11/*environmentinitialization(mountdisk,...)*/12#defineINIT_ENV_EXPORT(fn)INIT_EXPORT(fn,"5")13/*appliationinitialization(rtguiapplicationetc...)*/14#defineINIT_APP_EXPORT(fn)INIT_EXPORT(fn,"6")

INIT_EXPORT(fn, level) 表示這個(gè)函數(shù) fn 現(xiàn)在屬于哪個(gè)初始化 level 段, 由 SECTION(".rti_fn."level) 進(jìn)行定義。

1#defineINIT_EXPORT(fn,level)2RT_USEDconstinit_fn_t__rt_init_##fnSECTION(".rti_fn."level)=fn

而 SECTION(x) 是:

1#defineSECTION(x)__attribute__((section(x)))

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

以上就是整個(gè)的宏定義作用就是將函數(shù) fn 的地址賦給一個(gè) __rt_init_fn 的指針,然后放入相應(yīng) level 的數(shù)據(jù)段中。所以函數(shù)使用自動(dòng)初始化宏導(dǎo)出后,這些數(shù)據(jù)段中就會(huì)存儲(chǔ)指向各個(gè)初始化函數(shù)的指針。

舉例:INIT_APP_EXPORT(pin_beep_sample);

1//函數(shù)pin_beep_sample(),使用INIT_APP_EXPORT()進(jìn)行自動(dòng)初始化。 2 3INIT_APP_EXPORT(pin_beep_sample); 4=INIT_EXPORT(pin_beep_sample,"6") 5=constinit_fn_t__rt_init_pin_beep_sampleSECTION(".rti_fn.""6")=pin_beep_sample 6 7/* 8表示把函數(shù)pin_beep_sample的地址賦值給常量函數(shù)指針__rt_init_pin_beep_sample, 9然后放入名稱(chēng)為".rti_fn.6"的數(shù)據(jù)段中。10(其中init_fn_t是一個(gè)函數(shù)指針類(lèi)型,原型為typedef int (*init_fn_t)(void)。)11*/

表示把函數(shù) pin_beep_sample 的地址賦值給常量函數(shù)指針 __rt_init_pin_beep_sample,然后放入名稱(chēng)為 ".rti_fn.6" 的數(shù)據(jù)段中。( 其中 init_fn_t 是一個(gè)函數(shù)指針類(lèi)型,原型為 typedef int (*init_fn_t)(void)。)

注意被自動(dòng)初始化的函數(shù)類(lèi)型為:int (*init_fn_t)(void) ,無(wú)參,int 返回。

3.2 自動(dòng)初始化過(guò)程

那么上面提到,在啟動(dòng)流程中,調(diào)用了兩個(gè)函數(shù) rt_components_board_init() 與 rt_components_init() 就完成了6部分的初始化。從啟動(dòng)流程圖中可以看出:rt_components_board_init() 完成了第 1 段, rt_components_init() 完成了第2 到第6 段。

說(shuō)明:rt_components_board_init()主要board板級(jí)的初始化,調(diào)度器還未啟動(dòng),是在系統(tǒng)起來(lái)之前做的初始化。所以在使用board級(jí)別的初始化時(shí)不要使用系統(tǒng)API,如rt_thread_delay()等。rt_components_init()主要是一些組件的初始化及應(yīng)用初始化,是在main線程中完成的,當(dāng)調(diào)度器啟動(dòng)之后,系統(tǒng)啟動(dòng)開(kāi)始運(yùn)行main線程時(shí)才會(huì)進(jìn)行的初始化。是線程的運(yùn)行環(huán)境。

3.2.1、兩個(gè)函數(shù)的實(shí)現(xiàn)

1、第一個(gè)函數(shù) rt_components_board_init() 的實(shí)現(xiàn):

1voidrt_components_board_init(void) 2{ 3constinit_fn_t*fn_ptr; 4 5for(fn_ptr=&__rt_init_rti_board_start;fn_ptr

非調(diào)試模式下rt_components_board_init():for循環(huán)會(huì)遍歷位于__rt_init_rti_board_start 到 __rt_init_rti_board_end 之間保存的函數(shù)指針,然后依次執(zhí)行這些函數(shù)。

2、第二個(gè)函數(shù) rt_components_init() 的實(shí)現(xiàn):

1voidrt_components_init(void) 2{ 3constinit_fn_t*fn_ptr; 4 5for(fn_ptr=&__rt_init_rti_board_end;fn_ptr

非調(diào)試模式下rt_components_init():for循環(huán)會(huì)遍歷位于__rt_init_rti_board_end 到 __rt_init_rti_end 之間保存的函數(shù)指針,然后依次執(zhí)行這些函數(shù) 。

那么 __rt_init_rti_board_start、__rt_init_rti_board_end、__rt_init_rti_end 是啥?

3.2.2 劃分

在系統(tǒng)中,定義了這幾個(gè)空函數(shù):rti_start、rti_board_start、rti_board_end、rti_end。不同的段:0、 0.end 、 1.end 、6.end

1staticintrti_start(void) 2{ 3return0; 4} 5INIT_EXPORT(rti_start,"0"); 6 7staticintrti_board_start(void) 8{ 9return0;10}11INIT_EXPORT(rti_board_start,"0.end");1213staticintrti_board_end(void)14{15return0;16}17INIT_EXPORT(rti_board_end,"1.end");1819staticintrti_end(void)20{21return0;22}23INIT_EXPORT(rti_end,"6.end");

這幾個(gè)函數(shù)的導(dǎo)出,加上上面 6 個(gè)初始化宏的導(dǎo)出,就有了這樣一個(gè)表格:

可以看出,這4個(gè)空函數(shù)所導(dǎo)出的段中間,包含著這6個(gè)初始化宏定義的段,而這6個(gè)段中分別包含著各自宏導(dǎo)出函數(shù)時(shí)的函數(shù)指針。

rt_components_board_init() 完成了第 1 段, rt_components_init() 完成了第2 到第6 段。

1、rt_components_board_init() 完成了第 1 段,也就是初始化了由INIT_BOARD_EXPORT(fn) 的初始化的所有函數(shù),也就是__rt_init_rti_board_start 到 __rt_init_rti_board_end 之間的函數(shù)指針。

2、rt_components_init() 完成了第2 到第6 段,也就是按順序初始化了由 INIT_PREV_EXPORT(fn) 到 INIT_DEVICE_EXPORT(fn) 到 INIT_COMPONENT_EXPORT(fn)、 INIT_ENV_EXPORT(fn)、 INIT_APP_EXPORT(fn)初始化的所有函數(shù),也就是從 __rt_init_rti_board_end 到 __rt_init_rti_end 之間的函數(shù)指針。

所以,當(dāng)你使用自動(dòng)初始化導(dǎo)出宏 去初始化一個(gè)函數(shù)時(shí),是由系統(tǒng)中的這兩個(gè)函數(shù)進(jìn)行遍歷函數(shù)指針執(zhí)行的。

3.2.3、示例

還是上面 INIT_APP_EXPORT(pin_beep_sample); 的例子。

舉例:INIT_APP_EXPORT(pin_beep_sample);

1//函數(shù)pin_beep_sample(),使用INIT_APP_EXPORT()進(jìn)行自動(dòng)初始化。 2 3INIT_APP_EXPORT(pin_beep_sample); 4=INIT_EXPORT(pin_beep_sample,"6") 5=constinit_fn_t__rt_init_pin_beep_sampleSECTION(".rti_fn.""6")=pin_beep_sample 6 7/* 8表示把函數(shù)pin_beep_sample的地址賦值給常量函數(shù)指針__rt_init_pin_beep_sample, 9然后放入名稱(chēng)為".rti_fn.6"的數(shù)據(jù)段中。10(其中init_fn_t是一個(gè)函數(shù)指針類(lèi)型,原型為typedef int (*init_fn_t)(void)。)11*/

表示把函數(shù) pin_beep_sample 的地址賦值給常量函數(shù)指針 __rt_init_pin_beep_sample,然后放入名稱(chēng)為 ".rti_fn.6" 的數(shù)據(jù)段中。( 其中 init_fn_t 是一個(gè)函數(shù)指針類(lèi)型,原型為 typedef int (*init_fn_t)(void)。)

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

常量函數(shù)指針 __rt_init_pin_beep_sample 位于 .rti_fn.6 段中。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 初始化
    +關(guān)注

    關(guān)注

    0

    文章

    50

    瀏覽量

    11953
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1305

    瀏覽量

    40386

原文標(biāo)題:RT-Thread 自動(dòng)初始化詳解

文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Thread自動(dòng)初始化詳解

    我們知道,在寫(xiě)裸機(jī)程序時(shí),當(dāng)我們完成硬件初始化后,就需要在主函數(shù)中進(jìn)行調(diào)用。當(dāng)我們使用RT-Thread后,完全不需要這樣做了,我們可以將硬件等自動(dòng)初始化
    的頭像 發(fā)表于 06-25 21:38 ?1.1w次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>自動(dòng)</b><b class='flag-5'>初始化</b><b class='flag-5'>詳解</b>

    RT-Thread qemu mps2-an385 bsp移植制作 :系統(tǒng)運(yùn)行篇

    前面已經(jīng)讓 RT-Thread 進(jìn)入了 entry 入口函數(shù),并且 調(diào)整 鏈接腳本,自動(dòng)初始化與 MSH shell 的符號(hào)已經(jīng)預(yù)留, 進(jìn)入了 RT-Thread
    的頭像 發(fā)表于 11-14 12:27 ?889次閱讀
    <b class='flag-5'>RT-Thread</b> qemu mps2-an385 bsp移植制作 :系統(tǒng)運(yùn)行篇

    RT-thread初始化過(guò)程是怎樣進(jìn)行的

    RT-thread初始化過(guò)程是怎樣進(jìn)行的?擴(kuò)展補(bǔ)丁Sub和super的作用是什么?如何去使用它們呢?
    發(fā)表于 11-29 07:42

    如何對(duì)RT-Thread系統(tǒng)進(jìn)行初始化

    RT-Thread是如何啟動(dòng)的?如何對(duì)RT-Thread系統(tǒng)進(jìn)行初始化呢?
    發(fā)表于 11-30 07:54

    為什么RT-Thread要采用這種復(fù)雜的方式來(lái)進(jìn)行自動(dòng)初始化操作呢

    在分析之前首先查閱 RT-Thread 的官方文檔RT-Thread 自動(dòng)初始化機(jī)制,根據(jù)官方文檔的講述在 RTT 源碼中共使用了 6 中
    發(fā)表于 04-06 17:49

    RT-Thread自動(dòng)初始化機(jī)制簡(jiǎn)介

    RT-Thread 的時(shí)鐘管理以時(shí)鐘節(jié)拍為基礎(chǔ),時(shí)鐘節(jié)拍是 RT-Thread 操作系統(tǒng)中最小的RT-Thread 自動(dòng)初始化機(jī)制時(shí)鐘單位。
    發(fā)表于 04-06 18:08

    RT-Thread系統(tǒng)自動(dòng)初始化機(jī)制簡(jiǎn)介

    RT-Thread 自動(dòng)初始化機(jī)制1、自動(dòng)初始化機(jī)制簡(jiǎn)介在系統(tǒng)啟動(dòng)流程圖中,有兩個(gè)函數(shù):rt_c
    發(fā)表于 04-12 17:43

    RT-Thread系統(tǒng)初始化與啟動(dòng)流程詳細(xì)描述

    時(shí), 該函數(shù)將初始化系統(tǒng)的定時(shí)器線程。void rt_application_init( )創(chuàng)建用戶(hù)線程由此創(chuàng)建個(gè)用戶(hù)main()線程,而 main()函數(shù)是RT-Thread的用戶(hù)
    發(fā)表于 08-25 15:15

    RT-Thread自動(dòng)初始化原理分析

    ;}這里我們直接就可以使用 printf 進(jìn)行打印,而沒(méi)有進(jìn)行些其它的初始化,參考這個(gè)思路引出了 RT-Thread自動(dòng)初始化
    發(fā)表于 12-05 14:17

    RT-Thread學(xué)習(xí)筆記 --(3)RT-Thread自動(dòng)初始化機(jī)制分析

    相信不少工程師在閱讀RT-Thread相關(guān)源代碼的時(shí)候,都會(huì)經(jīng)??吹饺缦聢D所示的宏定義,按照宏定義的命名來(lái)理解,這些宏定義似乎都是對(duì)些...
    發(fā)表于 01-25 18:55 ?1次下載
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 --(3)<b class='flag-5'>RT-Thread</b><b class='flag-5'>自動(dòng)</b><b class='flag-5'>初始化</b>機(jī)制分析

    RT-Thread全球技術(shù)大會(huì):如何使用組件以及自動(dòng)初始化流程

    RT-Thread全球技術(shù)大會(huì):如何使用組件和自動(dòng)初始化流程 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 15:16 ?990次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術(shù)大會(huì):如何使用組件以及<b class='flag-5'>自動(dòng)</b><b class='flag-5'>初始化</b>流程

    RT-Thread自動(dòng)初始化機(jī)制

    ??在分析之前首先查閱 RT-Thread 的官方文檔 [RT-Thread 自動(dòng)初始化機(jī)制](https://www.rt-thread.
    的頭像 發(fā)表于 06-17 08:52 ?2767次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>自動(dòng)</b><b class='flag-5'>初始化</b>機(jī)制

    rt-thread 優(yōu)化系列(六)啟動(dòng)流程重構(gòu)

    去年此時(shí),筆者剛接觸 rt-thread 的時(shí)候,被它的初始化過(guò)程深深折服了。第次打開(kāi)個(gè) rt-thread 的項(xiàng)目,竟然沒(méi)找到多線程在
    的頭像 發(fā)表于 07-04 15:30 ?1816次閱讀
    <b class='flag-5'>rt-thread</b> 優(yōu)化系列(六)啟動(dòng)流程重構(gòu)

    rt-thread線程棧初始化參數(shù)分析

    RT-Thread 在線程初始化的代碼內(nèi)有初始化線程堆棧的代碼
    的頭像 發(fā)表于 08-14 16:50 ?1847次閱讀
    <b class='flag-5'>rt-thread</b>線程棧<b class='flag-5'>初始化</b>參數(shù)分析

    RT-Thread使用經(jīng)驗(yàn)分享:鏈表未初始化造成死機(jī)

    最近在開(kāi)發(fā)調(diào)試基于RT-Thread 的驅(qū)動(dòng)時(shí),遇到個(gè)比較奇怪的死機(jī)問(wèn)題,后來(lái)經(jīng)過(guò)步步排查,終于發(fā)現(xiàn)是驅(qū)動(dòng)的鏈表節(jié)點(diǎn)沒(méi)有初始化造成的死機(jī)
    的頭像 發(fā)表于 10-08 14:49 ?1042次閱讀
    <b class='flag-5'>RT-Thread</b>使用經(jīng)驗(yàn)分享:鏈表未<b class='flag-5'>初始化</b>造成死機(jī)
    主站蜘蛛池模板: 手机看片国产免费久久网 | 青草悠悠视频在线观看 | 天堂电影免费在线资源 | 日产精品卡二卡三卡四卡无卡乱码 | 四虎精品成人免费观看 | 四虎影院美女 | 婷婷丁香激情 | 成人v| 亚洲国产一区二区三区在线观看 | 站长工具天天爽视频 | a资源在线 | 日本一区二区不卡视频 | 久久午夜视频 | 午夜性a一级毛片 | 欧美成人精品一级高清片 | 久久天天综合 | 淫性视频 | 77788色淫网站免费观看 | 黄色性生活毛片 | 天天舔天天干 | 奇米激情| 亚洲成人高清在线观看 | 久久黄色网 | 国产日本特黄特色大片免费视频 | 免费大片看黄在观看 | 亚洲国产午夜精品理论片的软件 | 色一欲一性一乱一区二区三区 | 免费视频在线看 | 午夜视频在线观看一区 | 天堂网久久 | 午夜精品久久久久久久第一页 | 成人免费看黄网站无遮挡 | 五月sese | 亚洲欧美在线精品一区二区 | 999av视频 | 黄色靠逼网站 | 天天摸天天做天天爽在线 | 四虎影院网址大全 | 99热在线获取最新地址 | 亚洲电影一区二区 | 久久精品国产99精品国产2021 |