关于s3c2440从nand flash的疑惑

时间:2022-09-02 15:25:18
我知道2440从nand flash启动的时候会先由硬件把前4K的代码搬到片内的sram中去,然后从片内的sram开始运行,再把nand flash中的程序搬到外部sdram里面去,然后程序由内部sram跳到外部sdram去执行,这里我就有个疑惑,把程序从nand flash搬到外部sdram的时候,已经搬到内部sram的那4K还要搬吗?
还有一个问题,也是我最想问的问题,程序从nand flash搬到外部sdram后,中断向量表应该有两份吧,一份在片内sram(地址0x00000000)的起始地址处,一份在片外的sdram中(地址0x30000000),当发生中断的时候,PC会跳到地址0处,如果已经初始化了MMU的话,程序会跳到映射后的地址,也就是0x30000000处,这样的话,中断程序理所当然可以正常执行。但是,如果没有开MMU的话,程序跳到物理地址的0x00000000处,这里也有一份中断向量表啊,应该也能够正常的跳到中断函数去执行啊,可是为什么事实不行呢?手册上有说这4K的sram在启动后可以用作其他用途,但是我没有用啊,那内容应该还是原来的内容,那为什么不能正常跳到中断函数里去呢?问题在哪里?小弟用的是天嵌的开发板,前几天刚到手的。

16 个解决方案

#1


我最近也在弄,同样疑惑中。。。

#2


按你的说法的确那2个地方的确是放异常入口的地方,但是那里前提是要有东西

#3


也就是条b 指令

#4


引用 3 楼 nadleeh123 的回复:
也就是条b 指令

这个肯定是有的啊,nand flash里面的前4k内容不也是从内部sram复制过去的吗?只要nand flash里面有,sram里面肯定也有的啊

#5


你怎么知道前4k有中断向量表

#6


那前4k,最大的作用是初始化内存和数据总线,不关中断的事

#7


你可以看看u-boot中,对应的芯片的star.S 以及该文件下的源码,对你有帮助

#8


引用 5 楼 nadleeh123 的回复:
你怎么知道前4k有中断向量表

这个是肯定的,因为0x0到0x1c处存放的就是中断向量表

#9


如果不开mmu的话,发生了中断程序会跳转到0x0去执行,这个物理0x0地址就在sram中,所以跟中断还是有关的,只不过平时大家用的时候都开了mmu所以才看起来无关

#10


引用 9 楼 zzfei90 的回复:
如果不开mmu的话,发生了中断程序会跳转到0x0去执行,这个物理0x0地址就在sram中,所以跟中断还是有关的,只不过平时大家用的时候都开了mmu所以才看起来无关


中断发生了,会跳转到0x0偏转若干字节(4的整数倍),去执行放再那的指令,但是这里只有4个字节,你的中断函数放的下么,那里要放自己写的异常向量处理,系统起来的话系统已经帮你做了这个工作,裸板自己必须写。

再说如果中断就直接跳过去执行你的东西去了,那么cpu中断时的执行的东西岂不是丢了,那你的函数执行完了怎么回去呢?

#11


这是我从u-boot2012.10/arch/arm/cpu/arm1176/start.S中复制的部分代码。由IROM复制到SRAM中的前4K代码是木有中断向量表滴,这4K代码是同nand_spl//board/下面你开发板相关文件夹里面的Makefile生成的,其中最重要的就是生成CONFIG_NAND_SPL宏及make变量。再根据下面的代码,中断向量表当然是要被跳过编译啰!!

.globl _start
_start: b reset
#ifndef CONFIG_NAND_SPL
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq


所以,大部分的u-boot中两份中断向量表是不存在的。

#12


嗯,认真看了一下你的描述。

先说第一个问题吧:
从u-boot-2012.10源码中我开发板的情况来看是没有复制前4K的内容的,注意下面函数的第二个参数。
板配置文件中的宏定义:
#define CONFIG_SYS_NAND_U_BOOT_OFFS (4 * 1024)
加载nand中的u-boot到dram的加载函数的声明。
//函数声明
static int nand_load(struct mtd_info *mtd, unsigned int offs,
     unsigned int uboot_size, uchar *dst)
//加载nand中的u-boot到dram的加载函数调用
nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
  (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);

这是u-boot关于nand起动的通常情况。但具体的要看你开发板对于这个功能的实现,以及对于u-boot镜像的构造情况。

通常的nand起动的镜像是由根目录下的u-boot和nand_spl下的u-boot-spl这两部分的所构成的。从根目录makefile中的目标可以看出这个过程:
$(obj)u-boot-nand.bin: nand_spl $(obj)u-boot.bin
cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

还是那句话,这是通常情况…………

第二种情况,前面说了一点,我开发板运行于SRAM的4K代码是没有中断向量的也没有中断处理程序。至于开MMU,后我开发板的地址映射是0x0 - 0xA000000的虚拟地址和实地址是一一映射,所以有点糊涂了,脑袋一时转不过了……^_^

#13


网上查了一下,异常向量表的位置并非总是从0地址开始的,协处理器cp15中有相关设置。
我s3c6410是arm1176jzfs核心的CP15的c1寄存器[13]即‘V’bit可能选择异常向量的位置
0 = Normal exception vectors selected, the Vector Base Address Registers determine
the address range, reset value.
1 = High exception vectors selected, address range = 0xFFFF0000-0xFFFF001C.
当值为0时,CP15的c12还可以进一步设置异常向量的基地址,当然,默认情况下是0x0。

建议你阅读和你CPU核心相关的文档并参看你的u-boot源码看看!

不过,我的开发板的异常向量在物理地址57e00000虚拟地址为c7e00000,但找了半天没看到设置CP15的c12寄存器,对于这个情况相当不解,有待继续查找原因…………

#14


引用 13 楼 JQGuardian 的回复:
网上查了一下,异常向量表的位置并非总是从0地址开始的,协处理器cp15中有相关设置。
我s3c6410是arm1176jzfs核心的CP15的c1寄存器[13]即‘V’bit可能选择异常向量的位置
0 = Normal exception vectors selected, the Vector Base Address Registers determine
th……

呵呵,首先,谢谢你能认真的看并回答我的问题。
以下是我的开发板资料中启动代码中的一段:
void RdNF2SDRAM( )
{
U32 i;
U32 start_addr = 0x0;
unsigned char * to = (unsigned char *)0x30000000;
U32 size = 0x100000;
rNF_Init();
switch(rNF_ReadID())
{
case 0x76:
for(i = (start_addr >> 9); size > 0; )
{
rSB_ReadPage(i, to);
size -= 512;
to += 512;
i ++;
}
break;
case 0xf1:
case 0xda:
case 0xdc:
case 0xd3:
for(i = (start_addr >> 11); size > 0; )
{
rLB_ReadPage(i, to);
size -= 2048;
to += 2048;
i ++;
}
break;
}
}
从上面代码看,在从nand flash往sdram复制程序的时候,是从地址0开始复制的,也就是全部都复制到了sdram里面去了,而且我在网上查了,有的说是全部,有的说是不带前4k,这个好像有不一样的。
下面是我2440init.s里面的一段内容的汇编后代码:
 __ENTRY
    ResetEntry
    $a
    Init
        0x00000000:    eafffffe    ....    B        ResetHandler  ; 0x120
        0x00000004:    eafffffe    ....    B        HandlerUndef  ; 0x78
        0x00000008:    eafffffe    ....    B        HandlerSWI  ; 0x90
        0x0000000c:    eafffffe    ....    B        HandlerPabort  ; 0xc0
        0x00000010:    eafffffe    ....    B        HandlerDabort  ; 0xa8
        0x00000014:    eafffffe    ....    B        {pc}  ; 0x14
        0x00000018:    e59ff0dc    ....    LDR      HandlerIRQ
        0x0000001c:    eafffffe    ....    B        HandlerFIQ  ; 0x48
        0x00000020:    eafffffe    ....    B        EnterPWDN  ; 0x3f4
这个2440init.s在链接器里面是设置过的放在生成目标文件的最开始的部分的,也就是0x0的地方,从汇编过的代码来看,在0x00-0x1c地址处,放的也正是中断向量表,所以在生成的.bin文件中,这个中断向量表应该也是在最开始的地方,将.bin下载到nand flash里面后,也应该在最开始的地方,而上电后,nand控制器将前4k的内容自动复制到片内sram内,所以,在sram开始的位置,肯定是有一份中断向量表的。那么不开mmu的时候,如果发生中断,程序应该会跳到这个地方来的,可是为什么这里的跳转不能正确将程序引导到中断处理函数中去呢?跳转指令我改过了,用的是ldr,用绝对地址来跳

#15


关于s3c2440从nand flash的疑惑我老实用我的开发板试了下,在我的板子上使用的异常向量表是被映射到0地址的SRAM上。另外,由于我的TLB把0x0 - 0xa0000000的虚拟地址映射到了对应的实地址,所以不管开没开MMU都是使用的SRAM上的中断向量。

至于你的情况,
一、你在u-boot中检查下SRAM中的内容,是否被改变。
二、检查CP15 c0的V位设置,有源码就看看开,关MMU的语句。
    如果这个位被置为‘1’,则异常向量表的位置将不再是地址‘0’。
三、异常向量表的跳转指令是否正确。

关MMU不能执行异常中断应该是这三处地方……

#16


引用 15 楼 JQGuardian 的回复:
我老实用我的开发板试了下,在我的板子上使用的异常向量表是被映射到0地址的SRAM上。另外,由于我的TLB把0x0 - 0xa0000000的虚拟地址映射到了对应的实地址,所以不管开没开MMU都是使用的SRAM上的中断向量。

至于你的情况,
一、你在u-boot中检查下SRAM中的内容,是否被改变。
二、检查CP15 c0的V位设置,有源码就看看开,关MMU的语句……

我刚才看了下,我的0x00000000地址不能访问,往里面写数,再读出来,全是0,但是外部sdram的地址0x30000000可以正常访问,真郁闷…

#1


我最近也在弄,同样疑惑中。。。

#2


按你的说法的确那2个地方的确是放异常入口的地方,但是那里前提是要有东西

#3


也就是条b 指令

#4


引用 3 楼 nadleeh123 的回复:
也就是条b 指令

这个肯定是有的啊,nand flash里面的前4k内容不也是从内部sram复制过去的吗?只要nand flash里面有,sram里面肯定也有的啊

#5


你怎么知道前4k有中断向量表

#6


那前4k,最大的作用是初始化内存和数据总线,不关中断的事

#7


你可以看看u-boot中,对应的芯片的star.S 以及该文件下的源码,对你有帮助

#8


引用 5 楼 nadleeh123 的回复:
你怎么知道前4k有中断向量表

这个是肯定的,因为0x0到0x1c处存放的就是中断向量表

#9


如果不开mmu的话,发生了中断程序会跳转到0x0去执行,这个物理0x0地址就在sram中,所以跟中断还是有关的,只不过平时大家用的时候都开了mmu所以才看起来无关

#10


引用 9 楼 zzfei90 的回复:
如果不开mmu的话,发生了中断程序会跳转到0x0去执行,这个物理0x0地址就在sram中,所以跟中断还是有关的,只不过平时大家用的时候都开了mmu所以才看起来无关


中断发生了,会跳转到0x0偏转若干字节(4的整数倍),去执行放再那的指令,但是这里只有4个字节,你的中断函数放的下么,那里要放自己写的异常向量处理,系统起来的话系统已经帮你做了这个工作,裸板自己必须写。

再说如果中断就直接跳过去执行你的东西去了,那么cpu中断时的执行的东西岂不是丢了,那你的函数执行完了怎么回去呢?

#11


这是我从u-boot2012.10/arch/arm/cpu/arm1176/start.S中复制的部分代码。由IROM复制到SRAM中的前4K代码是木有中断向量表滴,这4K代码是同nand_spl//board/下面你开发板相关文件夹里面的Makefile生成的,其中最重要的就是生成CONFIG_NAND_SPL宏及make变量。再根据下面的代码,中断向量表当然是要被跳过编译啰!!

.globl _start
_start: b reset
#ifndef CONFIG_NAND_SPL
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq


所以,大部分的u-boot中两份中断向量表是不存在的。

#12


嗯,认真看了一下你的描述。

先说第一个问题吧:
从u-boot-2012.10源码中我开发板的情况来看是没有复制前4K的内容的,注意下面函数的第二个参数。
板配置文件中的宏定义:
#define CONFIG_SYS_NAND_U_BOOT_OFFS (4 * 1024)
加载nand中的u-boot到dram的加载函数的声明。
//函数声明
static int nand_load(struct mtd_info *mtd, unsigned int offs,
     unsigned int uboot_size, uchar *dst)
//加载nand中的u-boot到dram的加载函数调用
nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
  (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);

这是u-boot关于nand起动的通常情况。但具体的要看你开发板对于这个功能的实现,以及对于u-boot镜像的构造情况。

通常的nand起动的镜像是由根目录下的u-boot和nand_spl下的u-boot-spl这两部分的所构成的。从根目录makefile中的目标可以看出这个过程:
$(obj)u-boot-nand.bin: nand_spl $(obj)u-boot.bin
cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

还是那句话,这是通常情况…………

第二种情况,前面说了一点,我开发板运行于SRAM的4K代码是没有中断向量的也没有中断处理程序。至于开MMU,后我开发板的地址映射是0x0 - 0xA000000的虚拟地址和实地址是一一映射,所以有点糊涂了,脑袋一时转不过了……^_^

#13


网上查了一下,异常向量表的位置并非总是从0地址开始的,协处理器cp15中有相关设置。
我s3c6410是arm1176jzfs核心的CP15的c1寄存器[13]即‘V’bit可能选择异常向量的位置
0 = Normal exception vectors selected, the Vector Base Address Registers determine
the address range, reset value.
1 = High exception vectors selected, address range = 0xFFFF0000-0xFFFF001C.
当值为0时,CP15的c12还可以进一步设置异常向量的基地址,当然,默认情况下是0x0。

建议你阅读和你CPU核心相关的文档并参看你的u-boot源码看看!

不过,我的开发板的异常向量在物理地址57e00000虚拟地址为c7e00000,但找了半天没看到设置CP15的c12寄存器,对于这个情况相当不解,有待继续查找原因…………

#14


引用 13 楼 JQGuardian 的回复:
网上查了一下,异常向量表的位置并非总是从0地址开始的,协处理器cp15中有相关设置。
我s3c6410是arm1176jzfs核心的CP15的c1寄存器[13]即‘V’bit可能选择异常向量的位置
0 = Normal exception vectors selected, the Vector Base Address Registers determine
th……

呵呵,首先,谢谢你能认真的看并回答我的问题。
以下是我的开发板资料中启动代码中的一段:
void RdNF2SDRAM( )
{
U32 i;
U32 start_addr = 0x0;
unsigned char * to = (unsigned char *)0x30000000;
U32 size = 0x100000;
rNF_Init();
switch(rNF_ReadID())
{
case 0x76:
for(i = (start_addr >> 9); size > 0; )
{
rSB_ReadPage(i, to);
size -= 512;
to += 512;
i ++;
}
break;
case 0xf1:
case 0xda:
case 0xdc:
case 0xd3:
for(i = (start_addr >> 11); size > 0; )
{
rLB_ReadPage(i, to);
size -= 2048;
to += 2048;
i ++;
}
break;
}
}
从上面代码看,在从nand flash往sdram复制程序的时候,是从地址0开始复制的,也就是全部都复制到了sdram里面去了,而且我在网上查了,有的说是全部,有的说是不带前4k,这个好像有不一样的。
下面是我2440init.s里面的一段内容的汇编后代码:
 __ENTRY
    ResetEntry
    $a
    Init
        0x00000000:    eafffffe    ....    B        ResetHandler  ; 0x120
        0x00000004:    eafffffe    ....    B        HandlerUndef  ; 0x78
        0x00000008:    eafffffe    ....    B        HandlerSWI  ; 0x90
        0x0000000c:    eafffffe    ....    B        HandlerPabort  ; 0xc0
        0x00000010:    eafffffe    ....    B        HandlerDabort  ; 0xa8
        0x00000014:    eafffffe    ....    B        {pc}  ; 0x14
        0x00000018:    e59ff0dc    ....    LDR      HandlerIRQ
        0x0000001c:    eafffffe    ....    B        HandlerFIQ  ; 0x48
        0x00000020:    eafffffe    ....    B        EnterPWDN  ; 0x3f4
这个2440init.s在链接器里面是设置过的放在生成目标文件的最开始的部分的,也就是0x0的地方,从汇编过的代码来看,在0x00-0x1c地址处,放的也正是中断向量表,所以在生成的.bin文件中,这个中断向量表应该也是在最开始的地方,将.bin下载到nand flash里面后,也应该在最开始的地方,而上电后,nand控制器将前4k的内容自动复制到片内sram内,所以,在sram开始的位置,肯定是有一份中断向量表的。那么不开mmu的时候,如果发生中断,程序应该会跳到这个地方来的,可是为什么这里的跳转不能正确将程序引导到中断处理函数中去呢?跳转指令我改过了,用的是ldr,用绝对地址来跳

#15


关于s3c2440从nand flash的疑惑我老实用我的开发板试了下,在我的板子上使用的异常向量表是被映射到0地址的SRAM上。另外,由于我的TLB把0x0 - 0xa0000000的虚拟地址映射到了对应的实地址,所以不管开没开MMU都是使用的SRAM上的中断向量。

至于你的情况,
一、你在u-boot中检查下SRAM中的内容,是否被改变。
二、检查CP15 c0的V位设置,有源码就看看开,关MMU的语句。
    如果这个位被置为‘1’,则异常向量表的位置将不再是地址‘0’。
三、异常向量表的跳转指令是否正确。

关MMU不能执行异常中断应该是这三处地方……

#16


引用 15 楼 JQGuardian 的回复:
我老实用我的开发板试了下,在我的板子上使用的异常向量表是被映射到0地址的SRAM上。另外,由于我的TLB把0x0 - 0xa0000000的虚拟地址映射到了对应的实地址,所以不管开没开MMU都是使用的SRAM上的中断向量。

至于你的情况,
一、你在u-boot中检查下SRAM中的内容,是否被改变。
二、检查CP15 c0的V位设置,有源码就看看开,关MMU的语句……

我刚才看了下,我的0x00000000地址不能访问,往里面写数,再读出来,全是0,但是外部sdram的地址0x30000000可以正常访问,真郁闷…