210串口控制台-210移植printf不好使
生活随笔
收集整理的這篇文章主要介紹了
210串口控制台-210移植printf不好使
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
210串口控制臺(tái)-問題描述
當(dāng)210做到串口控制臺(tái)發(fā)現(xiàn)按照視頻及210故障分析之后卻發(fā)現(xiàn)仍然不好使,
這個(gè)是因?yàn)橐曨l中老師的代碼中去除了一部分之前課程中與串口控制臺(tái)無關(guān)部分的代碼,
這邊正常大家應(yīng)該會(huì)發(fā)現(xiàn),移植內(nèi)核中printf函數(shù)還是會(huì)不好使,但是基本的串口打印是正常的,
首先我們先得分析一下這邊主要的原因,如果細(xì)心的同學(xué)應(yīng)該會(huì)發(fā)現(xiàn),
當(dāng)我們加入內(nèi)核printf的代碼之后,編譯出來的檔案會(huì)大于16K,
我們查找?S5PV210_iROM_ApplicationNote_Preliminary.pdf 這份文件,
?
可以發(fā)現(xiàn)手冊(cè)中有這個(gè)部分的操作順序,上電之后首先會(huì)運(yùn)行在iROM中BL0里廠商固化好的代碼,
并且把用戶的BL1部分(只有16K)復(fù)制到了SRAM中(起始地址是0xD0020010,其中0xD0020000~0xD0020010是210加頭的部份),
按照?qǐng)D中順序用戶應(yīng)該要在BL1中將BL2(超過16K的部份),自己復(fù)制到SRAM中,
整個(gè)SRAM中有96K,如果整個(gè)Bootloader還超過就要在BL2中將剩馀代碼復(fù)制到內(nèi)存SDRAM中,
因此我們發(fā)現(xiàn)最大的問題應(yīng)該就出在BL0只復(fù)制16K上,按手冊(cè)要求,也為了之后的實(shí)驗(yàn),
我們?cè)谶@里需要把我們的裸機(jī)代碼分成BL1跟BL2兩個(gè)部分,這樣才能解決不好使的問題
210串口控制臺(tái)-BL0廠商固化代碼
如果你看過答疑助手-許老師的BL1部分代碼,你會(huì)發(fā)現(xiàn)許老師在BL1中根本沒有做內(nèi)存初始化,
直接就使用C語言,我們都知道C語言必須先要設(shè)置堆棧指針,而且堆棧指針會(huì)指向內(nèi)存,
但是這個(gè)時(shí)候我們內(nèi)存初始化都還沒做呢,怎么可能會(huì)把指針指向內(nèi)存,
其實(shí)答案就出在BL0廠商固化代碼中,210跟2440、6410的啟動(dòng)流程最大不一樣的地方,
就在這個(gè)BL0廠商固化代碼中,首先從手冊(cè)可以找到這個(gè)BL0干了什么
?
1.關(guān)閉看門狗計(jì)時(shí)器
2.初始化 iCache
3.初始化棧
4.初始化堆
5.初始化塊設(shè)備復(fù)制函數(shù)
6.初始化鎖相環(huán)并且設(shè)定系統(tǒng)時(shí)鐘
7.復(fù)制用戶代碼BL1到SRAM中
8.檢查BL1的校驗(yàn)值
9.檢查是否為安全啟動(dòng)模式
10.跳轉(zhuǎn)到用戶的BL1繼續(xù)執(zhí)行
也就是說BL0中其實(shí)已經(jīng)為我們初始化好堆棧了并且可以參考下面的內(nèi)存地址分布來看一下
?
210串口控制臺(tái)-BL1、BL2分別需要完成的代碼
知道了BL0都干了什么之后,我們就知道其實(shí)BL1中最重要就是把BL2的代碼復(fù)制到SRAM或者是內(nèi)存
因?yàn)槲覀兊膗boot很容易就超過80K所以我們就乾脆不復(fù)制到SRAM而直接復(fù)制到內(nèi)存了,
復(fù)制到內(nèi)存之后當(dāng)然還必須跳轉(zhuǎn)到內(nèi)存去執(zhí)行,而BL2就是我們正常的uboot或者是裸機(jī)了,
而在BL1中的復(fù)制代碼首先要考慮的就是從哪里復(fù)制、復(fù)制到哪里、怎么復(fù)制,
下面整理了BL1的這幾個(gè)問題
1.從哪里復(fù)制:我們的代碼是下載到nand中的所以當(dāng)然是從nand復(fù)制這個(gè)肯定是沒問題的,
當(dāng)然使用nand之前當(dāng)然得初始化nand
2.復(fù)制到哪:這個(gè)剛剛已經(jīng)知道了我們直接復(fù)制到內(nèi)存(SDRAM)中,這個(gè)也應(yīng)該沒問題
3.怎么復(fù)制:
(a)首先按照課程自己初始化nand自己寫的復(fù)制函數(shù),當(dāng)然沒有問題,但是要注意的是nand的地址,
老師視頻中的nand地址的寫法是針對(duì)塊來寫的,建議大家可以參考yang的代碼按手冊(cè)按不同的nand,
寫成標(biāo)準(zhǔn)的列+行地址的方式
?
(b)前面我們說到了BL0初始化了一個(gè)塊設(shè)備復(fù)制函數(shù),我們可不可以使用呢?當(dāng)然是可以使用
手冊(cè)提到了下面的說明
?
怎么使用呢可以先定義
#define NF8_ReadPage_Adv(a,b,c) (((int(*)(unsigned int, unsigned int, unsigned char*))(*((unsigned int *)0xD0037F90)))(a,b,c))
然后復(fù)制的時(shí)候
?
需要注意的是這個(gè)函數(shù)的輸入部分是數(shù)據(jù)所在的塊跟所在的頁,而不是頁偏移,因?yàn)槭菈K設(shè)備復(fù)制
(c)另外值得注意的是我們自己寫的nand復(fù)制函數(shù)其實(shí)沒有考慮過ecc,因?yàn)閚and存儲(chǔ)的數(shù)據(jù)很容易會(huì)出錯(cuò),
所以nand有個(gè)ecc的校驗(yàn)機(jī)制,其實(shí)我們?cè)诳磏and的手冊(cè)仔細(xì)點(diǎn)就可以看出端倪,
?
也就是這個(gè)部分,多出的這些字節(jié)其實(shí)就是存放ecc校驗(yàn)碼的,至于算法有興趣的可以參考yang的代碼
最后就是從nand的哪個(gè)地址開始復(fù)制,首先分為SLC跟MLC兩種flash
正常大家應(yīng)該使用的都是SLC的版本,下一節(jié)會(huì)提到BL1跟BL2的分割方式,
假設(shè)BL1加頭之后填充到4K,并且把BL2附加在后面那么實(shí)際上就是從nand4K的位置開始復(fù)制,
如果BL1加頭之后填充到16K,并且把BL2附加在后面那么實(shí)際上就是從nand16K的位置開始復(fù)制
另外提一下在210手冊(cè)523頁有一個(gè)OM腳的變量可以用來判斷是怎么啟動(dòng)的
?
固化代碼中還有從SD卡復(fù)制代碼的函數(shù)有興趣的可以參考yang的代碼判斷OM假設(shè)從SD卡啟動(dòng),
就從SD卡復(fù)制剩下的代碼BL2到內(nèi)存。
210串口控制臺(tái)-鏈接地址與BL1、BL2的分割方式
首先我們知道BL1是復(fù)制到SRAM中去執(zhí)行的,在BL1中我們基本上只有在跳轉(zhuǎn)BL2的時(shí)候使用絕對(duì)跳轉(zhuǎn),
剩下的地方都不會(huì)使用絕對(duì)跳轉(zhuǎn),所以BL1的鏈接地址實(shí)際上沒有多大的作用,
而BL2的鏈接地址因?yàn)槭翘D(zhuǎn)到內(nèi)存中的,并且是我們主要的程序部分,
加上需要處理中段向量,因此這個(gè)鏈接地址就非常重要了,
如果我們的代碼最終是復(fù)制到0x20008000這個(gè)地址并且跳轉(zhuǎn)到這個(gè)地址的,
那我們的鏈接地址就必須是0x20008000,也就是說鏈接地址與代碼實(shí)際的地址必須保持一致
?
至于怎么把代碼分割成BL1跟BL2實(shí)際上的作法是做兩個(gè)代碼分別編譯,
并且保證BL1小于16K,把BL1加頭之后擴(kuò)展到一定的大小,再把BL2附加在BL1后面
?
BL1的Makefile先把BL1編譯之后加頭
?
頂層的Makefile實(shí)際上就是把已經(jīng)加完頭的spl_210.bin 擴(kuò)展成16K,然后再把編譯完的BL2,
連接,實(shí)際上因?yàn)樵?10的頭中有BL1的實(shí)際大小,因此如果你的BL1不到16K也就不需要一定得擴(kuò)展到16K
當(dāng)210做到串口控制臺(tái)發(fā)現(xiàn)按照視頻及210故障分析之后卻發(fā)現(xiàn)仍然不好使,
這個(gè)是因?yàn)橐曨l中老師的代碼中去除了一部分之前課程中與串口控制臺(tái)無關(guān)部分的代碼,
這邊正常大家應(yīng)該會(huì)發(fā)現(xiàn),移植內(nèi)核中printf函數(shù)還是會(huì)不好使,但是基本的串口打印是正常的,
首先我們先得分析一下這邊主要的原因,如果細(xì)心的同學(xué)應(yīng)該會(huì)發(fā)現(xiàn),
當(dāng)我們加入內(nèi)核printf的代碼之后,編譯出來的檔案會(huì)大于16K,
我們查找?S5PV210_iROM_ApplicationNote_Preliminary.pdf 這份文件,
?
可以發(fā)現(xiàn)手冊(cè)中有這個(gè)部分的操作順序,上電之后首先會(huì)運(yùn)行在iROM中BL0里廠商固化好的代碼,
并且把用戶的BL1部分(只有16K)復(fù)制到了SRAM中(起始地址是0xD0020010,其中0xD0020000~0xD0020010是210加頭的部份),
按照?qǐng)D中順序用戶應(yīng)該要在BL1中將BL2(超過16K的部份),自己復(fù)制到SRAM中,
整個(gè)SRAM中有96K,如果整個(gè)Bootloader還超過就要在BL2中將剩馀代碼復(fù)制到內(nèi)存SDRAM中,
因此我們發(fā)現(xiàn)最大的問題應(yīng)該就出在BL0只復(fù)制16K上,按手冊(cè)要求,也為了之后的實(shí)驗(yàn),
我們?cè)谶@里需要把我們的裸機(jī)代碼分成BL1跟BL2兩個(gè)部分,這樣才能解決不好使的問題
210串口控制臺(tái)-BL0廠商固化代碼
如果你看過答疑助手-許老師的BL1部分代碼,你會(huì)發(fā)現(xiàn)許老師在BL1中根本沒有做內(nèi)存初始化,
直接就使用C語言,我們都知道C語言必須先要設(shè)置堆棧指針,而且堆棧指針會(huì)指向內(nèi)存,
但是這個(gè)時(shí)候我們內(nèi)存初始化都還沒做呢,怎么可能會(huì)把指針指向內(nèi)存,
其實(shí)答案就出在BL0廠商固化代碼中,210跟2440、6410的啟動(dòng)流程最大不一樣的地方,
就在這個(gè)BL0廠商固化代碼中,首先從手冊(cè)可以找到這個(gè)BL0干了什么
?
1.關(guān)閉看門狗計(jì)時(shí)器
2.初始化 iCache
3.初始化棧
4.初始化堆
5.初始化塊設(shè)備復(fù)制函數(shù)
6.初始化鎖相環(huán)并且設(shè)定系統(tǒng)時(shí)鐘
7.復(fù)制用戶代碼BL1到SRAM中
8.檢查BL1的校驗(yàn)值
9.檢查是否為安全啟動(dòng)模式
10.跳轉(zhuǎn)到用戶的BL1繼續(xù)執(zhí)行
也就是說BL0中其實(shí)已經(jīng)為我們初始化好堆棧了并且可以參考下面的內(nèi)存地址分布來看一下
?
210串口控制臺(tái)-BL1、BL2分別需要完成的代碼
知道了BL0都干了什么之后,我們就知道其實(shí)BL1中最重要就是把BL2的代碼復(fù)制到SRAM或者是內(nèi)存
因?yàn)槲覀兊膗boot很容易就超過80K所以我們就乾脆不復(fù)制到SRAM而直接復(fù)制到內(nèi)存了,
復(fù)制到內(nèi)存之后當(dāng)然還必須跳轉(zhuǎn)到內(nèi)存去執(zhí)行,而BL2就是我們正常的uboot或者是裸機(jī)了,
而在BL1中的復(fù)制代碼首先要考慮的就是從哪里復(fù)制、復(fù)制到哪里、怎么復(fù)制,
下面整理了BL1的這幾個(gè)問題
1.從哪里復(fù)制:我們的代碼是下載到nand中的所以當(dāng)然是從nand復(fù)制這個(gè)肯定是沒問題的,
當(dāng)然使用nand之前當(dāng)然得初始化nand
2.復(fù)制到哪:這個(gè)剛剛已經(jīng)知道了我們直接復(fù)制到內(nèi)存(SDRAM)中,這個(gè)也應(yīng)該沒問題
3.怎么復(fù)制:
(a)首先按照課程自己初始化nand自己寫的復(fù)制函數(shù),當(dāng)然沒有問題,但是要注意的是nand的地址,
老師視頻中的nand地址的寫法是針對(duì)塊來寫的,建議大家可以參考yang的代碼按手冊(cè)按不同的nand,
寫成標(biāo)準(zhǔn)的列+行地址的方式
?
(b)前面我們說到了BL0初始化了一個(gè)塊設(shè)備復(fù)制函數(shù),我們可不可以使用呢?當(dāng)然是可以使用
手冊(cè)提到了下面的說明
?
怎么使用呢可以先定義
#define NF8_ReadPage_Adv(a,b,c) (((int(*)(unsigned int, unsigned int, unsigned char*))(*((unsigned int *)0xD0037F90)))(a,b,c))
然后復(fù)制的時(shí)候
?
需要注意的是這個(gè)函數(shù)的輸入部分是數(shù)據(jù)所在的塊跟所在的頁,而不是頁偏移,因?yàn)槭菈K設(shè)備復(fù)制
(c)另外值得注意的是我們自己寫的nand復(fù)制函數(shù)其實(shí)沒有考慮過ecc,因?yàn)閚and存儲(chǔ)的數(shù)據(jù)很容易會(huì)出錯(cuò),
所以nand有個(gè)ecc的校驗(yàn)機(jī)制,其實(shí)我們?cè)诳磏and的手冊(cè)仔細(xì)點(diǎn)就可以看出端倪,
?
也就是這個(gè)部分,多出的這些字節(jié)其實(shí)就是存放ecc校驗(yàn)碼的,至于算法有興趣的可以參考yang的代碼
最后就是從nand的哪個(gè)地址開始復(fù)制,首先分為SLC跟MLC兩種flash
正常大家應(yīng)該使用的都是SLC的版本,下一節(jié)會(huì)提到BL1跟BL2的分割方式,
假設(shè)BL1加頭之后填充到4K,并且把BL2附加在后面那么實(shí)際上就是從nand4K的位置開始復(fù)制,
如果BL1加頭之后填充到16K,并且把BL2附加在后面那么實(shí)際上就是從nand16K的位置開始復(fù)制
另外提一下在210手冊(cè)523頁有一個(gè)OM腳的變量可以用來判斷是怎么啟動(dòng)的
?
固化代碼中還有從SD卡復(fù)制代碼的函數(shù)有興趣的可以參考yang的代碼判斷OM假設(shè)從SD卡啟動(dòng),
就從SD卡復(fù)制剩下的代碼BL2到內(nèi)存。
210串口控制臺(tái)-鏈接地址與BL1、BL2的分割方式
首先我們知道BL1是復(fù)制到SRAM中去執(zhí)行的,在BL1中我們基本上只有在跳轉(zhuǎn)BL2的時(shí)候使用絕對(duì)跳轉(zhuǎn),
剩下的地方都不會(huì)使用絕對(duì)跳轉(zhuǎn),所以BL1的鏈接地址實(shí)際上沒有多大的作用,
而BL2的鏈接地址因?yàn)槭翘D(zhuǎn)到內(nèi)存中的,并且是我們主要的程序部分,
加上需要處理中段向量,因此這個(gè)鏈接地址就非常重要了,
如果我們的代碼最終是復(fù)制到0x20008000這個(gè)地址并且跳轉(zhuǎn)到這個(gè)地址的,
那我們的鏈接地址就必須是0x20008000,也就是說鏈接地址與代碼實(shí)際的地址必須保持一致
?
至于怎么把代碼分割成BL1跟BL2實(shí)際上的作法是做兩個(gè)代碼分別編譯,
并且保證BL1小于16K,把BL1加頭之后擴(kuò)展到一定的大小,再把BL2附加在BL1后面
?
BL1的Makefile先把BL1編譯之后加頭
?
11.png?
下載附件??保存到相冊(cè)
頂層的Makefile實(shí)際上就是把已經(jīng)加完頭的spl_210.bin 擴(kuò)展成16K,然后再把編譯完的BL2,
連接,實(shí)際上因?yàn)樵?10的頭中有BL1的實(shí)際大小,因此如果你的BL1不到16K也就不需要一定得擴(kuò)展到16K
總結(jié)
以上是生活随笔為你收集整理的210串口控制台-210移植printf不好使的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于IO模式(浮空、推挽、开漏...)描
- 下一篇: FreeRtos osMessageP