1.裸机运行程序时一般情况下程序代码小于16KB将其下载地址设置到BL1的起始地址。BL0会自动加载并执行BL1。
当程序大于16kB时无法直接运行。
例如UBOOT就大于16KB,执行的原理为。将程序分为BL1、BL2两部分。
其中BL1初始化DDR并且指定BL2的起始地址。BL2为真正需要的程序。
BL1部分
start.S
#define WTCON 0xE2700000 #define SVC_STACK 0xd0037d80 .global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了 _start: // 第1步:关看门狗(向WTCON的bit5写入0即可) ldr r0, =WTCON ldr r1, =0x0 str r1, [r0] // 第2步:设置SVC栈 ldr sp, =SVC_STACK // 第3步:开/关icache mrc p15,0,r0,c1,c0,0; // 读出cp15的c1到r0中 //bic r0, r0, #(1<<12) // bit12 置0 关icache orr r0, r0, #(1<<12) // bit12 置1 开icache mcr p15,0,r0,c1,c0,0; // 第4步:初始化ddr bl sdram_asm_init // 第5步:重定位,从SD卡第45扇区开始,复制32个扇区到DDR 的0x23E00000 bl copy_bl2_2_ddr
sd_start.c
#define SD_START_BLOCK 45 #define SD_BLOCK_CNT 32 #define DDR_START_ADDR 0x23E00000 typedef unsigned int bool; // 通道号:0,或者2 // 开始扇区号:45 // 读取扇区个数:32 // 读取后放入内存地址:0x23E00000 // with_init:0 typedef bool(*pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int*, bool); typedef void (*pBL2Type)(void); // 从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000,然后跳转到23E00000去执行 void copy_bl2_2_ddr(void) { // 第一步,读取SD卡扇区到DDR中 pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)(*(unsigned int *)0xD0037F98); (*p1)(2, SD_START_BLOCK, SD_BLOCK_CNT, (unsigned int *)DDR_START_ADDR, 0); // 读取SD卡到DDR中 // 第二步,跳转到DDR中的BL2去执行 pBL2Type p2 = (pBL2Type)DDR_START_ADDR; (*p2)(); }
BL2(功能无所谓,将链接地址和BL1中的跳转地址相同即可)
SECTIONS { . = 0x23E00000; .text : { start.o * (.text) } .data : { * (.data) } bss_start = .; .bss : { * (.bss) } bss_end = .; }
来源:https://www.cnblogs.com/PengfeiSong/p/6380066.html