arm:启动代码判断是从nand启动还是从norflash启动,拷贝程序到内存的过程
一、nand启动和nor启动:[1]
CPU从0x00000000位置开始运行程序。
1、nand启动:
如果将S3C2440配置成从NANDFLASH启动(将开发板的启动开关拔到nand端,此时OM0管脚拉低)S3C2440的Nand控制器会自动把Nandflash中的前4K代码数据搬到内部SRAM中(地址为0x40000000),同时还把这块SRAM地址映射到了0x00000000地址。CPU从0x00000000位置开始运行程序。
2、如果将S3C2440配置成从Norflash启动(将开发的启动开关拔到nor端,此时OM0管脚拉高),0x00000000就是norflash实际的起始地址,norflash中的程序就从这里开始运行,不涉及到数据拷贝和地址映射
3、总结:
nand启动时,地址0x00000000为内部SRAM映射的地址;
nor启动时,地址0x00000000为norflash的实际起始地址。
向Norflash中写数据需要特定的命令时序,而向内存中写数据可以直接向内存地址赋值。
二、判断是从nand启动还是从norflash启动:
1.根据硬件接线,
引脚OM1、OM0 : 00: Nand-boot 01: 16-bit 10: 32-bit 11: Test mode
总线宽度和等待控制寄存器(BWSCON)0x48000000 BWSCON_bit[2:1] Indicate data bus width for bank 0 (read only).
The states are selected by OM[1:0] pins 。(01 = 16-bit, 10 = 32-bit ...)
what's done before copy?
ResetHandler
;WTCON watch dog disable
;INTMSK
;INTSUBMSK
;To reduce PLL lock time, adjust the LOCKTIME register.
;Setting value Fclk:Hclk:Pclk
;Configure UPLL
;Configure MPLL
;Check if the boot is caused by the wake-up from SLEEP mode.
;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.
;Set memory control registers
;Initialize stacks
bl InitStacks
; Setup IRQ handler
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there isn t 'subs pc,lr,#4' at 0x18, 0x1c
str r1,[r0]
now copy:
;===========================================================
;// 判断是从nor启动还是从nand启动
;===========================================================
ldr r0, =BWSCON
ldr r0, [r0]
ands r0, r0, # ;
bne NORRoCopy ;BWSCON的[2:1]反映了外部引脚OM[1:0].
;bne:若OM[1:0] != 00, 是从NOR FLash启动.
;若OM[1:0]==00,则为Nand Flash Mode. NandFlashMode
adr r0, ResetEntry ;注意adr得到的是相对地址,非绝对地址. Cpu刚启动时,ResetEntry==0.
cmp r0, # ;再比较入口是否为0地址处
bne InitRamZero ;如果不是0,直接初始化bss段,进入CEntry.
;nop ;===========================================================
;如果ResetEntry==0,说明是cpu刚启动(注意此处是nand启动),那就应该将nand中的代码搬运到sdram中。
;===========================================================
nand_boot_beg
bl ClearSdram ;将内存清零。从内存起始地址--->指定的足够大的范围,不超过内存的实际大小。 mov r5, #NFCONF ;nand控制器初始化
;set clk value
ldr r0, =(<<):OR:(<<):OR:(<<)
str r0, [r5]
;enable control
ldr r0, =(<<):OR:(<<):OR:(<<):OR:(<<):OR:(<<):OR:(<<):OR:(<<):OR:(<<):OR:(<<):OR:(<<)
str r0, [r5, #] bl ReadNandID ;读nandId,从而判断nand芯片的种类. r5 = nandId
mov r6, #
ldr r0, =0xecF1
cmp r5, r0
beq %F1 ;if(nandId==0xecf1){r6=0;//addr_cycle=4}else{r6=1;//addr_cycle=5}
mov r6, # ;Nandaddr(寻址周期 0:4 1:5) bl ReadNandStatus ;r1 = ret_of_ReadNandStatus ,这里似乎没有用。 mov r8, # ;page_addr = r8 = 0;
ldr r9, =ResetEntry ;r9 = size_copyed = pBuff = 0;
mov r10,# ;+081010 feiling nPages_need_to_copy=64(128KB); ands r0, r8, #0x3f ;R0 = R8 & 0X3F ; 如果是第一页(mov r8, #0),本式子equal 0;
bne %F3
mov r0, r8 ;如果是第一页,则检测坏块
bl CheckBadBlk ;unsigned int CheckBadBlk(unsigned int page_addr)
cmp r0, #
addne r8, r8, # ;每块的页数 r8 同时也做计数用。
addne r10,r10,# ;+081010 feiling if(is_bad_block){page_addr+=64;nPages_need_to_copy+=64;}
bne %F4 mov r0, r8
mov r1, r9 ;r1 = r9 = size_copyed
bl ReadNandPage
add r9, r9, # ;size_copyed+=2048
add r8, r8, # ;page_addr+1 cmp r8, r10 ;要拷贝的页数 081010 pht . if(page_addr < nPages_need_to_copy ){copy_loop;}
bcc %B2 mov r5, #NFCONF ;DsNandFlash
ldr r0, [r5, #]
bic r0, r0, #
str r0, [r5, #] ldr pc, =InitRamZero ;此处跳转到内存空间 LDR 装载数据,寻址灵活。 但不改变PSR
;要装载一个被存储的‘状态’并正确的恢复它 可以这样写:ldr r0, [base] 换行 moves pc, r0
;=============================================================================================
;若是从NAND启动,则先清零内存,再从nand[0 ~ user_set_size]拷贝到内存(ro 和.data),再初始化bss段,进入main。
;若是从NOR启动,同样是先清零,后拷贝,再初始化bss段,进入main。为了考虑jlink等调试的情况,避免二次拷贝,才使代码显得复杂。
;其实可以不管,直接全部拷贝过来,nor拷贝比nand拷贝更简单,逐个字节复制即可。;=============================================================================================
NORRoCopy ;copy_proc_from_nor_to_sdram
bl ClearSdram ;clear all sdram needed adr r0, ResetEntry ;判断是否在ROM中运行,ROM即RO指定的地址,从NOR启动时ResetEntry为0
ldr r2, BaseOfROM ;如果相等,说明是jlink调试,调试器将程序.ro段直接下载到了内存,就不需再拷贝。
cmp r0, r2 ;pFrom = r0 = ResetEntry(活的) ; pTo = r2 = BaseOfROM(链接文件写死的) ;pEnd = TopOfROM(链接文件写死的)
beq NORRwCopy ;if(ResetEntry==BaseOfROM){skip RoCopyLoop ,directly do RwCopy;} RoCopyLoop
ldr r3, TopOfROM ; ldmia r0!, {r4-r7}
stmia r2!, {r4-r7} ;mem_ResetEntry----> mem_BaseOfROM ; pFrom+=4;pTo+=4;
cmp r2, r3 ;if(pTo<pEnd){copy_loop;}
bcc %B0 NORRwCopy ;拷贝.data段(已初始化的全局变量、静态变量等),它在固件里占有空间。
ldr r0, TopOfROM ;根据链接文件sct, TopOfROM == BaseOfRW
ldr r1, BaseOfROM ;
sub r0, r0, r1 ;pFrom = r0 = (TopOfROM - BaseOfROM)
ldr r2, BaseOfRW ;pTo = BaseOfRW ,pEnd = BaseOfZero
ldr r3, BaseOfZero cmp r2, r3 ;if(r2<r3){
ldrcc r1, [r0], # ; r1 = [r0] ; r0+=4;
strcc r1, [r2], # ; [r2] = r1 ; r2+=4;
;}
bcc %B0
InitRamZero ;初始化Bss段,之后立即进入CEntry
mov r0, #0
ldr r2, BaseOfZero
ldr r3, EndOfBSS cmp r2, r3 ;清零bss段,bss段(未初始化的全局变量、静态变量)在bin文件中不占空间,只有占位符,因此需要在系统初始化时,手动初始化(一般memset为0);
strcc r0, [r2], #
bcc %B1 ldr pc, =CEntry ;goto compiler address CEntry
bl Main ;Don t use main() because ......
b .
ClearSdram:在拷贝程序到内存之前,先清内存。
;=========================================================
ClearSdram
mov r1,#
mov r2,#
mov r3,#
mov r4,#
mov r5,#
mov r6,#
mov r7,#
mov r8,# ldr r9,=0x00700000 ;size of ram to clear
ldr r0,=0x30000000 stmia r0!,{r1-r8}
subs r9,r9,#
bne %B0
BX lr
2、根据 “向norflash写入数据需要一定的命令序列,而向内存中写数据可以直接向内存地址赋值” 这一点来区别:
//int bBootFrmNORFlash(void) : 判断是否从norflash启动。
//ret== :norflash启动
//ret== :nandflash启动。(或者是jlink调试的情况。)
//说明:该函数应用范围有限,只针对于bootloader最初的stage1。
int bBootFrmNORFlash(void)
{
volatile unsigned int *pdw = (volatile unsigned int *); //volatile
unsigned int dwVal; /*
* 无论是从NOR Flash还是从NAND Flash启动,
* 地址0处为指令"b Reset", 机器码为0xEA00000B,
* 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,
* 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。
* 对于NOR Flash,必须通过一定的命令序列才能写数据,
* 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
* 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash
* 这仅仅针对于初始阶段,norflash启动时,最终也要将程序加载到SDRAM中运行。因此该函数应用范围是有局限性的。
*/ dwVal = *pdw;
*pdw = 0x12345678;
if (*pdw != 0x12345678)
{
return ;
}
else
{
*pdw = dwVal;//测试完后要还原数据。
return ;
}
}
参考:
1、uboot如何检测XC2440是从Nand或Nor启动 http://blog.chinaunix.net/uid-22030783-id-3347621.html
arm:启动代码判断是从nand启动还是从norflash启动,拷贝程序到内存的过程的更多相关文章
- Cortex-M3(NXP LPC 1788) 启动代码
startup_LPC177x_8x.s启动代码分析. 参考资料: Cortex-M3 (NXP LPC1788)之启动代码分析 ARM启动过程(Cortex-M3 NXP LPC1768为例) ;/ ...
- keil 51启动代码
Startup code:启动代码. 在Keil中,启动代码在复位目标系统后立即被执行.启动代码主要实现以下功能: (1) 清除内部数据存储器 (2) 清除外部数据存储器 (3) 清除外部页存储器 ( ...
- 启动代码和Bootloader区别
很多人都会把两者混淆,所以这里稍微说一下. 启动代码和Bootloader有点类似于类和结构体的关系,也就是说结构体只是一种很特殊很特殊的类,但不能说类是一种结构体. 也就是说可以说启动代码是Boot ...
- ARM Linux启动代码分析
前言 在学习.分析之前首先要弄明白一个问题:为什么要分析启动代码? 因为启动代码绝大部分都是用汇编语言写的,对于没学过或者不熟悉汇编语言的同学确实有一定难度,但是如果你想真正深入地学习Linux,那么 ...
- ARM的启动代码(1):介绍(转)
源:ARM的启动代码(1):介绍 很多朋友搞嵌入式,写起代码来一点问题没有,到最后上板子调试的时候,挂了.究其原因,还是对芯片的启动地址.启动方式.bootloader和操作系统的衔接出了问题.今天就 ...
- ARM启动代码中_main 与用户主程序main()的区别
1.1 问题描述 __main函数的作用是什么呀?1.2 问题剖析 __main函数是C/C++运行时库的一个函数,嵌入式系统在进入应用主程序之前必须有一个初始化的过程,使用__m ...
- ARM Cortex-M底层技术(2)—启动代码详解
杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第 ...
- STM32启动代码分析及其汇编学习-ARM
STM32 启动代码 Author By YuCloud 边看启动文件边学汇编 汇编 see ARM: Assembler User Guide see: https://blog.csdn.net/ ...
- S3C2440启动代码2440init.s彻底解析
可以选择nand启动和nor启动,这两者之间的关系通过一个按键来选择 这个OM0有何玄机,在数据手册中有这么一段 位宽RAM启动了(当然,还得设置一些东西,下面就说), Nanaflash启动经历的过 ...
随机推荐
- USB设备在连接PC时的reset从何而来?
近期在做烧写工具的优化工作,有一些关于USB的内容须要总结一下当中包含设备的初始化过程和枚举过程. 在枚举的过程中,设备会一直等PC端的状态,当等到reset命令时会对设备进行又一次枚举.可是这个re ...
- linux之grep用法
运用场景:在当前目录下查找,比如代码目录,不需要在.svn目录下,以及ctags生成的tags文件中查找: grep的--exclude-dir=参数就是为了排除某个目录的,即不包含等号后面的目录: ...
- Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型
Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型 在这一节中,你将添加用于管理数据库中电影的类.这些类是ASP.NET MVC应用程序的模型部分. 你将使用.NET Framewo ...
- Unqualified name lookup
Unqualified name lookup File scope Namespace scope For an qualified name, that is a name that does n ...
- Reverse Integer - Palindrome Number - 简单模拟
第一个题目是将整数进行反转,这个题实现反转并不难,主要关键点在于如何进行溢出判断.溢出判断再上一篇字符串转整数中已有介绍,本题采用其中的第三种方法,将数字转为字符串,使用字符串比较大小的方法进行比较. ...
- Jetty 8.1 安装 运行 部署
链接地址:http://blog.csdn.net/lego2816/article/details/42650545 Java + MySQL 从Jfinal开始,第一步先走完整个流程,主要是发布部 ...
- NOIP2015前
时间过得好快...明天就要出发去NOIP了...然后再过半年就要省选了....希望自己能取得好成绩吧... NOIP2015 bless all !
- hdu 4782 Beautiful Soupz
模拟.其实这题就是题目比较长而已...读完题目就差不多了.tag直接读就可以了,题目说了不用修改.然后整个题目就是让求text部分,严格按空格分开.注意每行前面空格个数. #include<al ...
- ORA-00845 Oracle 启不来修改 MEMORY_TARGET
1.内存减小导致Oracle启动不了 Last login: Sun Nov 4 15:09:06 2012 from 192.168.5.222 [oracle@h1 ~]$ sqlplus ...
- 奔小康赚大钱(km)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...