该u-boot是移植在JZ2440V2开发板上的,但移植过程跟其他板子移植是一样的,我是在看韦东山老师视频做的笔记,每一步都很详细,有兴趣的可以看看。有错误的地方请指出,谢谢
移植u-boot到jz2440开发板
第一:u-boot移植
首先配置
make smdk2410_config
编译一下u-boot
make
发现编译不通过,要切换编译工具,现在使用arm-linux-gcc 4.3.2
再make 完成编译,把u-boot.bin烧写到板子上看看状况
发现串口没有输出。
所以要分析原因,分析Makefile
分析编译过程来知道u-boot的构成
删掉刚才编译的u-boot,重新编译,只关心最后一条链接命令
arm-linux-ld -pie -T u-boot.lds -Bstatic -Ttext 0x0 arch/arm/cpu/arm920t/start.o --start-group api/libapi.o arch/arm/cpu/arm920t/libarm920t.o arch/arm/cpu/arm920t/s3c24x0/libs3c24x0.o arch/arm/lib/libarm.o common/libcommon.o
从链接命令看到链接文件u-boot.lds 那么,去看看里面的内容
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000; //链接地址是0,那么说明该u-boot是NorFash启动
. = ALIGN(4);
.text :
{
__image_copy_start = .;
arch/arm/cpu/arm920t/start.o (.text) //从start.o开始运行,那么我们就从start.o开始分析
*(.text)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
*(.data)
}
. = ALIGN(4);
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__image_copy_end = .;
.rel.dyn : {
__rel_dyn_start = .;
*(.rel*)
__rel_dyn_end = .;
}
.dynsym : {
__dynsym_start = .;
*(.dynsym)
}
_end = .;
. = ALIGN(4096);
.mmutable : {
*(.mmutable)
}
.bss __rel_dyn_start (OVERLAY) : {
__bss_start = .;
*(.bss)
. = ALIGN(4);
__bss_end__ = .;
}
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
/DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) }
}
分析start.S
u-boot的启动过程
1.set the cpu to SVC32 mode
2.turn off the watchdog
3.mask all IRQs by setting all bits in the INTMR
4.default FCLK is 120 MHz /* 设置分频比例 */
5.cpu_init_crit //设置SDRAM
6.Set stackpointer in internal RAM to call board_init_f //设置栈,调用board_init_f
7.board_init_f
memset((void *)gd, 0, sizeof(gd_t));//将gd_t结构体清0
调用init_sequence函数数组执行
arch_cpu_init
board_early_init_f
timer_init
定时器的初始化get_PCLK()
get_HCLK()
#ifdef CONFIG_S3C2440 //发现该u-boot也支持2440,到时可以配置这个宏
init_baudrate
serial_init
8.relocate_code(addr_sp, id, addr); //重定位代码
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
这段代码也说明该u-boot只支持NORfash
、分析relocate_code(addr_sp, id, addr);的参数[ 在board.c/board_init_f函数中]
addr_sp存在r0 id存在r1 addr存在r2
gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
addr -= gd->mon_len; /* 保留一块内存给bss等 */
gd->mon_len = _bss_end_ofs;
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end__ - _start /* 程序的大小 */
addr_sp = addr - TOTAL_MALLOC_LEN;
addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; /* 0x3000,0000+64M 初始值*/
addr=0x3400,0000
addr -= (4096 * 4);
执行上一句后,addr=33ff0001
addr &= ~(0x10000 - 1); /* 清低16位 */
那么addr=33ff0000
addr_sp = addr - TOTAL_MALLOC_LEN;
addr_sp -= sizeof (bd_t);
bd = (bd_t *) addr_sp; /* bd指向 addr_sp */
gd->bd = bd; /* gd中的某个成员指向bd */
addr_sp -= sizeof (gd_t);
id = (gd_t *) addr_sp;
gd->irq_sp = addr_sp;
addr_sp -= 12;
综上所述:
addr -= (4096 * 4);
addr &= ~(0x10000 - 1);
addr -= gd->mon_len;
留给data,bss,code
Uboot就是拷到这里
addr_sp = addr - TOTAL_MALLOC_LEN;
addr_sp -= sizeof (bd_t);
addr_sp -= sizeof (gd_t);
addr_sp -= 12;
栈:往下增长
SP
gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
了解过程后,我们要修改代码,
在include目录下
把configs目录下的smdk2410.h复制为smdk2440.h
在board目录下
把samsung目下的smdk2410目录复制为smdk2440
修改之后,配置,编译,看能不能通过
make smdk2440_config
发现不能通过配置,那么查看Makefile
在Makefile中没有找到smdk2410
那么在源代码中搜索一下 grep " smdk2410" * -nR
arch/arm/include/asm/mach-types.h:1644:# define machine_is_smdk2410() (machine_arch_type == MACH_TYPE_SMDK2410)
arch/arm/include/asm/mach-types.h:1646:# define machine_is_smdk2410() (0)
board/samsung/smdk2410/Makefile:28:COBJS := smdk2410.o
board/samsung/smdk2440/Makefile:28:COBJS := smdk2410.o
boards.cfg:65:smdk2410 arm arm920t - samsung s3c24x0
MAINTAINERS:750: smdk2410 ARM920T
vim borads.cgf
复制smdk2410为smd2440
再make smdk2440_config
配置成功
编译
make
编译通过,烧写,但绝对是不能通过的
所以,要调试程序
根据步骤,分析启动过程
该u-boot的不足:
1.时钟没设置只设置了分频比例
2.内存的设置也不对,我们是基于smdk2410的板子修改,所以该sdram的配置是没有用的
那么可以确定修改的地方:1是时钟设置 2是SDRAM的初始化
根据我们之前自己写bootloader事已经有了设置,可以挪用过来使用
处理措施:把MPLL的设置放到start.S中设置,取消
烧写进去的u-boot有反应了,但是出现乱码
继续分析:
1.查看代码发现get_HCLK中#ifdef CONFIG_S3C2440没有被配置
措施:include/smdk2440.h中定义#ifdef CONFIG_S3C2440注释掉#ifdef CONFIG_S3C2410
发现编译出错,从第一个错误开始修改
简单的解决办法,修改makefile让这个文件不要编译进来
在smdk2440.h中去掉#define CONFIG_NAND_S3C2410
去掉#define CONFIG_CMD_NAND
解决掉错误,编译烧写进去看看效果,乱码没有了
U-Boot 2012.04.01 (Apr 25 2015 - 19:51:22)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###
2.支持NANDFLASH启动
根据提示Flash不可用
将上次自己写u-boot的代码拷贝到板子目录
2.1 修改UBOOT支持NAND启动
原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)"
使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)
2.2 去掉 "-pie"选项
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行
2.3 参考"毕业班第1课"的start.S, init.c来修改代码
把init.c放入board/samsung/smdk2440目录, 修改Makefile
修改CONFIG_SYS_TEXT_BASE为0x33f00000
修改start.S
bl nand_init_ll
mov r0, #0
ldr r1, _TEXT_BASE
ldr r2, _bss_start_ofs
bl copy_code_to_sdram
bl clear_bss
ldr pc, =call_board_init_f
ldr r1, _TEXT_BASE //33f00000
bl board_init_r
2.4 修改board_init_f, 把relocate_code去掉
将board_init_f 修改为unsigned int board_init_f 注释掉relocate_code 最后面返回return (unsigned int)id作为board_init_r的参数
去掉addr -= gd->mon_len;
addr &= ~(4096 - 1);
addr=_TEXT_BASE
void board_init_r(gd_t *id, ulong dest_addr)
dest_addr就是程序的链接地址,也就是33f000000 /* 这是定死的值 */
2.5 修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
./arch/arm/cpu/u-boot.lds:
board/samsung/smdk2440/libsmdk2440.o
3.支持Nor FLASH
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###
根据上面的的提示作为参考,然后修改代码
搜索Flash
cfi_flash_bank_addr 在Linux下搜索
drivers/mtd/cfi_flash.c:104:phys_addr_t cfi_flash_bank_addr(int i)
确定了cfi_flash_bank_addr在smdk2440.h中定义为0x00000000也就是NorFlash的地址
CONFIG_FLASH_CFI_LEGACY在配置文件中有定义
flash_detect_legacy旧的方法
flash_get_size新的方法获取NorFlash
1.在board.c中注释掉
//puts(failed);
//hang();
添加调试信息
怎么添加?
#define _DEBUG 1
#define DEBUG 1
编译烧写进板子,查看调试信息
Flash: fwc addr (null) cmd f0 00f0 16bit x 16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16 bit
fwc addr 00005554 cmd 55 0055 16bit x 16 bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16 bit
fwc addr (null) cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID c2 2249 0
fwc addr (null) cmd ff 00ff 16bit x 16 bit
fwc addr (null) cmd 90 0090 16bit x 16 bit
fwc addr (null) cmd ff 00ff 16bit x 16 bit
JEDEC PROBE: ID 13 ea00 0
0 KB
*** Warning - bad CRC, using default environment
根据这些调试信息进行代码修改
1.JEDEC PROBE搜索一下,查看到
debug("JEDEC PROBE: ID %x %x %x\n",
info->manufacturer_id,
info->device_id,
info->device_id2);
2.jedec_flash_match,该函数做的内容就将info传入跟里面的某个数组比较,看是否匹配
如果不匹配,那么就认为没有找到
那么,我们需要查看数据手册知道该芯片的info
阅读norflash芯片手册
如果想读Manifacture ID的话
填入AA,55,读x00就得到C2
Device ID是
芯片手册有说明
这两个值正好对应串口打印出来的信息,但是为什么还是失败呢,很显然,jedec_flash_match函数在里面没有找到匹配的数组.所以,我们需要添加
进入jedec_flash_match函数
jedec_table
添加数组就行了
{
.mfr_id = (u16)MX_MANUFACT, /* 厂家ID。从芯片手册中得到 */
.dev_id = 0x2249, /* 芯片手册中得到的设别ID */
.name = "MXIC MT29LV160DB",
.uaddr = { /* 解锁地址 */
[1] = MTD_UADDR_0x0555_0x02AA /* x16 0表示8位,1表示16位、*/
},
.DevSize = SIZE_2MiB, /* 总大小 */
.CmdSet = P_ID_AMD_STD, /* 命令集 */
.NumEraseRegions= 4, /* 几种模式 */
.regions ={
ERASEINFO(16*1024,1),
ERASEINFO(8*1024,2),
ERASEINFO(32*1024,1),
ERASEINFO(64*1024,31),
}
},
NOR FLASH读取跟内存差不多,只需要确定他的基地址跟位宽就行了
修改后,编译烧写进板子查看状况
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: fwc addr (null) cmd f0 00f0 16bit x 16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16 bit
fwc addr 00005554 cmd 55 0055 16bit x 16 bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16 bit
fwc addr (null) cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID c2 2249 0
ERROR: too many flash sectors
2 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
那么,该u-boot识别了板子使用的芯片,现在可以去掉调试信息了
还需要重新设置栈,在start.S中,定义一个全局变量
.global base_sp
base_sp:
.long base_sp
在第二阶段的时候也就是board_init_r时,读sp
ldr sp, base_sp
在board.c中的board_init_f函数中声明一下
extern ulong base_sp
在最后一次调用addr_sp的时候,将addr_sp赋给base_sp
用这个u-boot来更新自己,用loady命令
用loady下载
Loady 32000000
下载完成,输入命令
protect off all
erase 0 7ffff
cp.b 32000000 0 80000
reset
再次测试
protect off all
erase 80000 8ffff
cp.b 30000000 80000 10000
cmp.b 30000000 80000 10000
发现没有问题了
|
|