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

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

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

在STM32上模擬Linux自動初始化

STM32嵌入式開發(fā) ? 來源:STM32嵌入式開發(fā) ? 2023-05-09 09:25 ? 次閱讀

Linux中有很多編程思想可以學(xué)習(xí),很多大佬把這些思想、機(jī)制運用到單片機(jī)的編程上。

下文,在STM32模擬Linux kernel自動初始化流程。

通常我們寫程序都是按照這個套路,一個函數(shù)一個函數(shù)按照順序邏輯一個一個的執(zhí)行下去。

wKgaomRZoXqAX6rbAAEIxGySr_E226.jpg

如果邏輯非常復(fù)雜,涉及的模塊比較多,那么這種順序執(zhí)行的代碼就會比較臃腫,各模塊耦合非常緊密。Linux kernel 中,有各種外設(shè)驅(qū)動,想按照一個順序邏輯執(zhí)行下去,幾乎是不可能的。

而kenrel 代碼能有這么大的代碼量,大而不亂,把各層次,各模塊有效的分離,而大量的代碼又有邏輯的組織在一起,和這個initcall 有至關(guān)重要的作用。

通過模仿這種方式,最后把圖片中main函數(shù)代碼清空,分離這種邏輯,又實現(xiàn)同樣的功能。

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

1,程序代碼的組織

2,鏈接腳本相關(guān)的知識。

3,函數(shù)指針的應(yīng)用。

wKgZomRZoXqAGB9mAAB5N68kDh0447.jpg

代碼的組織,如圖片需要知道變量a,b及函數(shù)指針 f,f2是存放在程序的哪些段中,可以去看一下這篇stm32 啟動代碼 實現(xiàn)|C語言,上述的a,f都是存放在bss 段中,b,f2是存放在data段中,因為已經(jīng)給定了初始值,而實現(xiàn)這個intcall會把需要自動初始化的數(shù)據(jù)放到一個自定義的段中去,如.initcall。

如何放到特定的段中了,就需要用到了attribute((section)) 關(guān)鍵字來改變的數(shù)據(jù)存放段了。

目前的程序編譯出來用到了這些個段,除了.isr_vector也是添加的,其他都是編譯器默認(rèn)的。

wKgaomRZoXqAYgguAALDZ7tSpOo994.png

先加段代碼:

wKgZomRZoXqAYaVoAABqFGapjxQ792.png

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

wKgaomRZoXqAKTtAAAEV4ZDxaz4342.jpg

這段按8字節(jié)對齊,定義兩個全局變量,及按0-5順序的鏈接這些數(shù)據(jù),這樣的兩處修改,再來看一下程序各段的情況。

如圖片:

wKgaomRZoXqAAOXZAAIqQD5KTys550.png

已經(jīng)多出紅色框框為.initcalls段,這段總共是8個字節(jié),從0x80005a8除開始。

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

wKgaomRZoXqAO4SyAACwT_haxtc325.png

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

wKgZomRZoXqABp0rAAEJjXL8JG8510.png

所以通過attribute及修改鏈接腳本,就把函數(shù)指針變量放到了.initcall 段中。

那么如何來調(diào)用這個函數(shù)了,和之前的初始化data段數(shù)據(jù)類似,遍歷這個段,然后取出這個函數(shù)地址,然后強(qiáng)制把段中的地址,轉(zhuǎn)成函數(shù)指針,再直接調(diào)用即可。

wKgaomRZoXqAJnrlAACJK4aTfXI240.png

wKgZomRZoXqAMgNBAAFWSNbCAg4585.png

實現(xiàn)的這張圖片,就是從.initcall段中取出函數(shù)地址,然后直接調(diào)用,非常容易把函數(shù)的地址及這個函數(shù)指針變量的地址搞混。

代碼這么修改,需要自動初始化函數(shù)的確是可以調(diào)到了,但是每次都寫這么長長的一段static initcall_t __ attribute__(( __ used__,__ section__(".initcall.0.init"))),就是不舒服. linux kernel中通過宏來修改。

這個也一樣。

wKgZomRZoXqAAwZjAAHF0FeQdh0722.png

添加 按照程序邏輯順序執(zhí)行的一些宏

0,low_level_init 比如放始化系統(tǒng)基本時鐘

1,arch_init 比如放CPU架構(gòu)d如初始化NVIC的一些初始化。

2,dev_init 外設(shè)模塊初始化,比 i2c, flash, spi等。

3,board_init 做具體硬件板及的一些設(shè)置。

4,os_init 操作系統(tǒng)的一些設(shè)置如,文件系統(tǒng),網(wǎng)絡(luò)協(xié)議棧等。

5,app_init 最后跑用戶程序。

把自己的程序也做一下修改,用宏代替。這樣子掉調(diào)用do_initcalls 就會按照0,1-到5的順序執(zhí)行了。

wKgaomRZoXqAR4AIAADA5rrXPBo591.png

wKgaomRZoXqANQbXAADaxBlZWoc941.png

最后在來看一下initcall 段:

wKgaomRZoXqAee7BAAF4g331D14969.png

wKgZomRZoXqAF2OkAAAPYn2Y9cE421.png

wKgZomRZoXqAIQ7QAAJ4F9IxZcE643.jpg

wKgZomRZoXqAa-9rAAEBcgMElwo640.jpg

這樣只要在需要自動初始化函數(shù)加上類似于dev_init(),app_init() 就可以了,就會自動調(diào)用到,而不需要main 函數(shù)中一個一個的順序執(zhí)行。

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

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

審核編輯:湯梓紅

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

    關(guān)注

    6026

    文章

    44456

    瀏覽量

    631052
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11177

    瀏覽量

    208499
  • STM32
    +關(guān)注

    關(guān)注

    2263

    文章

    10848

    瀏覽量

    353820
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4262

    瀏覽量

    62237
  • 函數(shù)指針
    +關(guān)注

    關(guān)注

    2

    文章

    56

    瀏覽量

    3768

原文標(biāo)題:在STM32上模擬Linux自動初始化

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    RT-Thread自動初始化詳解

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

    自動初始化機(jī)制原理詳解

    自動初始化機(jī)制是指初始化函數(shù)不需要被顯式調(diào)用,只需要在函數(shù)定義處通過宏定義的方式進(jìn)行申明,就會在系統(tǒng)啟動過程中被執(zhí)行。這篇文章就來探索一下其中的奧秘, 簡單理解其原理!
    的頭像 發(fā)表于 12-16 09:33 ?923次閱讀
    <b class='flag-5'>自動</b><b class='flag-5'>初始化</b>機(jī)制原理詳解

    LINUX系統(tǒng)引導(dǎo)和初始化-LINUX內(nèi)核解讀

    Linux 的系統(tǒng)引導(dǎo)和初始化 ----------Linux2.4.22內(nèi)核解讀之一 一、 系統(tǒng)引導(dǎo)和初始化概述 相關(guān)代碼(引導(dǎo)扇區(qū)的程序及其輔助程序,以 x86體系為例): \
    發(fā)表于 11-03 22:31 ?53次下載

    CR95HF 的初始化步驟

    STM32F103的CR95HF 的初始化步驟
    發(fā)表于 12-14 16:01 ?0次下載

    Linux內(nèi)存初始化

    之前有幾篇博客詳細(xì)介紹了Xen的內(nèi)存初始化,確實感覺這部分內(nèi)容蠻復(fù)雜的。這兩天在看Linux內(nèi)核啟動中內(nèi)存的初始化,也是看的云里霧里的,想嘗試下邊看邊寫,寫博客的過程中慢慢思考,最后
    發(fā)表于 10-12 11:16 ?0次下載

    ds1302時鐘芯片初始化,自動決定DS1302是否需要初始化程序

    ds1302芯片時鐘芯片大家都在問到底需要不需要初始化?這篇文章將會給大家一個程序,可以自動決定DS1302是否需要初始化。
    發(fā)表于 10-19 19:19 ?8423次閱讀

    stm32初始化流程圖解析

    STM32系列基于專為要求高性能、低成本、低功耗的嵌入式應(yīng)用專門設(shè)計的ARM Cortex-M3內(nèi)核。本文主要以stm32初始化流程而展開的討論。
    發(fā)表于 11-16 11:39 ?1.9w次閱讀
    <b class='flag-5'>stm32</b><b class='flag-5'>初始化</b>流程圖解析

    51平臺下初始化文件的引入導(dǎo)致全局變量無法初始化的問題如何解決

    本文檔的主要內(nèi)容詳細(xì)介紹的是51平臺下初始化文件的引入導(dǎo)致全局變量無法初始化的問題如何解決。
    發(fā)表于 08-20 17:31 ?0次下載
    <b class='flag-5'>在</b>51平臺下<b class='flag-5'>初始化</b>文件的引入導(dǎo)致全局變量無法<b class='flag-5'>初始化</b>的問題如何解決

    一文詳解RT-Thread自動初始化

    在學(xué)RT-Thread時,經(jīng)常能聽到這個詞:自動初始化。用起來也非常容易,一個宏就解決了,但是原理是什么呢?
    的頭像 發(fā)表于 07-21 10:17 ?7483次閱讀
    一文詳解RT-Thread<b class='flag-5'>自動</b><b class='flag-5'>初始化</b>

    STM32執(zhí)行代碼初始化卡住,或者電卡住,或者復(fù)位卡住,導(dǎo)致代碼不執(zhí)行

    STM32的板子電或者復(fù)位,接有顯示屏或者LED指示燈的都會卡住解決:1、檢查自己的代碼是否有中斷,有中斷的話,其初始化放在其他硬件初始化之后 即:中斷的
    發(fā)表于 12-09 09:21 ?22次下載
    <b class='flag-5'>STM32</b>執(zhí)行代碼<b class='flag-5'>初始化</b>卡住,或者<b class='flag-5'>上</b>電卡住,或者復(fù)位卡住,導(dǎo)致代碼不執(zhí)行

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

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

    如何對PNET 模擬器進(jìn)行初始化安裝

    今天給大家?guī)硪黄诟韶泝?nèi)容,關(guān)于模擬器, 這個模擬器就是PNET,今天給大家分享一下如何對PNET 模擬器進(jìn)行初始化安裝。
    的頭像 發(fā)表于 10-28 09:15 ?1883次閱讀

    DB2163_STM32配置和初始化C代碼生成

    DB2163_STM32配置和初始化C代碼生成
    發(fā)表于 11-23 20:29 ?0次下載
    DB2163_<b class='flag-5'>STM32</b>配置和<b class='flag-5'>初始化</b>C代碼生成

    使用STM32CubeMX生成初始化代碼

    我使用STM32CubeMX生成初始化代碼,使用LL庫,這里只介紹跟i2c相關(guān)的部分,其他必要的初始化需要自己完成。芯片使用stm32f042。本文的代碼不能到手即用,只提供思路。
    的頭像 發(fā)表于 03-22 15:26 ?2765次閱讀

    STM32 模擬Linux kernel自動初始化流程

    : 本次給大家轉(zhuǎn)來一篇:STM32 模擬Linux kernel自動初始化流程,這個機(jī)制 嵌入式大雜燴周記 | 第 4 期 中也有用到。文末
    的頭像 發(fā)表于 06-22 10:03 ?554次閱讀
    <b class='flag-5'>STM32</b> <b class='flag-5'>模擬</b><b class='flag-5'>Linux</b> kernel<b class='flag-5'>自動</b><b class='flag-5'>初始化</b>流程