Nand flash启动模式详解(LED程序为例)(2)

但是由于arm上电后系统会将Nand flash的前4KB代码拷贝到SRAM中,也就是_start函数开始的4KB指令将被拷贝到SRAM中执行,根据上例,在0x00000000处执行的指令就是“b reset”,由于b是相对跳转,是在当前pc值的基础上加减某个数而跳转到将要执行的代码处,因此,pc加减该数之后将到达reset函数的位置,故reset函数不能写到4KB之外的空间中,否则arm的启动将会失败,同样的,接下来的几个bl都是执行的相对跳转,所以都相对当前pc进行的跳转,由于Nand flash总共只有64M的空间,所以相对跳转是不可能会跳转到SDRAM的,因为跳转到SDRAM至少要发生0x30000000的跳转,而这个相对位移远远大于64M。

而ldr pc,=Main是将Main函数的实际地址赋值给pc,而Main的实际地址是在0x30000000之后,这样,就从SRAM跳转到了SDRAM。

由于这个过程设计到了硬件格局和编译原理,所以对一般人来讲,理解起来确实比较困难,而且受本人水平限制,很多地方只能说是只可意会不可言传,如果误导了大家请大家谅解。当然如果看到这里还不能理解arm的启动过程可以联系QQ630905224来讨论这个问题。下面是相关的其他代码,我附在这里,2440addr.h没有贴出,由于我也是使用arm自带示例程序中的代码,而且代码有四千多行,多数地址是没有用到的,如果有人需要就联系我的QQ吧。其他的代码如下

代码Init.s

#include "2440addr.h"      void disable_watch_dog(void);   void clock_init(void);   void memsetup(void);   void copy_steppingstone_to_sdram(void);   void inituart(void);      void disable_watch_dog(void)   {       rWTCON = 0;   }      void clock_init(void)   {       rCLKDIVN  = 0x03;          /*        *如果HDIVN非0,CPU的总线模式应该从        *“fast bus mode”变为“asynchronous         *bus mode”        */       __asm__(               "mrc    p15, 0, r1, c1, c0, 0\n"               "orr    r1, r1, #0xc0000000\n"               "mcr    p15, 0, r1, c1, c0, 0\n"              );          rMPLLCON = (92<<12)|(1<<4)|(2);       //rMPLLCON =  ((0x5c<<12)|(0x01<<4)|(0x02));   }      void memsetup(void)   {       volatile unsigned long *p = (volatile unsigned long *)0x48000000;          /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值        * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到        * SDRAM之前就可以在steppingstone中运行        */       /* 存储控制器13个寄存器的值 */       p[0] = 0x22011110;     //BWSCON       p[1] = 0x00000700;     //BANKCON0       p[2] = 0x00000700;     //BANKCON1       p[3] = 0x00000700;     //BANKCON2       p[4] = 0x00000700;     //BANKCON3         p[5] = 0x00000700;     //BANKCON4       p[6] = 0x00000700;     //BANKCON5       p[7] = 0x00018005;     //BANKCON6       p[8] = 0x00018005;     //BANKCON7          /* REFRESH,        * HCLK=12MHz:  0x008C07A3,        * HCLK=100MHz: 0x008C04F4        */        p[9]  = 0x008C04F4;       p[10] = 0x000000B1;     //BANKSIZE       p[11] = 0x00000030;     //MRSRB6       p[12] = 0x00000030;     //MRSRB7   }      void copy_steppingstone_to_sdram(void)   {       unsigned int *pdwSrc  = (unsigned int *)0;       unsigned int *pdwDest = (unsigned int *)0x30000000;          while (pdwSrc < (unsigned int *)4096)       {           *pdwDest = *pdwSrc;           pdwDest++;           pdwSrc++;       }   }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/0666cbeaba66312d08e30260aacc222a.html