| 
 
| 该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
 
 发现没有问题了
 
 
 | 
 |