6410开发板上有nor芯片,但是u-boot没有做nor驱动,将u-boot保存在nor中比较安全,因为nand很有可能会被全部清空。
查看开发板硬件原理图,发现使用的nor flash芯片是am29lv160DB,2MByte,但是由于a20被ddr占用,只连接了a0-a18这19根数据线,也就是只能使用1Mbyte空间。
既然只有1Mbyte空间,应该和am29lv800这颗芯片的使用方法兼容,查看smdk6410.h,发现启动有AMD_LV800相关的定义,smdk6410文件夹中的flash.c文件也是针对AMD_LV800的,看来使用nor芯片的难度不大。
1 为u-boot添加nor驱动支持
1)修改smdk6410.h文件
确认打开宏定义#define CONFIG_AMD_LV800
修改#define CFG_FLASH_BASE 0x10000000
根据原理图,nor芯片使用CSn[0]片选,基址0x10000000
修改#define CFG_MAX_FLASH_BANKS 1
至少有一颗nor芯片
修改#define CFG_MAX_FLASH_SECT 19
nor flash大小
2)重新编译下载后,启动能够识别出nor flash芯片
Flash: 1 MB
但是任何操作均没有响应
3)查看flash.c源码,发现只要定义CONFIG_AMD_LV800,在flash_init中就会对nor参数进行赋值,并没有从芯片读取数据。
也就说目前并没有真正从nor flash芯片中读到数据。
4)开始怀疑bank宽度设置不正确,因为前面做dm9000ae时就需要将bank宽度设置为16。
查看s3c6410数据手册,发现CSn[0]的bank宽度又H/W控制,如果配置nor启动,能够正确设置,但我目前还是nand启动。。。
调用printf,在启动时打印出SROM_BW_REG的值,是0xd0,果然,只初始化了CSn[1],CSn[0]还是停留在8bit宽带
5)参考dm9000的初始化,修改smdk6410.c文件
SROM_BW_REG &= ~(0xf); //nor
SROM_BW_REG |= (1<<3) | (1<<2) | (1);
添加初始化带宽代码,当然也可以修改SROM_BC0_REG,优化时序,也可以使用默认值。
6)重新编译后,nor flash可以使用!
nor 开头会被默认设置为RO,每次要unprotect比较烦,可以注释掉flash.c中flash_init相关代码
/*
flash_protect (FLAG_PROTECT_SET,
CFG_FLASH_BASE,
CFG_FLASH_BASE + monitor_flash_len - 1,
&flash_info[0]);
flash_protect (FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
*/
2 为u-boot添加nor启动
其实nor启动比nand启动简单多了,因为程序可以直接在nor中运行,通过简单的搬运代码将自身搬运到ram中即可。
1)修改smdk6410.h文件
#define CONFIG_BOOT_NOR
//#define CONFIG_BOOT_NAND
将nand_boot改为nor_boot
注释掉下面内容
//# error Define one of CONFIG_BOOT_{NAND|MOVINAND|ONENAND|ONENAND_IROM}
还有个宏不知道是否有用,也打开
#define CONFIG_USE_NOR_BOOT
2)重新编译,将内容烧到nor flash的开头(用cp.b比较方便)
将启动方式改为nor(1010)
上电后发现只能显示“OK”就没有内容了,郁闷
用si搜索了ok,没发现相关代码,估计这个ok使用asicii代码输出的(后面印证确实如此)
3)无奈跟u-boot启动代码
首先是执行s3c64xx的start.s文件
下面是代码执行顺序
_start:
reset:
cpu_init_crit:
bl lowlevel_init
这句bl 跳转到lowlevel_init.S初始化处理器代码,如果将其屏蔽掉,就没有OK了
4)跳转到lowlevel_init.s文件
lowlevel_init:
bl mem_ctrl_asm_init (这段在cpu_init.s中)
wakeup_reset:
system_clock_init: 初始化时钟,就是上次改666频率那段汇编
uart_asm_init: 初始话串口
找到输出'O'的代码
ldr r1, =0x4f4f4f4f
str r1, [r0, #UTXH_OFFSET] @'O'
nand_asm_init: 初始话nand基本代码
最后找到输出'K'的代码
ldr r0, =ELFIN_UART_BASE
ldr r1, =0x4b4b4b4b
str r1, [r0, #UTXH_OFFSET]
这段代码可用来跟踪初始化流程!
5)回到start.s,下面的代码实现搬运
/*
* Go setup Memory and board specific bits prior to relocation.
*/
bl lowlevel_init /* go setup pll,mux,memory */
/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
bic r2, r2, r0 /* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq after_copy /* r0 == r1 then skip flash copy */
#ifdef CONFIG_BOOT_NOR /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_PHY_BASE /* r1 <- destination */
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
nor_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 nor_copy_loop
ldr r0, =ELFIN_UART_BASE //在这儿输出'1',是可以的,说明搬运完成,代码应该已经到ram中
ldr r1, =0x31313131
str r1, [r0, #UTXH_OFFSET]
b after_copy
after_copy:
enable_mmu: //打开mmu
ldr r0, =ELFIN_UART_BASE //在这儿输出'2',也可以,说明mmu打开正常
ldr r1, =0x32323232
str r1, [r0, #UTXH_OFFSET]
stack_setup: //初始化堆栈
clear_bss:
ldr r0, =ELFIN_UART_BASE
ldr r1, =0x33333333
str r1, [r0, #UTXH_OFFSET] //在这儿输出'3',也可以,下面就要跳转到c代码了!
ldr pc, _start_armboot
_start_armboot:
.word start_armboot
6)start_armboot位于lib_arm/board.c
void start_armboot (void)
在line289添加puts("a");后,竟然也可以输出,orz,然后,整个u-boot就莫名其妙的好了。。
OK123a
U-Boot 1.1.6 (Aug 19 2009 - 22:36:49) for SMDK6410
****************************************
** UT-S3C6410 Nor boot v2 **
****************************************
CPU: S3C6410@666MHz
Fclk = 666MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (ASYNC Mode)
Board: SMDK6410
DRAM: 128 MB
Flash: 1 MB
NAND: 256 MB
In: serial
Out: serial
Err: serial
kyon6410 #
关于50008000的解释:
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
#
# SAMSUNG SMDK6400 board with mDirac3 (ARM1176) cpu
#
# see http://www.samsung.com/ for more information on SAMSUNG
#
#
# SMDK6410 has a 128 MB SDR SDRAM
#
# 5000'0000 to 5800'0000
#
#
# Linux-Kernel is expected to be at 5000'8000, entry 5000'8000
# optionally with a ramdisk at 5080'0000
#
# we load ourself to 57e0'0000 without MMU
# with MMU, load address is changed to 0xc7e0_0000
#
# download area is 5000'0000
#
http://hi.baidu.com/justin_huangjh/blog/item/ec032413072d6e846538db0f.html
讲的很详细
编译过程中的错误和解决
cpu/s3c64xx/libs3c64xx.a(vfat_hs_mmc.o): In function `hsmmc_reset':
/home/zhangqing/smartq5-bootloader/smartq5-bootloader-20090508/u-boot/cpu/s3c64xx/vfat_hs_mmc.c:219: multiple definition of `hsmmc_reset'
cpu/s3c64xx/libs3c64xx.a(hs_mmc.o):/home/zhangqing/smartq5-bootloader/smartq5-bootloader-20090508/u-boot/cpu/s3c64xx/hs_mmc.c:199: first defined here
cpu/s3c64xx/libs3c64xx.a(vfat_hs_mmc.o): In function `hsmmc_init':
/home/zhangqing/smartq5-bootloader/smartq5-bootloader-20090508/u-boot/cpu/s3c64xx/vfat_hs_mmc.c:1088: multiple definition of `hsmmc_init'
cpu/s3c64xx/libs3c64xx.a(hs_mmc.o):/home/zhangqing/smartq5-bootloader/smartq5-bootloader-20090508/u-boot/cpu/s3c64xx/hs_mmc.c:915: first defined here
make[1]: *** [u-boot] Error 1
make[1]: Leaving directory `/home/zhangqing/smartq5-bootloader/smartq5-bootloader-20090508/u-boot'
make: *** [all] Error 2