首頁 > 系統教程 > Linux > 主體

在STM32上模擬Linux自動初始化過程

王林
發布: 2024-02-12 08:00:04
轉載
826 人瀏覽過

在Linux中,有許多程式設計想法值得學習。許多技術大牛將這些想法和機制應用到單晶片程式設計中,特別是在STM32中模擬了Linux核心的自動初始化流程。

一般而言,我們在寫程式時都會按照一定套路來進行。我們會按照順序邏輯,一個接一個地執行函數。

在STM32上模擬Linux自動初始化過程

如果邏輯非常複雜,涉及的模組比較多,那麼這種順序執行的程式碼就會比較臃腫,各模組耦合非常緊密。 Linux kernel 中,有各種週邊驅動,想按照一個順序邏輯執行下去,幾乎是不可能的。

而kenrel 程式碼能有這麼大的程式碼量,大而不亂,把各層次,各模組有效的分離,而大量的程式碼又有邏輯的組織在一起,和這個initcall 有至關重要的作用。

透過模仿這種方式,最後把圖片中main函數程式碼清空,分離這種邏輯,又實現同樣的功能。

如何能實現這樣的功能了,需要一些背景知識:

1,程式碼的組織

2,連結腳本相關的知識。

3,函數指標的應用。

在STM32上模擬Linux自動初始化過程

程式碼的組織,如圖片需要知道變數a,b及函數指標f,f2是存放在程式的哪些段落中,可以去看這篇stm32 啟動程式碼實作|C語言,上述的a ,f都是存放在bss 段中,b,f2是存放在data段中,因為已經給定了初始值,而實現這個intcall會把需要自動初始化的資料放到一個自訂的段中去,如.initcall。

如何放到特定的段中了,就需要用到了attribute((section)) 關鍵字來改變的資料存放段了。

目前的程式編譯出來用到了這些個段,除了.isr_vector也是新增的,其他都是編譯器預設的。

在STM32上模擬Linux自動初始化過程

先加段程式碼:

在STM32上模擬Linux自動初始化過程

當然這還不夠,還需要告訴連接器(LD) 要把 .initcall 段也連結到程式中,所以也需要這段修改。

在STM32上模擬Linux自動初始化過程

這段以8位元組對齊,定義兩個全域變量,及依0-5順序的連結這些數據,這樣的兩處修改,再來看程式各段的情況。

如圖片:

在STM32上模擬Linux自動初始化過程

已經多出紅色框框為.initcalls段,這段總共是8個位元組,從0x80005a8除開始。

在來看一下具體的這一段的情況,用readelf 工具。

在STM32上模擬Linux自動初始化過程

和上面的size工具是匹配的,而綠色框框的位址就是SystemInit(0x08000231,小端模式。)

在STM32上模擬Linux自動初始化過程

所以透過attribute及修改連結腳本,就把函數指標變數放到了.initcall 段。

那麼如何來呼叫這個函數了,和之前的初始化data段資料類似,遍歷這個段,然後取出這個函數位址,然後強制把段中的位址,轉成函數指針,再直接呼叫即可。

在STM32上模擬Linux自動初始化過程在STM32上模擬Linux自動初始化過程

實現的這張圖片,就是從.initcall段中取出函數位址,然後直接調用,非常容易把函數的位址及這個函數指標變數的位址搞混。

程式碼這麼修改,需要自動初始化函數的確是可以調到了,但是每次都寫這麼長長的一段static initcall_t __ attribute__(( __ used__,__ section__(“.initcall.0.init”))) ,就是不舒服. linux kernel中透過巨集來修改。

這個也是一樣。

在STM32上模擬Linux自動初始化過程

新增 依照程式​​邏輯順序執行的一些巨集

0,low_level_init 例如放始化系統基本時鐘

1,arch_init 例如放CPU架構d如初始化NVIC的一些初始化。

2,dev_init 週邊模組初始化,比 i2c, flash, spi等。

3,board_init 做具體硬體板及的一些設定。

4,os_init 作業系統的一些設定如,檔案系統,網路協定堆疊等。

5,app_init 最後跑用戶程式。

把自己的程式也做一下修改,用巨集取代。這樣子掉呼叫do_initcalls 就會照0,1-到5的順序執行了。

在STM32上模擬Linux自動初始化過程在STM32上模擬Linux自動初始化過程

最後在來看initcall 段:

在STM32上模擬Linux自動初始化過程在STM32上模擬Linux自動初始化過程在STM32上模擬Linux自動初始化過程在STM32上模擬Linux自動初始化過程

這樣只要在需要自動初始化函數加上類似dev_init(),app_init() 就可以了,就會自動呼叫到,而不需要main 函數中一個一個的順序執行。

例如i2c控制的初始化放到dev_init 中,下面掛了很多i2c的從設備,只要分別給個從設備用app_init 初始化就行,即使來了一個新的,也用這app_init初始化就行,也不需要更改原來的,高度的分離模組間的耦合度。

這樣模擬Linux kenerl 初始化驗證成功,最後上函式庫。

以上是在STM32上模擬Linux自動初始化過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:lxlinux.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!