2015年(72)
分类: 嵌入式
2015-04-15 10:49:14
2.1 修改cpu/arm920t/start.S
(1)删除AT91RM9200使用的LED代码,117、118行,关闭LED代码。
start_code:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x
orr r0,r0,#0xd3
msr cpsr,r0
//bl coloured_LED_init
//bl red_LED_on
(2)修改编译条件支持s
#ifdef (CONFIG_S
/* turn off the watchdog */
# if defined(CONFIG_S
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else
# define pWTCON 0x53000000
# define INTMSK 0x
# define INTSUBMSK 0x
# define CLKDIVN 0x
# endif
修改 CPU频率初始化设置147行
//xujun
#define CLK_CTL_BASE 0x
#define MDIV_405 0x
#define PSDIV_405 0x21
#define MDIV_200 0xa1 <<12
#define PSDIV_200 0x31
(3)修改中断禁止部分
165行修改0x3ff为0x7ff
#if defined(CONFIG_S
ldr r1, =0x7ff /*根据2410芯片手册,INTSUBMSK有11位可用*/
ldr r0, =INTSUBMSK
str r1, [r0]
#endif
170行添加
#if defined(CONFIG_S
ldr r1, =0x7fff
ldr r0, =INTSUBMSK
str r1, [r0]
#endif
(4)修改时钟设置(2440的主频为405MHz。)175行
//xujun
#if defined(CONFIG_S
/* FCLK:HCLK:PCLK = 1:4:8 */
ldr r0,=CLKDIVN
mov r1,#5
str r1,[r0]
mrc p15,0,r1,c1,c0,0
orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0
mov r1,#CLK_CTL_BASE
mov r2,#MDIV_405
add r2,r2,#PSDIV_405
str r2,[r1,#0x04]
#else
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
//xujun
mrc p15,0,r1,c1,c0,0
orr r1,r1,#0xc0000000
mcr p15,0,r1,c1,c0,0
mov r1,#CLK_CTL_BASE
mov r2,#MDIV_200
add r2,r2,#PSDIV_200
str r2,[r2,#0x04]
#endif
#endif /* CONFIG_S
(5)将从自动识别从NAND Flash启动还是从Nor flash启动
代码原理:在启动的时候,用程序将0x40000000~0x40001000中的某些位置清零,如果回读0x00000000~0x00001000中的相应位置后为零,说明是Nand boot,如果是原来的数据(一定要选非零的位置)就是Nor boot。判断完后如果是nand boot,还要恢复被改动的数据,再进入自拷贝阶段。
只要检测的位置合理,这方法是可行的。现在的关键是选什么位置的数据最好呢?经过查看源码,我选择了在start.S文件开头,全局中断向量之后的:
.balignl 16,0xdeadbeef
选这个数据作为检测位置的理由如下:
(1)他是非零数,而且数据是确定的:0xdeadbeef
;
(2)他的位置是固定的:0x0000003c(0x4000003c);
(3)他在检测程序之前,不会影响程序的向下运行;
(4)他不属于程序,他是一个程序中的魔数(Magic Number),用魔数来检测也比较合理。
所以最后的检测步骤是:
在启动的时候,将0x4000003c位置开始的四个字节清零,然后读取0x0000003c位置开始的四个字节。如果回读的结果为零,说明是nand boot,否则就是Nor boot(为了保险还可以判断是否为0xdeadbeef
,不是的话就说明有未知错误,死循环!)。但是最后有一点很重要:如果是Nand boot,必须要复原清零的数据。原因是:在nand boot过后,会核对内部SRAM中的4K程序,和从Nand中拷贝到SDRAM的前4K程序是否一致,如果不一致会进入死循
在218行将原来转移nor flash启动的代码修改为:
(1)判断当前代码位置,如果在内存,直接跳到stack_setup
/***************** CHECK_CODE_POSITION **********************************/
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
/***************** CHECK_CODE_POSITION ************************************/
(2)如果不是在代码当前位置不在内存中,就判断启动的Flash:Nand 或者Nor
/***************** CHECK_BOOT_FLASH *************************************/
ldr r1, =( (4<<28)|(3<<4)|(3<<2) ) /* address of Internal SRAM 0x
mov r0, #0 /* r0 = 0 */ //0x
str r0, [r1]
mov r1, #0x
ldr r0, [r1]
cmp r0, #0 //判断0x
bne relocate //如果0x
/* recovery */
ldr r0, =(0xdeadbeef) //如果0x
ldr r1, =( (4<<28)|(3<<4)|(3<<2) ) //先恢复0x
str r0, [r1]
/***************** CHECK_BOOT_FLASH ***********************************/
(3)如果判断是在Nand Flash中启动的话,那么nand Flash搬移代码如下:
定义u-boot在nand flash中存放的长度为#define LENGTH_UBOOT 0x60000,可以方便修改u-boot因为裁剪和增添大小的改变而占的长度。
// copy U-Boot to RAM form Nand Flash
/***************** NAND_BOOT *******************************************/
#define LENGTH_UBOOT 0x60000
#define NAND_CTL_BASE 0x4E000000
#ifdef CONFIG_S
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFSTAT 0x20
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
str r2, [r1, #oNFCONT]
ldr r2, [r1, #oNFCONT]
ldr r2, =(0x6) @ RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x4
beq nand2
ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2 @ Flash Memory Chip Disable
str r2, [r1, #oNFCONT]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #LENGTH_UBOOT
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2:
b loop2 @ infinite loop
ok_nand_read:
@ verify
mov r0, #0
ldr r1, =TEXT_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq stack_setup
bne go_next
notmatch:
loop3:
b loop3 @ infinite loop
#endif
#ifdef CONFIG_S
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFSTAT 0x10
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #oNFCONF]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x1
beq nand2
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #LENGTH_UBOOT
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2:
b loop2 @ infinite loop
ok_nand_read:
@ verify
mov r0, #0
ldr r1, =TEXT_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq stack_setup
bne go_next
notmatch:
loop3:
b loop3 @ infinite loop
#endif
/*************** NAND_BOOT *******************************/
(4) 如果判断是在Nor Flash中启动的话,那么nor Flash搬移代码如下
// copy U-Boot to RAM form Nor Flash
//#ifndef CONFIG_SKIP_RELOCATE_UBOOT
/***************** NOR_BOOT *************************************************/
relocate: /* relocate U-Boot to RAM */
/*********** CHECK_FOR_MAGIC_NUMBER***************/
ldr r1, =(0xdeadbeef)
cmp r0, r1
bne loop3
/*********** CHECK_FOR_MAGIC_NUMBER***************/
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
//cmp r0, r1 /* don't reloc during debug */
//beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
/***************** NOR_BOOT *************************************************/
//#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
在“ldr pc, _start_armboot”之后加入LED代码:
ldr pc, _start_armboot
#if defined(CONFIG_MINI2440_LED)
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_B
ldr r2,=0x156aa
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
mov r2, #0x
str r2, [r1, #oGPIO_DAT]
#endif
_start_armboot: .word start_armboot
在 “ _start_armboot: .word start_armboot ” 后加入:
_start_armboot: .word start_armboot
#define STACK_BASE 0x
#define STACK_SIZE 0x10000
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4