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 優(yōu)化系列(六)啟動(dòng)流程重構(gòu)

出出 ? 來(lái)源:出出 ? 作者:出出 ? 2022-07-04 15:30 ? 次閱讀

前言

去年此時(shí),筆者剛接觸 rt-thread 的時(shí)候,被它的初始化過(guò)程深深折服了。第一次打開(kāi)一個(gè) rt-thread 的項(xiàng)目,竟然沒(méi)找到多線程在哪兒初始化的,"main" 函數(shù)里沒(méi)有!
進(jìn)而發(fā)現(xiàn),"main" 函數(shù)不是我們認(rèn)識(shí)的 "main" 函數(shù)了。在 rt-thread 里,程序進(jìn)入 "main" 函數(shù)之前還有很長(zhǎng)一段路。

目前的初始化流程

見(jiàn)下圖吧,一些主要的過(guò)程已經(jīng)被列出來(lái)了。

poYBAGLCkJ2AZU2kAADj4Zq8UMY084.png

從圖中可以看出來(lái):
1. 任務(wù)調(diào)度器啟動(dòng)前,有很多的初始化工作。
2. `rt_components_board_init` 里還有很多隱含的外設(shè)初始化操作。這個(gè)時(shí)候沒(méi)有進(jìn)入多線程環(huán)境。
3. 先創(chuàng)建了三個(gè)默認(rèn)線程(如果啟用了軟定時(shí)器),但并未立馬運(yùn)行,任務(wù)調(diào)度器啟動(dòng)后從中選擇優(yōu)先級(jí)最高的那個(gè)運(yùn)行(可能是 "main" 可能是 "timer")。
4. "main" 線程啟動(dòng)后,還有很多初始化工作,這個(gè)時(shí)候已經(jīng)進(jìn)入多線程環(huán)境。

這個(gè)流程存在的問(wèn)題:
1. 堆申請(qǐng)被設(shè)計(jì)成多線程安全訪問(wèn),內(nèi)部有加鎖動(dòng)作,而鎖也是限于在線程上下文使用的。串口驅(qū)動(dòng)申請(qǐng)緩存內(nèi)存卻是在任務(wù)調(diào)度器啟動(dòng)前!
2. 開(kāi)啟 ulog 后,也有可能出現(xiàn)在任務(wù)調(diào)度器啟動(dòng)之先使用鎖的現(xiàn)象。
3. 還有線程安全版 `rt_kprintf` ,這個(gè)也是考慮只在線程上下文使用,如果開(kāi)啟了它,任務(wù)調(diào)度器啟動(dòng)前的 `rt_kprintf` 需求被忽略了。

`rt_components_board_init` `rt_components_init` 兩個(gè)函數(shù)可能有很多隱含操作。但是因?yàn)?`rt_components_board_init` 處于非多任務(wù)環(huán)境中,它比 `rt_components_init` 更容易出問(wèn)題。

例如,不能使用加鎖操作、不能使用 `rt_thread_mdelay` `rt_thread_delay` 等延時(shí)操作。

在之前的一篇文章里,[rt-thread 驅(qū)動(dòng)篇(六)serialX弊端及解決方法]( http://srfitnesspt.com/d/1850548.html ) 比較全面的梳理了一下串口終端設(shè)備怎么用中斷發(fā)送模式。首先,任務(wù)調(diào)度器啟動(dòng)前是不會(huì)有中斷的,用中斷發(fā)送,可能不會(huì)輸出數(shù)據(jù),如果是阻塞模式,可能會(huì)永久卡死到這里;如果是非阻塞模式,可能有很多信息被扔掉。

**所以,任務(wù)調(diào)度器啟動(dòng)前,串口終端輸出要么用輪詢輸出,要么給個(gè)很大的輸出緩存**,至于多大合適,這個(gè)誰(shuí)也說(shuō)不好。

還有一個(gè)折中的方法是降低任務(wù)調(diào)度器啟動(dòng)前的打印輸出需求。怎么降低?調(diào)整初始化流程,先啟動(dòng)一個(gè)無(wú)依賴(lài)的 idle 線程,把其它操作放到線程中。

新初始化流程設(shè)想

poYBAGLCkOyALohXAAC7C3LqP2U345.png

這樣一來(lái),初始化注冊(cè)外設(shè)設(shè)備的過(guò)程也是在線程上下文環(huán)境了,這個(gè)時(shí)候想用加鎖操作也可以,申請(qǐng)堆內(nèi)存也不會(huì)出現(xiàn) `Function[rt_sem_take] shall not be used before scheduler start`

如果不開(kāi)啟 RT_DEBUG,堆、pin、UART、控制臺(tái)初始化部分也可以放到 idle 線程里。一年前,筆者在 rt-thread 論壇上提出過(guò)這個(gè)設(shè)想——[
rt-thread 系統(tǒng)啟動(dòng)及 SysTick 初始化流程優(yōu)化可行性分析]( https://club.rt-thread.org/ask/article/ab1c5556dd9f186a.html )。
稍作修改,如下:
1. 配置系統(tǒng)時(shí)鐘,同時(shí)配置 SysTick(同前);
2. 初始化 rtt 系統(tǒng)調(diào)度器,定時(shí)器鏈表等全局變量;
3. 創(chuàng)建 idle 線程;
4. 啟動(dòng) idle 線程并啟動(dòng) 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 初始化板級(jí)外設(shè)配置;
9. 由 idle 線程創(chuàng)建 main 和 soft timer 線程。
10. main 線程進(jìn)行組件初始化配置,以及創(chuàng)建其它應(yīng)用線程。

和上面鏈接里提到的流程,修改了開(kāi)啟 systick 中斷節(jié)點(diǎn)。
同時(shí)如果放棄在初始化配置系統(tǒng)時(shí)鐘時(shí)調(diào)試輸出信息的想法,放棄創(chuàng)建 idle 線程過(guò)程中調(diào)試輸出錯(cuò)誤信息的想法,放棄啟動(dòng)系統(tǒng)任務(wù)調(diào)度器過(guò)程調(diào)試輸出錯(cuò)誤信息的想法后,控制臺(tái)輸出信息也就全處于線程上下文了。

最起碼,我們有以下幾點(diǎn)收獲:
1. 任務(wù)調(diào)度器啟動(dòng)前,不需要開(kāi)全局中斷。
2. 申請(qǐng)堆內(nèi)存的操作都可以是在線程上下文。
3. 控制臺(tái)串口輸出數(shù)據(jù)可以使用中斷或者 DMA 任意模式。

缺點(diǎn):idle 線程??赡鼙戎耙笠恍6?,這些內(nèi)存只有一次使用機(jī)會(huì),切換到 “main” 線程后多了些“閑置”內(nèi)存。

實(shí)踐驗(yàn)證

目前,筆者在自己的項(xiàng)目上,使用 NUC970 系列芯片,驗(yàn)證了上述想法,目前系統(tǒng)啟動(dòng)過(guò)程未發(fā)現(xiàn)出現(xiàn)異常。

結(jié)束語(yǔ)

很多問(wèn)題是時(shí)序的原因,打亂了某件東西本該有的操作 [#5584]( https://github.com/RT-Thread/rt-thread/issues/5584 )。
對(duì)系統(tǒng)啟動(dòng)流程做些修改,我們發(fā)現(xiàn)很多概念可以理直氣壯的講出來(lái),比如,鎖只能在線程上下文使用。當(dāng)我們通過(guò)補(bǔ)丁的方式,使得在任務(wù)調(diào)度器啟動(dòng)前進(jìn)行了鎖操作而不出異常,那么這樣就讓人迷惑了。

審核編輯:湯梓紅
聲明:本文內(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)投訴
  • 啟動(dòng)流程
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

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

    關(guān)注

    31

    文章

    1249

    瀏覽量

    39727
  • main
    +關(guān)注

    關(guān)注

    0

    文章

    38

    瀏覽量

    6114
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Thread記錄(三、RT-Thread線程操作函數(shù))

    講完了RT-Thread開(kāi)發(fā)環(huán)境,啟動(dòng)流程啟動(dòng)以后當(dāng)然是開(kāi)始跑線程了,那么自然我們得學(xué)會(huì)如何創(chuàng)建線程以及線程的有關(guān)操作。
    的頭像 發(fā)表于 06-20 00:31 ?6507次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(三、<b class='flag-5'>RT-Thread</b>線程操作函數(shù))

    RT-Thread記錄(二、RT-Thread內(nèi)核啟動(dòng)流程

    在前面我們RT-Thread Studio工程基礎(chǔ)之上講一講RT-Thread內(nèi)核啟動(dòng)流程.
    的頭像 發(fā)表于 06-20 00:30 ?4883次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(二、<b class='flag-5'>RT-Thread</b>內(nèi)核<b class='flag-5'>啟動(dòng)</b><b class='flag-5'>流程</b>)

    【原創(chuàng)精選】RT-Thread征文精選技術(shù)文章合集

    漂移問(wèn)題分析rt-thread 優(yōu)化系列(四)信號(hào)對(duì) ipc 的影響rt-thread 優(yōu)化系列
    發(fā)表于 07-26 14:56

    RT-Thread快速入門(mén)之了解內(nèi)核啟動(dòng)流程

    1、了解RT-Thread內(nèi)核的啟動(dòng)流程  內(nèi)核是操作系統(tǒng)最基礎(chǔ)也是最重要的部分。從本文開(kāi)始進(jìn)入 RT-Thread 內(nèi)核相關(guān)知識(shí)的學(xué)習(xí)?! ∈紫攘私鈨?nèi)核的基礎(chǔ)知識(shí),對(duì)
    發(fā)表于 09-05 17:01

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開(kāi)發(fā)組(2015-03-31)。RT-Thread做為國(guó)內(nèi)有較大影響力的開(kāi)源實(shí)時(shí)操作系統(tǒng),本文是RT-Thread實(shí)時(shí)操作系統(tǒng)的編程指南
    發(fā)表于 11-26 16:06 ?0次下載

    RT-Thread用戶手冊(cè)

    RT-Thread用戶手冊(cè)——本書(shū)是RT-Thread的編程手冊(cè),用于指導(dǎo)在RT-Thread實(shí)時(shí)操作系統(tǒng)環(huán)境下如何進(jìn)行編 程。
    發(fā)表于 11-26 16:16 ?0次下載

    RT-Thread全球技術(shù)大會(huì):Kconfig在RT-Thread中的工作機(jī)制

    RT-Thread全球技術(shù)大會(huì):Kconfig在RT-Thread中的工作機(jī)制 ? ? ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 14:49 ?1452次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術(shù)大會(huì):Kconfig在<b class='flag-5'>RT-Thread</b>中的工作機(jī)制

    RT-Thread全球技術(shù)大會(huì):RT-Thread測(cè)試用例集合案例

    RT-Thread全球技術(shù)大會(huì):RT-Thread測(cè)試用例集合案例 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 16:34 ?2014次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術(shù)大會(huì):<b class='flag-5'>RT-Thread</b>測(cè)試用例集合案例

    RT-Thread學(xué)習(xí)筆記 RT-Thread的架構(gòu)概述

    RT-Thread 簡(jiǎn)介 作為一名 RTOS 的初學(xué)者,也許你對(duì) RT-Thread 還比較陌生。然而,隨著你的深入接觸,你會(huì)逐漸發(fā)現(xiàn) RT-Thread 的魅力和它相較于其他同類(lèi)型 RTOS
    的頭像 發(fā)表于 07-09 11:27 ?4388次閱讀
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 <b class='flag-5'>RT-Thread</b>的架構(gòu)概述

    RT-Thread文檔_RT-Thread 簡(jiǎn)介

    RT-Thread文檔_RT-Thread 簡(jiǎn)介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡(jiǎn)介

    RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南

    RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南
    發(fā)表于 02-22 18:23 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 潘多拉 STM32L475 上手指南

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    基于RT-Thread Studio學(xué)習(xí)

    前期準(zhǔn)備:從官網(wǎng)下載 RT-Thread Studio,弄個(gè)賬號(hào)登陸,開(kāi)啟rt-thread學(xué)習(xí)之旅。
    的頭像 發(fā)表于 05-15 11:00 ?3658次閱讀
    基于<b class='flag-5'>RT-Thread</b> Studio學(xué)習(xí)

    RT-Thread啟動(dòng)流程?RT-Thread如何支持不同開(kāi)發(fā)板?

    一個(gè)開(kāi)發(fā)板上的RT-Thread啟動(dòng)流程可能是首先從bsp?當(dāng)中鏈接腳本指定的startup_xxx.S?中的入口函數(shù)(ENTRY)或者復(fù)位異常處理函數(shù)(ResetHandler)開(kāi)始運(yùn)行,這部分我們?cè)谥v?bsp?支持時(shí)會(huì)詳細(xì)
    的頭像 發(fā)表于 08-10 15:29 ?1401次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>啟動(dòng)</b><b class='flag-5'>流程</b>?<b class='flag-5'>RT-Thread</b>如何支持不同開(kāi)發(fā)板?

    RT-Thread v5.0.2 發(fā)布

    RT-Thread 代碼倉(cāng)庫(kù)地址: ●? https://github.com/RT-Thread/rt-thread RT-Thread 5.0.2 版本發(fā)布日志詳情: ●? htt
    的頭像 發(fā)表于 10-10 18:45 ?1298次閱讀
    <b class='flag-5'>RT-Thread</b> v5.0.2 發(fā)布