剛從硬件跳槽為嵌軟時(shí),沒(méi)有任何一絲的準(zhǔn)備。一入職,領(lǐng)導(dǎo)就交代了一項(xiàng)特難的任務(wù)——在stm32上移植linux!
瞬間我就懵了,沒(méi)辦法硬著頭皮上吧,先搜集資料,我之前跑的是ok6410的板子上運(yùn)行的linux,現(xiàn)在是在stm32上移植,以前stm32倒是玩過(guò),研究生期間就搗鼓過(guò)它,但現(xiàn)在還沒(méi)從抓烙鐵的硬件當(dāng)中緩過(guò)神來(lái),就轉(zhuǎn)到嵌入式軟件的開發(fā),更頭疼的是stm32沒(méi)有MMU!沒(méi)有MMU!找了一下,好吧,有個(gè)uClinux!
于是開始學(xué)習(xí)各種相關(guān)的知識(shí),了解到linux的啟動(dòng)一般是u-boot——》liunx內(nèi)核——》根文件系統(tǒng),那么首先要做個(gè)基于stm32的u-boot,先初始化時(shí)鐘、外設(shè)、中斷什么的,看了韋東山老師的視頻感覺很好,理解了不少,從一無(wú)所知到有點(diǎn)明白了。
移植u-boot到stm32f407
其實(shí)說(shuō)白了u-boot就是一裸板程序,就是跟跑跑馬燈、串口通信一個(gè)性質(zhì)的,而裸板程序從正點(diǎn)原子的stm32開發(fā)板學(xué)習(xí)了不少,加上自己研究生階段有點(diǎn)積累,首先我是參照http://www.cnblogs.com/fozu/p/3618076.html寫這位博文的大神寫的程序,這篇文章寫得很好,后面還分析到內(nèi)核了,反復(fù)看受益匪淺,這個(gè)程序不是u-boot程序但是實(shí)現(xiàn)的作用一樣,初始化時(shí)鐘,外設(shè)。。。最后傳遞內(nèi)核參數(shù),跳轉(zhuǎn)內(nèi)核。。。,一開始用keil編譯這個(gè)程序,結(jié)果一堆錯(cuò)誤,人家用的板子和你用的板子不一樣,硬件的led燈、串口都可能連接不一樣啊,比如人家用的是串口1,你用的是串口2,還有缺少一些頭文件等等都會(huì)引發(fā)錯(cuò)誤,所以根據(jù)自己的實(shí)際來(lái)修改,費(fèi)了一陣功夫終于把錯(cuò)誤全干掉,順利編譯成功。
這時(shí)用的板子是stm32f103,ST對(duì)這個(gè)板子早在08年就發(fā)布了支持它的u-boot、Uclinux內(nèi)核(領(lǐng)導(dǎo)額外買的,說(shuō)是要我對(duì)照著對(duì)應(yīng)修改支持stm32f407的uClinux內(nèi)核),但是只有Uclinux內(nèi)核有源碼,u-boot就給了個(gè)hex文件尷尬,其實(shí)cortx m3與cortx m4之前架構(gòu)已經(jīng)大不一樣了,這樣修改的話對(duì)于我來(lái)說(shuō)無(wú)疑是很難的,我一聽頭都大了,又是單干,煩,沒(méi)辦法照做唄!那就先弄stm32f103的,把之前那個(gè)編譯沒(méi)有錯(cuò)誤的引導(dǎo)程序拷入,在stm32的0x08003000的位置拷入官方提供的uClinux內(nèi)核,一啟動(dòng),接上串口,打開串口助手,一看啥都沒(méi)有。。。
到底錯(cuò)在哪啦?仔細(xì)想想,先是要看看最后跳轉(zhuǎn)內(nèi)核那步到底有沒(méi)有成功,那就先驗(yàn)證這一步,參照原子的IAR跳轉(zhuǎn)歷程,編了個(gè)跑馬燈跳轉(zhuǎn)程序,就是引導(dǎo)程序沒(méi)變,拷在地址0x08000000,而跑馬燈程序拷在0x08003000上,如果led燈亮滅就說(shuō)明跳轉(zhuǎn)無(wú)誤,于是一啟動(dòng),燈不亮。抓狂抓狂怎么情況啊,后仔細(xì)排查發(fā)現(xiàn)是跳轉(zhuǎn)函數(shù),引導(dǎo)程序參照的是u-boot源碼來(lái)編寫的,里面的函數(shù)用函數(shù)指針賦個(gè)地址(0x08003000),最后跳轉(zhuǎn)過(guò)去。折騰了兩天最后對(duì)著原子的程序修改,燈居然可以亮滅了,我現(xiàn)在想想也不知道是什么問(wèn)題,不過(guò)至少現(xiàn)在可以實(shí)現(xiàn)跳轉(zhuǎn)了。
再把內(nèi)核拷到0x08003000,一啟動(dòng),串口助手還是沒(méi)有任何輸出,這下就真的煩了,郁悶死了,stm32f103還搞不定還想搞stm32f407。。。之后開始各種找原因,各種修改,領(lǐng)導(dǎo)各種催,在stm32f103和stm32f407兩個(gè)板子之間這搞搞,那搞搞,休息時(shí)間就看看韋老師的視頻,找資料看看有什么靈感,但是還是沒(méi)什么進(jìn)展。
后來(lái)在網(wǎng)上搜到一個(gè)哥們居然在stm32f407上移植u-boot成功了,而且還有啟動(dòng)圖曬出來(lái),這下我就想,人家可以我為什么就不能?于是繼續(xù)找,終于在網(wǎng)上找到了這個(gè)u-boot的源碼,根據(jù)自己的stm32f407的板子修改串口,時(shí)鐘等,安裝好對(duì)應(yīng)的交叉編譯鏈,注意應(yīng)該是arm-non-eabi不帶linux的,因?yàn)槭锹惆宄绦虿魂P(guān)linux啥事,然后一跑,終于在串口助手看到久違的u-boot啟動(dòng)圖,狂喜!想想那段日子確實(shí)是在壓力之下成長(zhǎng)的,感覺技術(shù)上有了很大的提升了。
領(lǐng)導(dǎo)過(guò)來(lái)一看見有u-boot(有點(diǎn)東西交差了。。。)就說(shuō)要把外部的SRAM驅(qū)動(dòng)加上,以便于跑linux內(nèi)核,這個(gè)sram只有512K,這么小能跑得了linux內(nèi)核嗎?這是后話,先把sram驅(qū)動(dòng)加到u-boot上再說(shuō)。
先參照原子的sram程序修改運(yùn)行試試看看,結(jié)果可以運(yùn)行但是寫入再讀出,有幾個(gè)地址的數(shù)據(jù)總有錯(cuò)誤,于是一直苦思冥想,想到了一個(gè)可能,驅(qū)動(dòng)外部SRAM用到的是stm32的FSMC配置,它有btcr寄存器設(shè)置,分為bcr和btr設(shè)置,原子的開發(fā)板用的是1M16位的,而我的是512k8位,在btr寄存器設(shè)置那里應(yīng)該是設(shè)成8位而不是16位,于是把相關(guān)設(shè)置位置0,這下數(shù)據(jù)正常了。
接下來(lái)就是在u-boot上添加sram的驅(qū)動(dòng),這個(gè)u-boot編寫得還蠻好,不過(guò)它配置的是外部8M的SDRAM,那么我就在sdram_init()的函數(shù)上添加配置sram的代碼,把原來(lái)配置sdram的代碼通通刪去。折騰了兩天,編寫修改成功,一開機(jī),串口助手正常輸出啟動(dòng)信息,用u-boot的md、mw指令驗(yàn)證sram的驅(qū)動(dòng)是否可行,之間也遇到一些問(wèn)題,如在前100個(gè)地址寫ff,md查看有幾個(gè)地址數(shù)據(jù)不對(duì),不是顯示ff,用之前的sram裸板程序也是如此,一想軟件程序肯定是沒(méi)問(wèn)題,那就是硬件問(wèn)題,幸虧還搞過(guò)一段時(shí)間硬件,不然被公司硬件工程師給坑了,用萬(wàn)用表仔細(xì)檢測(cè),果然發(fā)現(xiàn)sram有幾個(gè)數(shù)據(jù)線虛焊了,怪不得數(shù)據(jù)有誤,拿烙鐵一拖,OK!數(shù)據(jù)正常了,嗯!想成為合格的嵌入式軟件工程師還是要軟件硬件相結(jié)合,不能脫離了硬件啊!!!!
好!至此基于stm32f407的u-boot移植成功,外加外部2M的SRAM驅(qū)動(dòng)(后來(lái)把512K升級(jí)為2M,因?yàn)楹髞?lái)內(nèi)核內(nèi)存不夠跑到一半kernel panic掛了,此乃后話),最后上一張u-boot啟動(dòng)圖。人生第一篇在CSDN的博文,希望以后自己不斷學(xué)習(xí)技術(shù)不斷提升,努力!
移植uClinux內(nèi)核到stm32f407
上面介紹了先移植基于stm32f407的u-boot,下面會(huì)講到其中最難的移植stm32f407的內(nèi)核這部分,這個(gè)內(nèi)核源代碼我也是在網(wǎng)上找到了,看介紹是國(guó)外大神修改而成的,真的萬(wàn)分感謝這位大神,網(wǎng)上的資源其實(shí)很多,要善于挖掘,善于搜尋。
內(nèi)核代碼是我無(wú)意中down下來(lái)的,剛得到代碼時(shí)并沒(méi)有對(duì)在stm32f407上跑uClinux有太多的信心,一是網(wǎng)上還沒(méi)有在stm32f407跑uClinux的資料(至少我沒(méi)找到過(guò))網(wǎng)上都對(duì)在stm32上跑uClinux都是唱衰的態(tài)度,的確stm32跑起uClinux系統(tǒng),資源是有些匱乏,而stm32f407內(nèi)部flash只有1M的空間,其中u-boot占了128K,那么內(nèi)核就存儲(chǔ)在0x08020000處,剩下900k的空間使用,還有我的板子還有外部2M 的SRAM,但更要命的是得到的代碼是基于stm32f429的uClinux,很多人都在stm32f429上成功運(yùn)行了,但是卻從沒(méi)在stm32f407成功過(guò),但我已經(jīng)沒(méi)有退路了,項(xiàng)目需要、領(lǐng)導(dǎo)要求,只能硬著頭皮瞎改,其實(shí)對(duì)于stm32f103改成stm32f429已經(jīng)好很多了,最起碼stm32f429的架構(gòu)和stm32f407的架構(gòu)大致相同(內(nèi)部存儲(chǔ)和時(shí)鐘和gpio等略有不同),于是就按照自己手上的板子來(lái)改,期間遇到了不少的問(wèn)題,也想過(guò)放棄,不過(guò)好歹堅(jiān)持了下來(lái),因?yàn)橹眽毫ι酱笏钥戳瞬簧贂?,查了很多資料也學(xué)到了很多東西對(duì)u-boot和內(nèi)核代碼有了深入的理解,
特別感謝的是jserv老師,我走投無(wú)路之下給他發(fā)了幾封郵件,他回答了我兩個(gè)極為重要的問(wèn)題,建議把外部的512K換成至少2M的SRAM,不然內(nèi)核就真的跑不動(dòng)了,跑到一半就kernel panic….
然后就是針對(duì)stm32f407來(lái)修改內(nèi)核代碼,stm32f429用的是串口3,我用的是串口1,改!時(shí)鐘不對(duì),改!儲(chǔ)存地址不同,改!stm32f429不單是有外部的SRAM,空間8M還有NOR flash,財(cái)大氣粗,資源隨便用,不像我的stm32f407只有外部2M的SRAM(領(lǐng)導(dǎo)說(shuō)硬件就那樣,節(jié)約成本,無(wú)語(yǔ)。。),幸好uClinux代碼是用XIP的方式來(lái)運(yùn)行的,就是代碼段放在內(nèi)部flash中就地執(zhí)行,數(shù)據(jù)段和bss段其它段就放在sram上運(yùn)行,這樣算算,空間還是足夠的。
其間還出現(xiàn)這樣的問(wèn)題:
卡了我一個(gè)星期,當(dāng)時(shí)我就百思不得其解,在創(chuàng)建高速緩存那里就出現(xiàn)內(nèi)核錯(cuò)誤運(yùn)行不下去了,仔細(xì)比對(duì)了stm32f103的uClinux源代碼,也沒(méi)發(fā)現(xiàn)什么錯(cuò)誤,一個(gè)多星期沒(méi)有進(jìn)展,內(nèi)核恐慌我也恐慌了,幸好領(lǐng)導(dǎo)知道情況后也不催促我,而是買了一本《ARM Linux內(nèi)核源代碼分析》給我,叫我好好研讀,解決問(wèn)題,于是就看里面構(gòu)建kmem cache那一篇,linux內(nèi)核源碼過(guò)于復(fù)雜,看得我頭都大了,后來(lái)想想這不是辦法啊,是不是又是硬件問(wèn)題?因?yàn)樵扔玫氖?12k的sram升級(jí)到2M,公司的硬件工程師又重新改版了,于是我又用電烙鐵把stm32芯片,sram芯片,和他們之間的上拉電阻,又重新焊了一遍,一上電就正常運(yùn)行到下一步了,唉~之前移植u-boot的sram驅(qū)動(dòng)也是硬件坑我的啊,真不敢相信我不懂點(diǎn)硬件的話會(huì)坑到我什么時(shí)候。。。
接著瞎搗鼓著,前后花了將近兩個(gè)月,就成這樣了:
- 想想還真是運(yùn)氣好。。。
接下來(lái)遇到的問(wèn)題,應(yīng)該是少了根文件系統(tǒng),這個(gè)uClinux代碼原來(lái)是配有根文件系統(tǒng)的,是romfs,但是存儲(chǔ)空間不夠了。
uClinux的根文件系統(tǒng)未能掛載起來(lái),因?yàn)橄到y(tǒng)原來(lái)配置的根文件系統(tǒng)是romfs,是基于stm32f429的,stm32f429的內(nèi)部flash存儲(chǔ)空間有2M,romfs占用空間為300多kB,這樣存放顯然是充足的,但是對(duì)于stm32f407來(lái)說(shuō),它的內(nèi)部flash存儲(chǔ)空間為1M,這樣存放的話,存儲(chǔ)空間是不夠的(u-boot占用空間0x08000000-0x08020000,內(nèi)核占用空間約為0x08020000-0x080BB000,約620多KB,那么只有剩下約250多KB的空間供根文件系統(tǒng)存放),所以根據(jù)這個(gè)情況,我想是另外搭建占用內(nèi)存空間更小的initramfs作為uClinux的根文件系統(tǒng)來(lái)掛載。
構(gòu)建stm32f407-uClinux的initramfs根文件系統(tǒng)
上文講到內(nèi)核運(yùn)行到free init memory:8k這個(gè)地方就卡住,運(yùn)行不下去了,在查閱了相關(guān)資料后,推測(cè)是缺少根文件系統(tǒng)所導(dǎo)致的,原來(lái)的內(nèi)核源代碼是搭配有根文件系統(tǒng)的bin文件,是romfs但沒(méi)有源碼,前面講過(guò)我現(xiàn)在項(xiàng)目使用的是stm32f407,內(nèi)部flash容量和外部SRAM都不足以拷入這個(gè)原配的romfs掛起為根文件系統(tǒng)來(lái)使用。
接下來(lái)就是尋找一種經(jīng)濟(jì)適用的文件系統(tǒng)來(lái)作為內(nèi)核的根文件系統(tǒng),從網(wǎng)上查閱相關(guān)資料可以知道,YAFFS2支持的是nandflash,jffs支持nor flash,這些看來(lái)對(duì)于我手上的stm32f407來(lái)說(shuō)是不適用的,于是我仔細(xì)研究了stm32f103的源代碼,發(fā)現(xiàn)它是有兩種啟動(dòng)的方式,一種采用的是用iniramfs作為根文件系統(tǒng),xip啟動(dòng),在stm32f103內(nèi)部flash只有512k的情況居然跑起了Uclinux,另一種是jfss2掛在外部nor flash上,顯然我這種情況目前只有參考第一種方式來(lái),采用initramfs作為根文件系統(tǒng)。于是開始構(gòu)建initramfs相關(guān)文件。 仔細(xì)研究stm32f103 XIP啟動(dòng)方式的內(nèi)核配置make menuconfig中, CONFIG_INITRAMFS_SOURCE=”initramfs-filelist” 而initramfs-filelist位于Uclinux/linux-2.6.x下,打開一看是這樣的:
一開始我看不懂這里面的shell什么意思,網(wǎng)上找到一篇文章,寫得很清楚,把它c(diǎn)opy過(guò)來(lái),學(xué)習(xí)一下:
把initramfs編譯到內(nèi)核里面去
使用initramfs最簡(jiǎn)單的方式,莫過(guò)于用已經(jīng)做好的cpio.gz把kernel里面那個(gè)空的給換掉。這是2.6 kernel天生支持的,所以,你不用做什么特殊的設(shè)置。
kernel的config option里面有一項(xiàng)CONFIG_INITRAMFS_SOURCE(I.E. General setup—>Initramfs source file(s) in menuconfig)。這個(gè)選項(xiàng)指向放著內(nèi)核打包initramfs需要的所有文件。默認(rèn)情況下,這個(gè)選項(xiàng)是留空的,所以內(nèi)核編譯出來(lái)之后initramfs也就是空的,也就是前面提到的rootfs什么都不做的情形。
CONFIG_INITRAMFS_SOURCE 可以是一個(gè)絕對(duì)路徑,也可以是一個(gè)從kernel’s top build dir(你敲入build或者是make的地方)開始的相對(duì)路徑。而指向的目標(biāo)可以有以下三種:一個(gè)已經(jīng)做好的cpio.gz,或者一個(gè)已經(jīng)為制作cpio.gz準(zhǔn)備好所有內(nèi)容的文件夾,或者是一個(gè)text的配置文件。第三種方式是最靈活的,我們先依次來(lái)介紹這三種方法。
1)使用一個(gè)已經(jīng)做好的cpio.gz檔案
If you already have your own initramfs_data.cpio.gz file (because you created it yourself, or saved the cpio.gz file produced by a previous kernel build), you can point CONFIG_INITRAMFS_SOURCE at it and the kernel build will autodetect the file type and link it into the resulting kernel image.
You can also leave CONFIG_INITRAMFS_SOURCE empty, and instead copy your cpio.gz file to usr/initramfs_data.cpio.gz in your kernel’s build directory. The kernel’s makefile won’t generate a new archive if it doesn’t need to.
Either way, if you build a kernel like this you can boot it without supplying an external initrd image, and it’ll still finish its boot by running your init program out of rootfs. This is packaging method #2, if you’d like to try it now.
2)指定給內(nèi)核一個(gè)文件或者文件夾
If CONFIG_INITRAMFS_SOURCE points to a directory, the kernel will archive it up for you. This is a very easy way to create an initramfs archive, and is method #3.
Interestingly, the kernel build doesn’t use the standard cpio command to create initramfs archives. You don’t even need to have any cpio tools installed on your build system. Instead the kernel build (in usr/Makefile) generates a text file describing the directory with the script “gen_initramfs_list.sh”, and then feeds that descript to a program called “gen_init_cpio” (built from C source in the kernel’s usr directory), which create the cpio archive. This looks something like the following:
scripts/gen_initramfs_list.sh $CONFIG_INITRAMFS_SOURCE > usr/initramfs_list
usr/gen_init_cpio usr/initramfs_list > usr/initramfs_data.cpio
gzip usr/initramfs_data.cpio
To package up our hello world program, you could simply copy it into its own directory, name it “init”, point CONFIG_INITRAMFS_SOURCE at that directory, and rebuild the kernel. The resulting kernel should end its boot by printing “hello world”. And if you need to tweak the contents of that directory, rebuilding the kernel will re-package the contents of that directory if anything has changed.
The downside of this method is that it if your initramfs has device nodes, or cares about file ownership and permissions, you need to be able to create those things in a directory for it to copy. This is hard to do if you haven’t got root access, or are using a cross-compile environment like cygwin. That’s where the fourth and final method comes in.
3)使用configuration文件initramfs_list來(lái)告訴內(nèi)核initramfs在哪里
This is the most flexible method. The kernel’s gen_initramfs_list.sh script creates a text description file listing the contents of initramfs, and gen_init_cpio uses this file to produce an archive. This file is a standard text file, easily editable, containing one line per file. Each line starts with a keyword indicating what type of entry it describes.
The config file to create our “hello world” initramfs only needs a single line:
file /init usr/hello 500 0 0
This takes the file “hello” and packages it so it shows up as /init in rootfs, with permissions 500, with uid and gid 0. It expects to find the source file “hello” in a “usr” subdirectory under the kernel’s build directory. (If you’re building the kernel in a different directory than the source directory, this path would be relative to the build directory, not the source directory.)
To try it yourself, copy “hello” into usr in the kernel’s build directory, copy the above configuration line to its own file, use “make menuconfig” to point CONFIG_INITRAMFS_SOURCE to that file, run the kernel build, and test boot the new kernel. Alternately, you can put the “hello” file in its own directory and use “scripts/gen_initramfs_list.sh dirname” to create a configuration file (where dirname is the path to your directory, from the kernel’s build directory). For large projects, you may want to generate a starting configuration with the script, and then customize it with any text editor.
This configuration file can also specify device nodes (with the “nod” keyword), directories (“dir”), symbolic links (“slink”), named FIFO pipes (“pipe”), and unix domain sockets (“sock”). Full documentation on this file’s format is available by running “usr/gen_init_cpio” (with no arguments) after a kernel build.
A more complicated example containing device nodes and symlinks could look like this:
dir /dev 755 0 0
nod /dev/console 644 0 0 c 5 1
nod /dev/loop0 644 0 0 b 7 0
dir /bin 755 1000 1000
slink /bin/sh busybox 777 0 0
file /bin/busybox initramfs/busybox 755 0 0
dir /proc 755 0 0
dir /sys 755 0 0
dir /mnt 755 0 0
file /init initramfs/init.sh 755 0 0
One significant advantage of the configuration file method is that any regular user can create one, specifying ownership and permissions and the creation of device nodes in initramfs, without any special permissions on the build system. Creating a cpio archive using the cpio command line tool, or pointing the kernel build at a directory, requires a directory that contains everything initramfs will contain. The configuration file method merely requires a few source files to get data from, and a description file.
This also comes in handy cross-compiling from other environments such as cygwin, where the local filesystem may not even be capable of reproducing everything initramfs should have in it.
總結(jié)一下
這四種給rootfs提供內(nèi)容的方式都有一個(gè)共同點(diǎn):在kernel啟動(dòng)時(shí),一系列的文件被解壓到rootfs,如果kernel能在其中找到可執(zhí)行的文件“/init”,kernel就會(huì)運(yùn)行它;這意味著,kernel不會(huì)再去理會(huì)“root=”是指向哪里的。
此外,一旦initramfs里面的init 進(jìn)程運(yùn)行起來(lái),kernel就會(huì)認(rèn)為啟動(dòng)已經(jīng)完成。接下來(lái),init將掌控整個(gè)宇宙!它擁有霹靂無(wú)敵的專門為它預(yù)留的Process ID #1,整個(gè)系統(tǒng)接下來(lái)的所有都將由它來(lái)創(chuàng)造!還有,它的地位將是不可剝奪的,嗯哼,PID 1 退出的話,系統(tǒng)會(huì)panic的。
接下來(lái)我會(huì)介紹其他一些,在rootfs中,init程序可以做的事。
Footnote 1: The kernel doesn’t allow rootfs to be unmounted for the same reason the same reason it won’t let the first process (PID 1, generally running init) be killed. The fact the lists of mounts and processes are never empty simplifies the kernel’s implementation.
Footnote 2: The cpio format is another way of combining files together, like tar and zip. It’s an older and simpler storage format that dates back to the original unix, and it’s the storage format used inside RPM packages. It’s not as widely used as tar or zip because the command line syntax of the cpio command is unnecessarily complicated (type “man 1 cpio” at a Linux or Cygwin command line if you have a strong stomach). Luckily, we don’t need to use this command.
Footnote 3: The kernel will always panic if PID 1 exits; this is unrelated to initramfs. All of the signals that might kill init are blocked, even “kill -9” which will reliably kill any other process. But init can still call the exit() syscall itself, and the kernel panics if this happens in PID 1. Avoiding it here is mostly a cosmetic issue: we don’t want the panic scrolling our “Hello World!” message off the top of the screen.
Footnote 4: Statically linking programs against glibc produces enormous, bloated binaries. Yes, this is expected to be over 400k for a hello world proram. You can try using the “strip” command on the resulting binary, but it won’t help much. This sort of bloat is why uClibc exists.
Footnote 5: Older 2.6 kernels had a bug where they would append to duplicate files rather than overwriting. Test your kernel version before depending on this behavior.
Footnote 6:User Mode Linux or QEMU can be very helpful testing out initramfs, but are beyond the scope of this article.
Footnote 7: Well, sort of. The default one is probably meant to be empty, but due to a small bug (gen_initramfs_list.sh spits out an example file when run with no arguments) the version in the 2.6.16 kernel actually contains a “/dev/console” node and a “/root” directory, which aren’t used for anything. It gzips down to about 135 bytes, and might as well actually be empty. On Intel you can run “readelf -S vmlinux” and look for section “.init.ramfs” to see the cpio.gz archive linked into a 2.6 kernel. Elf section names might vary a bit on other platforms.
顯然stm32f103使用的是第三種方法,里面那些指令無(wú)非是設(shè)置文件權(quán)限、設(shè)置軟連接等等操作,期間還學(xué)了一點(diǎn)bash shell,又有點(diǎn)收獲,明白了道理之后就好辦了,直接照貓畫虎,我采用的是第二種方法:
1、先創(chuàng)建rootfs這個(gè)文件夾,再在這個(gè)文件夾下面分別創(chuàng)建bin、dev、etc、proc、sys等目錄
2、編譯busybox,把生成的bin文件復(fù)制到rootfs/bin下
3、新建linuxrc文件,設(shè)置權(quán)限chmod 777,然后在u-boot傳給內(nèi)核參數(shù)中一定要加上init=/linuxrc
4、在dev目錄下,加設(shè)備節(jié)點(diǎn),不然會(huì)沒(méi)有輸出信息哦!
· 1 mknod -m 666 console c 5 1
· 2 mknod -m 666 null c 1 3
5、在內(nèi)核make menuconfig上CONFIG_INITRAMFS_SOURCE=“你剛剛構(gòu)建的文件夾的絕對(duì)路徑”
編譯內(nèi)核,initramfs直接和內(nèi)核編譯在一起,不用另外分出一個(gè)bin文件拷,這比較方便,啟動(dòng),在串口調(diào)試助手中可看到相關(guān)顯示信息:
最后說(shuō)一下自己的感想,用initramfs根文件系統(tǒng)雖然方便實(shí)用,但是有弊端就是它只讀不可寫,這對(duì)開發(fā)很不利,領(lǐng)導(dǎo)說(shuō)會(huì)加個(gè)spi flash再在里面掛載個(gè)根文件系統(tǒng)(spi flash能掛jfss2嗎?),那是以后的事了以后再說(shuō),目前這種情況以我的技術(shù)水平只能做到這個(gè)份上了,加了根文件之后,stm32內(nèi)部flash還有200多k的存儲(chǔ)空間,應(yīng)該可以添加些驅(qū)動(dòng)和應(yīng)用程序,那下面我的任務(wù)是編寫簡(jiǎn)單的驅(qū)動(dòng)與應(yīng)用程序,好吧,又得繼續(xù)學(xué)習(xí),努力工作了。
-
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209322 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355721
原文標(biāo)題:如何在STM32上移植Linux?超詳細(xì)的實(shí)操經(jīng)驗(yàn)分享
文章出處:【微信號(hào):WW_CGQJS,微信公眾號(hào):傳感器技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論