一、开发环境
Linux发行版本:CentOS 7
远程登陆工具:C-kermit(这里只使用其串口通信功能)
开发板:mini2440
J-link版本:V9
调试软件:J-link Commander
二、问题及解决方案
1、Linux环境下没有J-flash软件,只有J-link Commander,我们无法使用J-link直接烧写NOR flash,所以我们只能利用J-link Commander烧写不需要初始化的片内SRAM;
2、片内SRAM只有4K大小,然而u-boot通常有100~300K大小,u-boot不能直接在SRAM中运行,J-link又不能烧写NAND flash,但是SDRAM有64M大小,只是需要初始化才能利用J-link烧写程序,所以我们将SDRAM初始化程序烧写进SRAM中并运行,然后将为能够在SDRAM中运行而定制的u-boot烧写进SDRAM中并运行,再将需要烧写进NAND flash中的u-boot烧写到SDRAM中的另一段空间,最后使用运行在SDRAM中的u-boot将需要烧写进NAND flash中的u-boot复制到NAND flash中。
三、操作步骤
1、将开发板跳线开关打至从NAND flash启动一侧启动;
2、将初始化SDRAM(内存)的程序烧写进片内4K的SRAM,并且使其运行:
SDRAM初始化程序及其Makefile:
init.S
@******************************************************************************
@ init.S
@ 功能:J-link先将init.bin下载到Steppingstone(内部RAM)中,初始化SDRAM等
@ 然后就可以将bootloader直接下载到SDRAM中运行
@******************************************************************************
#define DELAY_COUNT 700000
.text
.global _start
_start:
Reset:
mrs r0, CPSR
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr CPSR_fc, r0 @ Supervisor mode, sets the I and F bits
mov r0, #0x53000000
mov r1, #0
str r1, [r0] @ disable WTCON
mvn r1, #0 @ 0x0
ldr r0, =0x4a000008
str r1, [r0] @ INTMSK = 0xFFFFFFFF
ldr r1, =0x000003ff
ldr r0, =0x4a00001c
str r1, [r0] @ INTSUBMSK = 0x000003ff
mov r0, #0
mcr 15, 0, r0, cr7, cr7, 0 @ invalidate I,D caches on v4
mcr 15, 0, r0, cr8, cr7, 0 @ invalidate I,D TLBs on v4
mrc 15, 0, r0, cr1, cr0, 0 @ get control register v4, read control register P539
bic r0, r0, #0x2300 @ V[bit[13]](Base location of exception registers)=0 = Low addresses = 0x0000 0000
@ R(ROM protection bit[9])=0
@ S(System protection bit[8])=0
@ 由于TTB中AP=0b11(line141),所以RS位不使用
bic r0, r0, #0x87
@ M(bit[0])=0 = MMU disabled
@ A(bit[1])=0 =Data address alignment fault checking disable
@ C(bit[2])=0 = Data cache disabled
@ B(bit[7])=0 = Little-endian operation
orr r0, r0, #0x2 @ /* .... .... .... ..1. *//*A(bit[1])=1 = Data address alignment fault checking enable*/
orr r0, r0, #0x1000 @ /* ...1 .... .... .... *//*I(bit[12])=1 = Instruction cache enabled*/
mcr 15, 0, r0, cr1, cr0, 0 @ /* write control register *//*write control register P545*/
@ set memory control registers
mov r1, #0x48000000
adrl r2, mem_cfg_val
add r3, r1, #52
1: ldr r4, [r2], #4
str r4, [r1], #4
cmp r1, r3
bne 1b
mrc 15, 0, r1, cr1, cr0, 0 @ read ctrl register
orr r1, r1, #0xc0000000 @ Asynchronous bus mode
mcr 15, 0, r1, cr1, cr0, 0 @ write ctrl register
@ Light LEDs
leds_flicker:
ldr r2, =0x56000010 @ GPBCON
mov r3, #((1<<(5*2)) | (1<<(6*2)) | (1<<(7*2)) | (1<<(8*2))) @ GPB5_out|GPB6_out|GPB7_out|GPB8_out
str r3, [r2]
ldr r5, =0x56000014 @ GPBDAT
mov r4, #0 @ 0x0
led_loop:
ldr r0, =DELAY_COUNT
bl wait
mvn r3, r4, lsl #5
add r4, r4, #1 @ 0x1
cmp r4, #16 @ 0x10
subeq r4, r4, #16 @ 0x10
str r3, [r5]
b led_loop
wait:
subs r0, r0, #1
bne wait
mov pc, lr
.align 4
mem_cfg_val:
.long 0x2201d110
.long 0x00000700
.long 0x00000700
.long 0x00000700
.long 0x00001f4c
.long 0x00000700
.long 0x00000700
.long 0x00018005
.long 0x00018005
.long 0x008C04F4 @ HCLK=100MHz
# .long 0x008C062C @ HCLK=60MHz
# .long 0x008C067A @ HCLK=50MHz
.long 0x000000B1
.long 0x00000030
.long 0x00000030
Makefile
objs := init.o
all: $(objs)
arm-elf-ld -Ttext 0x0000000 -o init_elf $^
arm-elf-objcopy -O binary -S init_elf init.bin
arm-elf-objdump -D -m arm init_elf > init.dis
%.o:%.c
arm-elf-gcc -Wall -g -c -o $@ $<
%.o:%.S
arm-elf-gcc -Wall -g -c -o $@ $<
clean:
rm -f init.bin init_elf init.dis *.o
编译生成init.bin之后在J-link Commander中输入以下命令:
h
loadbin /some/place/init.bin 0x00000000
setpc 0x00000000
g
如果看到开发板的四个用户LED灯以0~16轮流计数,则说明SDRAM初始化成功。
3、修改并编译已经移植好的u-boot的代码使其能够在SDRAM中运行,然后烧写进SDRAM使其运行:
在smdk2440a.h文件中#undef CONFIG_SKIP_LOWLEVEL_INIT这一行的下面添加#define CONFIG_SKIP_LOWLEVEL_INIT。定义了CONFIG_SKIP_LOWLEVEL_INIT之后那么位于start.S文件中的cpu_init_crit函数就不会运行。这个函数是SDRAM的初始化函数,因为此时u-boot在SDRAM中运行,如果此时初始化SDRAM则程序将崩溃。
再将smdk2440a.h文件中的LCD部分的如下宏定义删除,否则u-boot将卡在”Video:”。
#if 0 //Changed 1 to 0
#define CONFIG_CMD_BMP
#define CONFIG_VIDEO
#define CONFIG_VIDEO_S3C2410
#define CONFIG_VIDEO_LOGO
#define VIDEO_FB_16BPP_WORD_SWAP
#define CONFIG_VIDEO_SW_CURSOR
#define CONFIG_VIDEO_BMP_LOGO
//#define CONFIG_CONSOLE_EXTRA_INFO
//#define CONFIG_CONSOLE_CURSOR
//#define CONFIG_CONSOLE_TIME
#define CONFIG_CFB_CONSOLE
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
//#define CFG_CONSOLE_INFO_QUIET
//#define VIDEO_FB_LITTLE_ENDIAN
#define CONFIG_SPLASH_SCREEN
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (240*320+1024+100) /* 100 = slack */
#define CONFIG_VIDEO_BMP_GZIP
#define CONFIG_CMD_UNZIP
#define LCD_VIDEO_ADDR 0x33d00000
/*for PC-keyboard*/
#define VIDEO_KBD_INIT_FCT 0
#define VIDEO_TSTC_FCT serial_tstc
#define VIDEO_GETC_FCT serial_getc
保存,然后编译生成u-boot.bin,在J-link Commander中输入如下命令将修改后的u-boot烧写进SDRAM中并运行:
h
loadbin /some/place/u-boot.bin 0x33f80000
setpc 0x33f80000
g
其中运行地址0x33f80000在smdk2440a文件夹里的config.mk中有定义,此时就能看到串口中u-boot输出的信息了。
4、将需要烧写进NAND flash里的u-boot烧写到SDRAM中的另一地址:
在J-link Commander中输入以下命令:
h
loadbin /some/place/u-boot.bin 0x30000000
g
5、用u-boot命令行擦除NAND flash中的数据,并且将SDRAM中需要烧写进NAND flash里的u-boot复制进NAND flash:
在u-boot命令行中输入以下命令:
nand erase 0 50000
//擦除从0地址开始的大小为0x40000的Nnad Flash扇区,0x40000是待写入的U-boot.bin的大致长度,长度必须为NAND Flash页大小的整数倍,通常会需要比u-boot.bin实际长度长。
nand write 30000000 0 50000
//把前面下载到0x30000000的u-boot.bin烧写到Nand去
6、重启开发板,u-boot将从NAND flash启动。