📄 疑难解答.txt
字号:
问:
你好,首先很感谢你写这些东西,看了你写的bootloader,对我很有启发。但我还是有几个问题不是很明白,想请教一下。
首先是对于part5这块儿有点儿疑问,这段代码主要是把bootloader由flash拷贝到sdram中去,我的理解是只要把RO代码段拷贝过去就可以了啊,为什么要拷贝(RO+RW)长度的代码呢,而且我的理解是虽说拷贝了(RO+RW)长度的代码,但是RW段的内容并没有被拷贝到sdram中去,这么做是为什么呢?另外这里RWBase的地址是多少呢,是在ads中设置的0xA00000这个吗?RW段代码在flash中的地址是如何确定的呢?如果是0xA00000的话,已经超过2Mflash的大小了啊?
;Part 5
;***************************************************************
;Self copy from FLASH to SDRAM
LDR r0, =|Image$$RO$$Base|
LDR r1, =|Image$$RO$$Limit|
LDR r2, =|Image$$RW$$Base|
LDR r3, =|Image$$RW$$Limit|
SUB r1, r1, r0
SUB r3, r3, r2
ADD r1, r1, r3
LDR r2, =0x200000 ;@2M
COPY
LDR r3, [r0], #4
STR r3, [r2], #4
SUBS r1, r1, #4
BNE COPY
还有一个问题就是你是把image.ram转换成一个数组了,那么在把bootloader烧到flash里这个数组是存在哪里的呢,是放在RW段吗?如果是放在RW段的话,那在映射后是不是先把RW段的数据由flash拷贝到sdram中,再把位于sdram中RW段的image.ram数组拷贝到0x8000处,然后运行uclinux。
答:
part5这部分代码的目的就是要把整个bootlaoder拷贝到sdram里去,包括RW段和RO段。在程序里,RO BASE = 0X0, RW BASE = 0XA00000, 这里需要注意一个问题:在编译链接好的程序里面,RW段是放置在RO段后面的,所以|Image$$RO$$Limit|既是RO段的结束位置也是RW段的起始地址。 而RW BASE是指在运行的时候RW段的地址,因为运行时我们需要把RW段拷贝到memory里可读写的存储介质上去,所以RW BASE 被设置为 0XA00000. 所以,RW BASE 大于2M并不是个问题。
其实你也可以开始指把RO段拷贝到SDRAM里去,回头在从flash里把RW段拷贝到合适的位置上去,但为了使得实现更简单和直接,我没有这样做,而是一口气就把整个bootloader拷贝到sdram里去了,回头就不用在管flash了。在remap后再把RW段从SDRAM里拷贝到SDRAM合适的位置去。
因为kernel[]这个数组是一个全局变量,所以肯定是被放到RW段去了。所以,在remap后,先把RW段拷贝到RW_BASE的位置上去,设置好堆栈指针,就可以调用loadkernel函数了,这个函数会把knerle[]这个数组(其实就是内核image.ram)拷贝到0x8000的位置上去,然后跳转过去就可以启动了。
希望能够解释清楚,如果有问题请发贴继续讨论。
问:
编译出来有1M多,怎么会如此大呢?
答:
是的,大概有1M多。为了简单起见,在把image.ram转化为char数组前并没有把image.ram先压缩一下,所以编译出来比较大。如果你感兴趣的话,可以自己把压缩和解压缩添加进去,网上找的到压缩和解压缩的源代码,应该挺容易实现的。
问:
非常清楚的說明。另外有個問題想請教,在 load kernal 完成後,uClinux kernal 會在位址 0x0 重設中斷向量嗎? thks
答:
bootloader里不用管中断。但在kernel起来后,kernel自己肯定会设置中断向量的。
呵呵,一个BootLoader的最小系统,简洁、高效!真是好人!
问:
现在有一个问题:
在loadkernel.c中2097152你是怎么计算出来的呢?也就是uclinux内核字节的大小。
for(i = 0; i < 2097152; i++){
*to = *from;
to++;
from++;
}
我通过ultraEdit计算出来的是:2732523,好像差别蛮大呀?敢问大侠如何计算?
再次谢谢了!
答:
其实在这个地方我偷了个懒,呵呵,直接设置成2M了,因为flash的大小就是2M。
请问在源代码中在管理模式下设置堆栈指针0x800000,有什么讲究吗?为什么不启用内部RAM,将堆栈设置在3FE0000呢?
是uclinux要求必须设置在0x800000吗?请指教。
;Part 8
;***********************************************************************
;Set stack pointer & jump to c function
LDR sp, =0x800000
IMPORT loadkernel
LDR pc, =loadkernel
这里设置的堆栈指针只是bootloader用的,可以随便设置在那里(SDRAM or SRAM),只要不占用0x8000开始的那块SDRAM就可以了。 因为必须把kernel转载到0x8000处,所以我把堆栈指针设置在了SDRAM的高端。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -