前言
去年此時,筆者剛接觸 rt-thread 的時候,被它的初始化過程深深折服了。第一次打開一個 rt-thread 的項目,竟然沒找到多線程在哪兒初始化的,"main" 函數(shù)里沒有!
進(jìn)而發(fā)現(xiàn),"main" 函數(shù)不是我們認(rèn)識的 "main" 函數(shù)了。在 rt-thread 里,程序進(jìn)入 "main" 函數(shù)之前還有很長一段路。
目前的初始化流程
見下圖吧,一些主要的過程已經(jīng)被列出來了。
![poYBAGLCkJ2AZU2kAADj4Zq8UMY084.png](https://file.elecfans.com/web2/M00/4E/DC/poYBAGLCkJ2AZU2kAADj4Zq8UMY084.png)
從圖中可以看出來:
1. 任務(wù)調(diào)度器啟動前,有很多的初始化工作。
2. `rt_components_board_init` 里還有很多隱含的外設(shè)初始化操作。這個時候沒有進(jìn)入多線程環(huán)境。
3. 先創(chuàng)建了三個默認(rèn)線程(如果啟用了軟定時器),但并未立馬運(yùn)行,任務(wù)調(diào)度器啟動后從中選擇優(yōu)先級最高的那個運(yùn)行(可能是 "main" 可能是 "timer")。
4. "main" 線程啟動后,還有很多初始化工作,這個時候已經(jīng)進(jìn)入多線程環(huán)境。
這個流程存在的問題:
1. 堆申請被設(shè)計成多線程安全訪問,內(nèi)部有加鎖動作,而鎖也是限于在線程上下文使用的。串口驅(qū)動申請緩存內(nèi)存卻是在任務(wù)調(diào)度器啟動前!
2. 開啟 ulog 后,也有可能出現(xiàn)在任務(wù)調(diào)度器啟動之先使用鎖的現(xiàn)象。
3. 還有線程安全版 `rt_kprintf` ,這個也是考慮只在線程上下文使用,如果開啟了它,任務(wù)調(diào)度器啟動前的 `rt_kprintf` 需求被忽略了。
`rt_components_board_init` `rt_components_init` 兩個函數(shù)可能有很多隱含操作。但是因?yàn)?`rt_components_board_init` 處于非多任務(wù)環(huán)境中,它比 `rt_components_init` 更容易出問題。
例如,不能使用加鎖操作、不能使用 `rt_thread_mdelay` `rt_thread_delay` 等延時操作。
在之前的一篇文章里,[rt-thread 驅(qū)動篇(六)serialX弊端及解決方法]( http://www.qldv.cn/d/1850548.html ) 比較全面的梳理了一下串口終端設(shè)備怎么用中斷發(fā)送模式。首先,任務(wù)調(diào)度器啟動前是不會有中斷的,用中斷發(fā)送,可能不會輸出數(shù)據(jù),如果是阻塞模式,可能會永久卡死到這里;如果是非阻塞模式,可能有很多信息被扔掉。
**所以,任務(wù)調(diào)度器啟動前,串口終端輸出要么用輪詢輸出,要么給個很大的輸出緩存**,至于多大合適,這個誰也說不好。
還有一個折中的方法是降低任務(wù)調(diào)度器啟動前的打印輸出需求。怎么降低?調(diào)整初始化流程,先啟動一個無依賴的 idle 線程,把其它操作放到線程中。
新初始化流程設(shè)想
![poYBAGLCkOyALohXAAC7C3LqP2U345.png](https://file.elecfans.com/web2/M00/4E/DD/poYBAGLCkOyALohXAAC7C3LqP2U345.png)
這樣一來,初始化注冊外設(shè)設(shè)備的過程也是在線程上下文環(huán)境了,這個時候想用加鎖操作也可以,申請堆內(nèi)存也不會出現(xiàn) `Function[rt_sem_take] shall not be used before scheduler start`
如果不開啟 RT_DEBUG,堆、pin、UART、控制臺初始化部分也可以放到 idle 線程里。一年前,筆者在 rt-thread 論壇上提出過這個設(shè)想——[
rt-thread 系統(tǒng)啟動及 SysTick 初始化流程優(yōu)化可行性分析]( https://club.rt-thread.org/ask/article/ab1c5556dd9f186a.html )。
稍作修改,如下:
1. 配置系統(tǒng)時鐘,同時配置 SysTick(同前);
2. 初始化 rtt 系統(tǒng)調(diào)度器,定時器鏈表等全局變量;
3. 創(chuàng)建 idle 線程;
4. 啟動 idle 線程并啟動 rtt 系統(tǒng)調(diào)度;
5. 由 idle 線程啟用 SysTick 中斷;
6. 由 idle 線程初始化調(diào)試串口;
7. 由 idle 線程初始化內(nèi)存堆;
8. 由 idle 線程調(diào)用執(zhí)行 rt_components_board_init 初始化板級外設(shè)配置;
9. 由 idle 線程創(chuàng)建 main 和 soft timer 線程。
10. main 線程進(jìn)行組件初始化配置,以及創(chuàng)建其它應(yīng)用線程。
和上面鏈接里提到的流程,修改了開啟 systick 中斷節(jié)點(diǎn)。
同時如果放棄在初始化配置系統(tǒng)時鐘時調(diào)試輸出信息的想法,放棄創(chuàng)建 idle 線程過程中調(diào)試輸出錯誤信息的想法,放棄啟動系統(tǒng)任務(wù)調(diào)度器過程調(diào)試輸出錯誤信息的想法后,控制臺輸出信息也就全處于線程上下文了。
最起碼,我們有以下幾點(diǎn)收獲:
1. 任務(wù)調(diào)度器啟動前,不需要開全局中斷。
2. 申請堆內(nèi)存的操作都可以是在線程上下文。
3. 控制臺串口輸出數(shù)據(jù)可以使用中斷或者 DMA 任意模式。
缺點(diǎn):idle 線程棧可能比之前要大一些。而且,這些內(nèi)存只有一次使用機(jī)會,切換到 “main” 線程后多了些“閑置”內(nèi)存。
實(shí)踐驗(yàn)證
目前,筆者在自己的項目上,使用 NUC970 系列芯片,驗(yàn)證了上述想法,目前系統(tǒng)啟動過程未發(fā)現(xiàn)出現(xiàn)異常。
結(jié)束語
很多問題是時序的原因,打亂了某件東西本該有的操作 [#5584]( https://github.com/RT-Thread/rt-thread/issues/5584 )。
對系統(tǒng)啟動流程做些修改,我們發(fā)現(xiàn)很多概念可以理直氣壯的講出來,比如,鎖只能在線程上下文使用。當(dāng)我們通過補(bǔ)丁的方式,使得在任務(wù)調(diào)度器啟動前進(jìn)行了鎖操作而不出異常,那么這樣就讓人迷惑了。
-
啟動流程
+關(guān)注
關(guān)注
0文章
14瀏覽量
6502 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1305瀏覽量
40391 -
main
+關(guān)注
關(guān)注
0文章
38瀏覽量
6203
發(fā)布評論請先 登錄
相關(guān)推薦
RT-Thread記錄(三、RT-Thread線程操作函數(shù))
![<b class='flag-5'>RT-Thread</b>記錄(三、<b class='flag-5'>RT-Thread</b>線程操作函數(shù))](https://file.elecfans.com//web2/M00/4B/C4/poYBAGKugYaAXQOrAABFNRF2GvE722.png)
【原創(chuàng)精選】RT-Thread征文精選技術(shù)文章合集
RT-Thread快速入門之了解內(nèi)核啟動流程
RT-Thread編程指南
RT-Thread用戶手冊
RT-Thread全球技術(shù)大會:Kconfig在RT-Thread中的工作機(jī)制
![<b class='flag-5'>RT-Thread</b>全球技術(shù)大會:Kconfig在<b class='flag-5'>RT-Thread</b>中的工作機(jī)制](https://file.elecfans.com/web2/M00/46/18/pYYBAGKQcvGAQEQrAAFnDo7l2-o172.png)
RT-Thread學(xué)習(xí)筆記 RT-Thread的架構(gòu)概述
![<b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 <b class='flag-5'>RT-Thread</b>的架構(gòu)概述](https://file.elecfans.com/web2/M00/52/31/pYYBAGLKk5WAA__jAADjdAdXhIs410.jpg)
RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南
![<b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 潘多拉 STM32L475 上手指南](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于RT-Thread Studio學(xué)習(xí)
![基于<b class='flag-5'>RT-Thread</b> Studio學(xué)習(xí)](https://file1.elecfans.com/web2/M00/82/C1/wKgaomRhn_SAM7fdAACQhFt0KEA325.jpg)
RT-Thread啟動流程?RT-Thread如何支持不同開發(fā)板?
![<b class='flag-5'>RT-Thread</b><b class='flag-5'>啟動</b><b class='flag-5'>流程</b>?<b class='flag-5'>RT-Thread</b>如何支持不同開發(fā)板?](https://file1.elecfans.com/web2/M00/90/07/wKgZomTUkaaANMUOAAF8Ea4XbKc357.jpg)
RT-Thread v5.0.2 發(fā)布
![<b class='flag-5'>RT-Thread</b> v5.0.2 發(fā)布](https://file1.elecfans.com//web2/M00/A8/7A/wKgaomUt2fWAVBHtAHiX-BnG6Ho342.gif)
評論