分类: 嵌入式
2011-06-11 22:55:41
@******************************************************************************
@ File:crt0.S
@ 功能:将NAND中的《4KB的程序自动映射片内4kb的sram中调用C程序运行
@******************************************************************************
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启
ldr sp, =1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
bl main @ 调用C程序中的main函数
halt_loop:
b halt_loop
@*************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@*************************************************************************
.equ MEM_CTL_BASE, 0x48000000
.equ SDRAM_BASE, 0x30000000
.text
.global _start
_start:
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
bl memsetup @ 设置存储控制器
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
ldr pc, =on_sdram @ 跳到SDRAM中继续执行
on_sdram:
ldr sp, =0x34000000 @ 设置堆栈
bl main
halt_loop:
b halt_loop
disable_watch_dog:
@ 往WATCHDOG寄存器写0即可
mov r1, #0x53000000
mov r2, #0x0
str r2, [r1]
mov pc, lr @ 返回
copy_steppingstone_to_sdram:
@ 将Steppingstone的4K数据全部复制到SDRAM中去
@ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000
mov r1, #0
ldr r2, =SDRAM_BASE
mov r3, #4*1024
1:
ldr r4, [r1],#4 @ 从Steppingstone读取4字节的数据,并让源地址加4
str r4, [r2],#4 @ 将此4字节的数据复制到SDRAM中,并让目地地址加4
cmp r1, r3 @ 判断是否完成:源地址等于Steppingstone的未地址?
bne 1b @ 若没有复制完,继续
mov pc, lr @ 返回
memsetup:
@ 设置存储控制器以便使用SDRAM等外设
mov r1, #MEM_CTL_BASE @ 存储控制器的13个寄存器的开始地址
adrl r2, mem_cfg_val @ 这13个值的起始存储地址
add r3, r1, #52 @ 13*4 = 54
1:
ldr r4, [r2], #4 @ 读取设置值,并让r2加4
str r4, [r1], #4 @ 将此值写入寄存器,并让r1加4
cmp r1, r3 @ 判断是否设置完所有13个寄存器
bne 1b @ 若没有写成,继续
mov pc, lr @ 返回
.align 4
mem_cfg_val:
@ 存储控制器13个寄存器的设置值
.long 0x22011110 @ BWSCON
.long 0x00000700 @ BANKCON0
.long 0x00000700 @ BANKCON1
.long 0x00000700 @ BANKCON2
.long 0x00000700 @ BANKCON3
.long 0x00000700 @ BANKCON4
.long 0x00000700 @ BANKCON5
.long 0x00018005 @ BANKCON6
.long 0x00018005 @ BANKCON7
.long 0x008C07A3 @ REFRESH
.long 0x000000B1 @ BANKSIZE
.long 0x00000030 @ MRSRB6
.long 0x00000030 @ MRSRB7
@*************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU,一,建立映射表格
表格里面是虚拟地址和物理地址的对应关系
这种映射关系以1MB为单位
二,将映射表格首地址告诉MMU
映射表格建立在内存SDRAM上,
三,启动MMU
MMU自带权限管理,CACHE功能
@ 然后跳到SDRAM继续执行
@*************************************************************************
.text
.global _start
_start:
ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
bl memsetup @ 设置存储控制器以使用SDRAM
bl copy_2th_to_sdram @ 将第二部分代码复制到SDRAM
bl create_page_table @ 设置页表
bl mmu_init @ 启动MMU
ldr sp, =0xB4000000 @ 重设栈指针,指向SDRAM顶端(使用虚拟地址)
ldr pc, =0xB0004000 @ 跳到SDRAM中继续执行第二部分代码
@ ldr pc, =main
halt_loop:
b halt_loop
@******************************************************************************
@ File:head.s
@ 功能:设置SDRAM,将NAND中的程序》4KB的程序复制到SDRAM,然后跳到SDRAM继续执行
Nand
没有地址线,只有8根数据线和控制信号线
在控制信号的作用下,地址线借用数据线
控制信号线直接接到CPU相应引脚上,控制信号线的状态由cpu的NAND寄存器设置
操作方式:Nand内自己编址,
以字节为单位:256M=268435456b
以页为单位256M=131072页
以块为单位256M=2048块
硬件上对Nand访问,
一, 发命令,CLE,DATA BUS
二, 给地址,ALE,DATABUS
三, 传输数据,R/W,DATABUS
2440对NAND的访问:即对这四个寄存器的操作
1, NFCMND
2, NFADDR
3, NFDADA
4, NFSTAT
@******************************************************************************
.text
.global _start
_start:
@函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义
ldr sp, =4096 @设置堆栈
bl disable_watch_dog @关WATCH DOG
bl memsetup @初始化SDRAM
bl nand_init @初始化NAND Flash
@将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中
@nand_read_ll函数需要3个参数:
ldr r0, =0x30000000 @1. 目标地址=0x30000000,这是SDRAM的起始地址
mov r1, #4096 @2. 源地址 = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处
mov r2, #2048 @3. 复制长度= 2048(bytes),对于本实验的main.c,这是足够了
bl nand_read @调用C函数nand_read
ldr sp, =0x34000000 @设置栈
ldr lr, =halt_loop @设置返回地址
ldr pc, =main @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转
halt_loop:
b halt_loop
1,系统默认分配那几个向量地址
A,当然第一个是复位,复位程序那里禁用掉看门狗,设置各个中断模式的SP位置
注意:调用C函数,首先要设置好堆栈,例如main函数。
B,其他几个中断向量入口地址,当发生相应的中断后,系统自动跳到相应的入口地址处
2,中断处理程序:
a) 计算返回地址
b) 保护现场,压入那个模式的堆栈
c) 中断处理
d) 清除中断标志
e) 恢复现场
f) 中断返回
.global _start
_start:
b Reset
HandleUndef:
b HandleUndef
HandleSWI:
b HandleSWI
HandlePrefetchAbort:
b HandlePrefetchAbort
HandleDataAbort:
b HandleDataAbort
HandleNotUsed:
b HandleNotUsed
HandleIRQ:
b HandleIRQ
HandleFIQ:
b HandleFIQ
Reset:
ldr sp, =4096 @ 设置栈指针,因为以下都是C函数 bl disable_watch_dog @ 关闭看门狗否则CPU会不断重启
msr cpsr_c, #0xd2 @ 进入中断模式
ldr sp, =3072 @ 设置中断模式栈指针
msr cpsr_c, #0xd3 @ 进入管理模式
ldr sp, =4096 @ 设置管理模式栈指针,
@ 其实复位之后,CPU就处于管理模式,
bl init_led @ 初始化LED的GPIO管脚
bl init_irq @ 调用中断初始化函数,在init.c中
msr cpsr_c, #0x53 @ 设置I-bit=0,开IRQ中断
ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4 @ 计算返回地址
stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器
@ 注意,此时的sp是中断模式的sp
@ 初始值是上面设置的3072
ldr lr, =int_return @ 设置调用EINT_Handle函数的返回地址
ldr pc, =EINT_Handle @ 调用中断服务函数在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsr
void EINT_Handle()
{
unsigned long oft = INTOFFSET;
unsigned long val;
switch( oft )
{
// S2被按下
case 0:
case1:
。。。。。
}
//清中断
if( oft == 5 )
EINTPEND = (1<<11); // EINT8_23合用IRQ5
SRCPND =
1<
INTPND =
1<
}