日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

u-boot移植第一弹——制作可用的BL1

發布時間:2024/9/3 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 u-boot移植第一弹——制作可用的BL1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我的BL1源代碼來源于網路,博客地址是http://blog.csdn.net/xiaojiaohuazi/article/details/8265757。在這里記錄下自己的移植心得。

???????? 為什么要制作這個BL1呢,對于官方以及很多人說的它是u-boot啟動的第二階段,這里我不做過多說明,我想說的是,這個BL1可以讓你對內存操作的理解更加深入,對于后面移植u-boot的理解有幫助。

???????? 實際上在BL1階段只需要做串口和內存的初始化就可以了,初始化串口的目的是調試使用,這個是必須要的;初始化內存那不用說了,你想拷貝代碼,不初始化內存怎么能行的。

???????? 但是在這里我還加入了一個LED的操作代碼,為什么要加入呢,對于學習一個東西,不能說會移植了就算學會了,我想有問題的時候會調試才是更重要的,在開發時也是如此,有了調試手段就有了查錯的手段,那么找問題就可以很方便的定位了。所以加入這個LED的控制目的也就是為了調試使用,這也是看到網上有人說過,仔細想想,非常好用,O(∩_∩)O。

???????? 首先看看我的BL1的所有文件:

這里只說明移植的時候涉及到的文件,build、main.c、mem_setup.S、s5pv210.h、start.S這幾個文件。其中build是我加入的一個文件,目的在操作編譯燒寫的時候減少輸入命令,build文件的內容如下:

#!/bin/sh make ./mkv210_image bl.bin blSD2.bin dd iflag=dsync oflag=dsync if=blSD2.bin of=/dev/sdc seek=1

做的工作就是編譯,制作BL1,燒寫到SD卡。

這個BL1啟動的入口也是在start.S文件,看看做的是什么:

.text.global _start_start:bl mem_ctrl_asm_initldr sp, =0xD0035400bl mainloop:b loop
第一步就是初始化內存也就是進入mem_ctrl_asm_init這個函數進行執行,這個函數的代碼如下:

mem_ctrl_asm_init:/* DMC0 Drive Strength (Setting 2X) */ldr r0, =ELFIN_GPIO_BASEldr r1, =0x0000AAAAstr r1, [r0, #MP1_0DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_1DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_2DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_3DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_4DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_5DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_6DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP1_7DRV_SR_OFFSET]ldr r1, =0x00002AAAstr r1, [r0, #MP1_8DRV_SR_OFFSET]/* DMC1 Drive Strength (Setting 2X) */ldr r0, =ELFIN_GPIO_BASEldr r1, =0x0000AAAAstr r1, [r0, #MP2_0DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_1DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_2DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_3DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_4DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_5DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_6DRV_SR_OFFSET]ldr r1, =0x0000AAAAstr r1, [r0, #MP2_7DRV_SR_OFFSET]ldr r1, =0x00002AAAstr r1, [r0, #MP2_8DRV_SR_OFFSET]/* DMC0 initialization at single Type*/ldr r0, =APB_DMC_0_BASEldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000str r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Casestr r1, [r0, #DMC_PHYCONTROL1]ldr r1, =0x00101002 @PhyControl0 DLL onstr r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00101003 @PhyControl0 DLL startstr r1, [r0, #DMC_PHYCONTROL0]find_lock_val:ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register valueand r2, r1, #0x7cmp r2, #0x7 @Loop until DLL is lockedbne find_lock_valand r1, #0x3fc0 mov r2, r1, LSL #18orr r2, r2, #0x100000orr r2 ,r2, #0x1000 orr r1, r2, #0x3 @Force Value lockingstr r1, [r0, #DMC_PHYCONTROL0]#if 0 /* Memory margin test 10.01.05 */orr r1, r2, #0x1 @DLL offstr r1, [r0, #DMC_PHYCONTROL0] #endif/* setting DDR2 */ldr r1, =0x0FFF2010 @ConControl auto refresh offstr r1, [r0, #DMC_CONCONTROL]ldr r1, =DMC0_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedstr r1, [r0, #DMC_MEMCONFIG0]ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1str r1, [r0, #DMC_MEMCONFIG1]ldr r1, =0xFF000000 @PrechConfigstr r1, [r0, #DMC_PRECHCONFIG]ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)str r1, [r0, #DMC_TIMINGAREF]ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHzstr r1, [r0, #DMC_TIMINGROW]ldr r1, =DMC0_TIMING_DATA @TimingData CL=3str r1, [r0, #DMC_TIMINGDATA]ldr r1, =DMC0_TIMING_PWR @TimingPowerstr r1, [r0, #DMC_TIMINGPOWER]ldr r1, =0x07000000 @DirectCmd chip0 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00020000 @DirectCmd chip0 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00030000 @DirectCmd chip0 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x07100000 @DirectCmd chip1 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00120000 @DirectCmd chip1 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00130000 @DirectCmd chip1 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x0FF02030 @ConControl auto refresh onstr r1, [r0, #DMC_CONCONTROL]ldr r1, =0xFFFF00FF @PwrdnConfigstr r1, [r0, #DMC_PWRDNCONFIG]ldr r1, =DMC0_MEMCONTROL @MemControl 0x00202400 BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]/* DMC1 initialization */ldr r0, =APB_DMC_1_BASEldr r1, =0x00101000 @Phycontrol0 DLL parameter settingstr r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00000086 @Phycontrol1 DLL parameter settingstr r1, [r0, #DMC_PHYCONTROL1]ldr r1, =0x00101002 @PhyControl0 DLL onstr r1, [r0, #DMC_PHYCONTROL0]ldr r1, =0x00101003 @PhyControl0 DLL startstr r1, [r0, #DMC_PHYCONTROL0] find_lock_val1:ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register valueand r2, r1, #0x7cmp r2, #0x7 @Loop until DLL is lockedbne find_lock_val1and r1, #0x3fc0 mov r2, r1, LSL #18orr r2, r2, #0x100000orr r2, r2, #0x1000orr r1, r2, #0x3 @Force Value lockingstr r1, [r0, #DMC_PHYCONTROL0]#if 0 /* Memory margin test 10.01.05 */orr r1, r2, #0x1 @DLL offstr r1, [r0, #DMC_PHYCONTROL0] #endif/* settinf fot DDR2 */ldr r0, =APB_DMC_1_BASEldr r1, =0x0FFF2010 @auto refresh offstr r1, [r0, #DMC_CONCONTROL]ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]ldr r1, =DMC1_MEMCONFIG_0 @MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixedstr r1, [r0, #DMC_MEMCONFIG0]ldr r1, =DMC1_MEMCONFIG_1 @MemConfig1str r1, [r0, #DMC_MEMCONFIG1]ldr r1, =0xFF000000str r1, [r0, #DMC_PRECHCONFIG]ldr r1, =DMC1_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4str r1, [r0, #DMC_TIMINGAREF]ldr r1, =DMC1_TIMING_ROW @TimingRow for @200MHzstr r1, [r0, #DMC_TIMINGROW]ldr r1, =DMC1_TIMING_DATA @TimingData CL=3str r1, [r0, #DMC_TIMINGDATA]ldr r1, =DMC1_TIMING_PWR @TimingPowerstr r1, [r0, #DMC_TIMINGPOWER]ldr r1, =0x07000000 @DirectCmd chip0 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00020000 @DirectCmd chip0 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00030000 @DirectCmd chip0 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01000000 @DirectCmd chip0 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05000000 @DirectCmd chip0 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x07100000 @DirectCmd chip1 Deselectstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00120000 @DirectCmd chip1 EMRS2str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00130000 @DirectCmd chip1 EMRS3str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110440 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x01100000 @DirectCmd chip1 PALLstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x05100000 @DirectCmd chip1 REFAstr r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit)str r1, [r0, #DMC_DIRECTCMD]ldr r1, =0x0FF02030 @ConControl auto refresh onstr r1, [r0, #DMC_CONCONTROL]ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG]ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down offstr r1, [r0, #DMC_MEMCONTROL]//下面為點燈代碼,用于調試ldr r0, =0xE0200C00 ldr r1, =0x11000000 str r1, [r0] ldr r1, =0xc0 str r1, [r0, #4]//上面為點燈代碼,用于調試 mov pc, lr
可以看到我在該函數的最后增加了LED燈的代碼,具體的含義請參考帖子 http://blog.csdn.net/kevinshq/article/details/7968409不同的板子LED接口可能不同,這樣的話就需要修改寄存器的地址了,也可能沒有LED,如果是這種情況就需要使用其他的提醒功能來代替LED了(最好是能夠看到現象的)。LED代碼放在這里在啟動板子的時候就可以觀察LED的狀態來判斷內存初始化這部分代碼是否啟動了。

好,現在回到該函數的起始部分,對于該函數已經有人做過了分析,這里我就引用之博文地址為http://blog.csdn.net/mutemob/article/details/12974483。在這之外我們需要注意一個問題,那就是下面代碼的位置處


有可能你的代碼紅色部分為0x00202400這種格式的16進制,最好是改成上圖所示的請款個,目的是為了方便修改。

從start.S文件中可以知道,第二個執行的函數為main函數,函數位置在main.c。

???????? main.c文件源代碼請下載下來觀看,這里我就不一次全部貼上來了。我們從main主函數出發,看看都做了些什么:

int main (void) {__attribute__((noreturn)) void (*uboot)(void); uart_init(); //串口初始化mem_test(); //內存測試printf ("copy uboot from sd to sdram ddr2\r\n"); copy_uboot_to_ram(); printf ("jump to u-boot image\r\n"); //下面代碼是控制班子上的LED,可用于調試 //*(volatile unsigned int *)0xE0200C00 = 0x11000000; //*(volatile unsigned int *)0xE0200C04 = 0x000000c0; //上面代碼是控制班子上的LED,可用于調試 /* Jump to U-Boot imaguboot = (void *)0x33e00000; (*uboot)(); return 1; }

開始進行了串口的初始化,然后是內存的測試,接著是u-boot的拷貝階段,最后跳轉到u-boot的位置開始執行。我的u-boot的起始地址是0x33e00000,不同的板子地址可能有所不同,請調整為自己的u-boot起始地址即可,也就是把0x33e00000換成自己的板子的地址。

?????? 串口的初始化我的板子是Real210板子,調試口使用的是串口2,所以在網絡上原來的代碼基礎上把他的串口初始化從串口0修改到了串口2,在源碼的s5pv210.h中可以看到各寄存器的定義。串口的初始化是在文件uart.c中進行,這里我不再說明,具體的請參閱s5pv210 pdf進行對比學習。

?????? 內存的測試函數mem_test()代碼如下:

void mem_test() {#define test_mem1 0x30000000#define test_mem2 0x33e00004#define test_mem3 0x3f000f08#define test_mem4 0x3ffff0fc#define test_mem5 0x3ffffffc //內存地址是每隔4個字節存放的,所以訪問時是4個字節訪問#define test_mem6 0x40000000#define test_mem7 0x43e00004#define test_mem8 0x4f00f008#define test_mem9 0x4ffffff8 #define test_mem10 0x4ffffffcunsigned int *p1 = (volatile unsigned int *)test_mem1;unsigned int *p2 = (volatile unsigned int *)test_mem2;unsigned int *p3 = (volatile unsigned int *)test_mem3;unsigned int *p4 = (volatile unsigned int *)test_mem4;unsigned int *p5 = (volatile unsigned int *)test_mem5;unsigned int *p6 = (volatile unsigned int *)test_mem6;unsigned int *p7 = (volatile unsigned int *)test_mem7;unsigned int *p8 = (volatile unsigned int *)test_mem8;unsigned int *p9 = (volatile unsigned int *)test_mem9;unsigned int *p10 = (volatile unsigned int *)test_mem10;printf ("******s5pv210 Test********\r\n");printf ("********By ZheGao********\r\n");*p1 = 0x12345678;if (*p1 == 0x12345678) {printf ("1: equ\r\n");} else {printf ("1: not equ\r\n");}*p2 = 0x12345678;if (*p2 == 0x12345678) {printf ("2: equ\r\n");} else {printf ("2: not equ\r\n");}*p3= 0xfffffff0;if (*p3 == 0xfffffff0) {printf ("3: equ\r\n");} else {printf ("3: not equ\r\n");}*p4 = 0x12345678;if (*p4 == 0x12345678) {printf ("4: equ\r\n");} else {printf ("4: not equ\r\n");}*p5 = 0x12345678;if (*p5 == 0x12345678) {printf ("5: equ\r\n");} else {printf ("5: not equ\r\n");}*p6= 0xfffffff0;if (*p6 == 0xfffffff0) {printf ("6: equ\r\n");} else {printf ("6: not equ\r\n");}*p7 = 0x12345678;if (*p7 == 0x12345678) {printf ("7: equ\r\n");} else {printf ("7: not equ\r\n");}*p8 = 0x12345678;if (*p8 == 0x12345678) {printf ("8: equ\r\n");} else {printf ("8: not equ\r\n");}*p9= 0x12345678;if (*p9 == 0x12345678) {printf ("9: equ\r\n");} else {printf ("9: not equ\r\n");}*p10= 0x12345678;if (*p10 == 0x12345678) {printf ("10: equ\r\n");} else {printf ("10: not equ\r\n");}}

從最開始宏定義可以知道測試的內存地址,這里把我板子的全部內存做了隔段測試,我的內存地址是從0x30000000到0x4fffffff總共512MB,注意在測試的時候內存地址需要隔4個字節進行測試,也就是最后一位只能取值0、4、8、c這四個值,原因是,我們的內存是32位的也就是4個字節,所以在測試訪問的時候需要隔4個字節,注意不能取最后一位除0、4、8、c以外的值,否者就會死掉。

copy_uboot_to_ram()這個拷貝函數的說也參考一個博文http://blog.csdn.net/shangguobuliuhen/article/details/9844371。

同樣在main函數中也有LED燈的代碼,不過這次換成了C語言的寫法,放在這里也是為了判斷代碼執行的位置,進而判斷代碼會死在哪里,這個LED定位的思想要靈活運用,可以為你學習和調試帶來極大的幫助。就在u-boot中一樣我們使用串口打印信息來進行調試一個道理。

第一階段告一段落,后面繼續更新,下一個就是讓u-boot能夠啟動并能進入控制臺,過些天在寫上來吧。有問題得朋友可以留言,大家共同探討。





與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的u-boot移植第一弹——制作可用的BL1的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。