自己写一个最简单的bootloader_jz2440
寫在前面:
我的博客已遷移至自建服務器:博客傳送門,CSDN博客暫時停止,如有機器學習方面的興趣,歡迎來看一看。
此外目前我在gitHub上準備一些李航的《統(tǒng)計學習方法》的實現(xiàn)算法,目標將書內(nèi)算法全部手打?qū)崿F(xiàn),歡迎參觀并打星。GitHib傳送門
正文
boot是為了啟動內(nèi)核,本質(zhì)上也就是一個裸板程序,就是為了引導內(nèi)核的啟動。所以打算自己寫一個boot,功能只有引導內(nèi)核啟動。
首先是匯編的代碼段,是為了關(guān)閉看門狗,設置時鐘以及代碼的重定位,這些都是在main函數(shù)之前執(zhí)行的。之前學習單片機的時候,我們只看到main函數(shù),實際上是main之前的執(zhí)行步驟都被包起來了。
整個匯編文件的開頭要寫上
.text @這是為了表示這是一個代碼段 .global _start _start:第一步:關(guān)閉看門狗,2440是默認關(guān)門狗打開的,如果不關(guān)閉看門狗,三秒鐘后板子會自動重啟
/* 關(guān)看門狗 */ldr r0, = 0x53000000 /* 看門狗的寄存器地址,通過芯片手冊可以查看 */mov r1, #0 /* 把0放入r1*/str r1, [r0] /* 把r1中的0賦給看門狗,即關(guān)閉看門狗 */第二步:設置時鐘,2440板子的晶振是12M(也可以使用16M或其他的),如果不設置時鐘去倍頻,板子是以12M的速度跑的,這里是設置分頻系數(shù)以及設置板子的頻率為400M
//經(jīng)過實測,boot在200M和400M的情況下,都需要6秒才能啟動內(nèi)核,速度有點慢,所以使用了ICACHE提高速度,使用ICACHE以后,啟動內(nèi)核只需要2秒,可以接受
啟動Icahe的原理是這樣:每次CPU去RAM讀代碼,很費力,ICACHE就是把這段代碼copy到片子里的一個區(qū)域,CPU直接去讀這塊區(qū)域就行了,而且這塊區(qū)域的讀速度比RAM快多了。就好像每天都有一份快遞,自己每天去取費時費力,直接讓快遞員送門口,就省很多事。
第三步:初始化SDRAM,代碼需要在SDRAM中執(zhí)行,所以需要初始化
/* 初始化SDRAM */ldr r0, =MEM_CTL_BASE //設置SDRAM寄存器的首地址adr r1, sdram_config /*SDRAM每個寄存器的配置值 */add r3, r0, #(13 * 4) //SDRAM寄存器的尾地址1:ldr r2, [r1], #4 //把寄存器的配置值寫入r2,然后r1地址加4字節(jié),定位到sdram_config的下一個配置值str r2, [r0], #4 //r2里的值寫入到r0地址,也就是SDRAM的第一個寄存器,然后寄存器地址加四字節(jié),指 //向下一個寄存器cmp r0, r3 //當前寄存器地址和寄存器尾地址比較,如果不一致說明還沒配置完,跳轉(zhuǎn)到1繼續(xù)循環(huán)bne 1b/*放在文件末尾,這是關(guān)于SDRAM的每個寄存器的配置值*/ sdram_config:.long 0x22011110 //BWSCON.long 0x00000700 //BANKCON0.long 0x00000700 //BANKCON1.long 0x00000700 //BANKCON2.long 0x00000700 //BANKCON3 .long 0x00000700 //BANKCON4.long 0x00000700 //BANKCON5.long 0x00018005 //BANKCON6.long 0x00018005 //BANKCON7.long 0x008C04F4 //REFRESH.long 0x000000B1 //BANKSIZE.long 0x00000030 //MRSRB6.long 0x00000030 //MRSRB7第四步:代碼重定位,因為代碼是存在NOR FLASH 或者 NAND FLASH里面的,CPU要將代碼移入SDRAM中才可以使用
/* 重定位 */ldr sp, =0x34000000 //因為nand初始化比較復雜,使用C語言實現(xiàn),如果要使用C語言,需要設置堆棧指針bl nand_init //初始化nand,其實如果使用的是nor,完全可以不初始化nand,這里是考慮到不知道使用的是nor還是nand,所以把nand初始化了,之后會判斷使用的是什么flash。之所以不用初始化nor,是因為CPU可以直接讀normov r0, #0 //設置copy_code_to_sdram的參數(shù),r0是該函數(shù)第一個參數(shù),r1是第二個,r2是第三個,很好理解ldr r1, =_startldr r2, = __bss_startsub r2, r2, r1bl copy_code_to_sdram //調(diào)用C函數(shù),實現(xiàn)將代碼copy至SDRAMbl clear_bss //清除BSS段,未初始化或初始化為0的變量都存在這里,所以需要清零bss段挺好玩的,這樣的,如果你程序里面設置了很多變量,初始值都為0,那么程序一開始一個一個去賦0效率太低了,所以所有初始值為0的變量,都保存在bss代碼段里,程序啟動前將整個代碼段清零就行了,就很方便
第五步:執(zhí)行main函數(shù)
/* 執(zhí)行main */ldr lr, =halt //設置main函數(shù)的返回地址,其實boot啟動內(nèi)核以后直接就死掉了,根本不會返回,這里還是寫一下返回地址,main返回以后去執(zhí)行下面的halt段,不斷地死循環(huán),防止出問題ldr pc, =main //指針定位到main函數(shù)halt:b halt/* 重定位過程中使用的C函數(shù) 挑了幾個稍微重要點的,別的都不寫了,沒什么意思*/
/* nand初始化,沒什么意思,就不多寫了 */
/* 復制代碼段到SDRAM*/
//這里就是判斷是NOR還是NAND,因為它們的特性不同,導致nand可讀可寫,NOR只能讀,所以測試的時候就隨便找個地址,往里寫一個數(shù),再往外讀,如果值被修改了,說明是nand,反之是nor
總結(jié)
以上是生活随笔為你收集整理的自己写一个最简单的bootloader_jz2440的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NFS挂载失败(Kernel Panic
- 下一篇: 移植uboot第一步:下载,编译,烧到板