Chinaunix首页 | 论坛 | 博客
  • 博客访问: 233497
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 781
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-08 10:41
个人简介

爱莉清

文章分类

全部博文(80)

文章存档

2018年(1)

2017年(18)

2016年(49)

2015年(7)

2014年(5)

我的朋友

分类: LINUX

2015-07-04 21:37:18

原文地址: />
作者:    黄英文
编译环境:red hat enterprise linux 5
交叉编译工具链:gcc version 4.3.3    (天嵌公司提供)

解压:tar xjf u-boot-2014.04.tar.bz2
进入u-boot目录:cd u-boot-2014.04
解压后在board/samsung/目录下仍然没有2440,虽然没有直接支持2440开发板,但其代码已经支持,只需添加
相关配置即可。
一、首先建立自己的开发板
拷贝board/samsung/smdk2410/目录到board/tq2440
 cp -a board/samsung/smdk2410 board/tq2440
进入board/tq2440目录修改
[root@localhost u-boot-2014.04]# cd board/tq2440/
[root@localhost tq2440]# mv smdk2410.c tq2440.c
[root@localhost tq2440]# vi Makefile
修改Makefile
obj-y := smdk2410.o
改为:
obj-y := tq2440.o
保存退出


拷贝配置文件(使用相似的smdk2410开发板的配置文件)
[root@localhost u-boot-2014.04]# cp include/configs/smdk2410.h include/configs/tq2440.h

增加开发板配置选项(编译之前需要配置,如make smdk2410_config 现在需添加支持make tq2440_config)
在顶层目录下的 Makefile 中搜索不到 smdk2410
在顶层目录执行如下命令
[root@localhost u-boot-2014.04]# grep "smdk2410" * -nR
得到的结果为:
 

因此可知smdk2410的配置信息在根目录的boards.cfg文件中定义,所以我们同样仿照sdmk2410来定义我们的tq2440
boards.cfg添加如下信息:

Active     arm     arm920t     s3c24x0     -     tq2440                  tq2440                                   -                                                                                                                                

由于我在board目录下创建开发板目录,所以Vendor指定为空
二、配置时钟
先大致看一下配置文件include/configs/tq2440.h
#define CONFIG_ARM920T        /* This is an ARM920T Core */
#define CONFIG_S3C24X0          /* in a SAMSUNG S3C24x0-type SoC */
#define CONFIG_S3C2410          /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410      /* on a SAMSUNG SMDK2410 Board */
这里是高级别的一些配置,配置了S3C2410SoC和SMDK2410Board,跟我使用的开发板不一致
根据我自己的开发板tq2440进行如下配置
//#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */
//#define CONFIG_SMDK2410 /* on a SAMSUNG SMDK2410 Board */
#define CONFIG_S3C2440
#define CONFIG_AUTO_COMPLETE    /* 开启命令自动补全 */
#define CONFIG_SYS_PROMPT "TQ2440 # "    /* 命令提示符 */
红色的为新加入的 黑色的为原本就有的
    屏蔽一些暂时不用的支持,用的时候再加上
 #if 0
#define CONFIG_CS8900 /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#endif 

 #if 0
#define CONFIG_USB_OHCI
#define CONFIG_USB_OHCI_S3C24XX
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION
#endif 

#define CONFIG_CMD_BSP
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
//#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
//#define CONFIG_CMD_NAND
//#define CONFIG_CMD_PING
//#define CONFIG_CMD_REGINFO
//#define CONFIG_CMD_USB

/*
 * File system
 */
 #if 0
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE
#endif


从连接脚本文件arch/arm/cpu/u-boot.lds我们可以看出u-boot执行的第一个文件是arch/arm/cpu/arm920t/start.S
修改arch/arm/cpu/arm920t/start.S文件
这几行代码为2410的时钟初始化函数
# if defined(CONFIG_S3C2410)
 ldr r1, =0x3ff
 ldr r0, =INTSUBMSK
 str r1, [r0]
# endif

修改如下:
# if defined(CONFIG_S3C2410)
 ldr r1, =0x3ff
 ldr r0, =INTSUBMSK
 str r1, [r0]
# endif
#if defined(CONFIG_S3C2440)
 ldr r1, =0x7fff
 ldr r0, =INTSUBMSK
 str r1, [r0]
#endif
#if defined(CONFIG_S3C2440)
                                                   
# define MPLLCON 0x4C000004
# define UPLLCON 0x4C000008
# define CAMDIVN 0x4C000018
                                                   
  ldr r0, =CAMDIVN
 mov r1, #0
 str r1, [r0]
                                                   
 /* FCLK:HCLK:PCLK = 1:4:8 */
 /* default FCLK is 400 MHz ! */
 ldr r0, =CLKDIVN
 mov r1, #0x05
 str r1, [r0]
                                                   
 mrc p15,0,r0,c1,c0,0
 orr r0,r0,#0xc0000000
 mcr p15,0,r0,c1,c0,0
                                                   
 ldr r0, =UPLLCON
 ldr r1, =0x38022 // USB 48MHZ
 str r1, [r0]
                                                   
 /*
  **When you set MPLL&UPLL values, you have to se
  **value first and then the MPLL value. (Needs i
  **approximately 7 NOP)
  */
 nop
 nop
 nop
 nop
 nop
 nop
 nop
                                                 
 ldr r0, =MPLLCON
 ldr r1, =0x5c011
 str r1, [r0]
#else
 /* FCLK:HCLK:PCLK = 1:2:4 */
 /* default FCLK is 120 MHz ! */
 ldr r0, =CLKDIVN
 mov r1, #3
 str r1, [r0]
#endif     /* CONFIG_S3C2440 */
#endif     /* CONFIG_S3C24X0 */


board/tq2440/tq2440.c    中    board_early_init_f()    函数也初始化了时钟,因为我在start.S中已初始化了时钟,
所以屏蔽掉    board_early_init_f()    中对时钟的初始化代码


可以先配置 u-boot 支持直接烧写进内存 SDRAM 运行
修改配置文件 tq2440.h
#define CONFIG_SYS_TEXT_BASE 0x32000000
CONFIG_SYS_TEXT_BASE    指定了代码的加载地址,待会编译好后生成可执行二进制文件
u—boot.bin,就要把    u-boot.bin    下载到该地址
我们现在需要直接烧写进内存运行,而底层初始化代码还没移植,所以我们需要跳过底层初始化
查看arch/arm/cpu/arm920t/start.S
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
 bl cpu_init_crit
#endif

如果没有定义 CONFIG_SKIP_LOWLEVEL_INIT 就跳转 cpu_init_crit 函数执行,该函数进行了一些底
层的初始化,比如内存。因为下面我们直接将u-boot下载到内存中运行,如果在内存中运行的同时再
初始化内存,那么内存中的数据代码会遭到破坏。
所以我们在配置文件tq2440.h中定义该宏

#define CONFIG_SKIP_LOWLEVEL_INIT
修改一下顶层Makefile:
配置:
[root@localhost u-boot-2014.04]# make tq2440_config
如果配置成功会出现:Configuring for tq2440 board...
编译:
[root@localhost u-boot-2014.04]#make
编译完成生成可执行二进制文件 u—boot.bin ,开发板启动原有好的u-boot
将u-boot.bin下载到SDRAM的 0x32000000 地址,然后跳转到 0x32000000 运行
我这里使用的是tftp下载的方式:
EmbedSky> tftp 32000000 u-boot.bin
EmbedSky> go 32000000

在tq2440.h中定义DEBUG宏
#define    DEBUG
重新编译 并使用刚才的方法下载到SDRAM上
EmbedSky>tftp 32000000 u-boot.bin; go 32000000
输出的信息为:
经过加打印,问题定位在board.c中的board_init_r在调用mem_malloc_init函数时出了问题,他完成的
操作是将malloc_start标识的malloc区域清零,这里malloc区域的大小是4MB+160KB,发现在清除
到2MB多的时候程序就挂了。
这个问题的原因好没有找到,等待解决。目前临时的解决办法是将malloc区域的大小减小为
2MB+160KB,做法是修改tq2440.h中,将
#define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
改为:
#define CONFIG_SYS_MALLOC_LEN (2 * 1024 * 1024)
然后编译运行,打印信息如下:

三、移植NORFLASH
*** failed ***
### ERROR ### Please RESET the board ###
u-boot卡在这里不动了。
搜索    *** failed ***    
[root@localhost u-boot-2014.04]# grep "\*\*\* failed \*\*\*" * -nR 
arch/sparc/lib/board.c:57:static char *failed = "*** failed ***\n"; 
arch/powerpc/lib/board.c:91:static char *failed = "*** failed ***\n"; 
arch/mips/lib/board.c:28:static char *failed = "*** failed ***\n"; 
arch/m68k/lib/board.c:59:static char *failed = "*** failed ***\n"; 
arch/arm/lib/board.c:465:static char *failed = "*** failed ***\n"; 
Binary file arch/arm/lib/built-in.o matches 
Binary file arch/arm/lib/board.o matches 
common/board_f.c:190: puts("*** failed ***\n"); 
common/board_r.c:325: puts("*** failed ***\n"); 
Binary file u-boot matches 
Binary file u-boot.bin matches 
[root@localhost u-boot-2014.04]#

进入arch/arm/lib/board.c文件查看

根据debug("JEDECPROBE:ID%x%x%x\n",
info->manufacturer_id,
info->device_id,
info->device_id2);
可以知道已经探测到开发板的flash的厂家ID为0x1c,设备ID为0x2249
在 jedec_table 表中增加 TQ2440 开发板的 NOR FLASH(EN29LV160AB) 内容
该文件位于 u-boot-2014.04\drivers\mtd\Jedec_flash.c 第166行
static const struct amd_flash_info jedec_table[] 
的末尾添加:
#endif
#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16
    { /* TQ2440 EN29LV160AB */
            .mfr_id = 0x1c, /* manufacturer_id */
            .dev_id = 0x2249, /* device_id */
            .name = "EON EN29LV160AB",
            .uaddr = {/* 因为NOR FLASH的ADDR0接到了S3C2440的ADDR1 */
                [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
            },
            .DevSize = SIZE_2MiB,
            .CmdSet = P_ID_AMD_STD,
            .NumEraseRegions= 4,
            .regions = {
                ERASEINFO(0x04000, 1),
                ERASEINFO(0x02000, 2),
                ERASEINFO(0x08000, 1),
                ERASEINFO(0x10000, 31),
            }
        },
#endif
};
在 tq2440.h 中定义 CONFIG_SYS_FLASH_LEGACY_1024Kx16
注释掉512K的宏
//#define CONFIG_SYS_FLASH_LEGACY_512Kx16
#define CONFIG_SYS_FLASH_LEGACY_1024Kx16

重新编译并下载到 开发板:
测试flash读写是否正常
读取0x32000000地址的0x10字节数据到0x0地址,然后比较两份数据是否相等
注意:从flinfo中可以看出0地址所在扇区是RO,要先解保护
TQ2440 # flinfo
TQ2440 # protect off all    /*打开写保护*/
TQ2440 # erase 0 7ffff    /*先擦除在写入*/
........... done
Erased 11 sectors
TQ2440 # cp.b 32000000 0 10
Copy to Flash... done
TQ2440 # cmp.b 0 32000000 10
Total of 16 byte(s) were the same
再来读:
TQ2440 # md.b 32000000 10
32000000: 0f 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................
TQ2440 # md.b 0 10
00000000: 0f 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................
两次读取的数据一样,说明nor flash读写正常。


三、移植网卡DM900
网卡DM9000的驱动为drivers/net/dm9000x.c,我们需要将它编译进u-boot,查看drivers/net/Makefile
38 COBJS-$(CONFIG_DRIVER_DM9000) +=dm9000x.o
如果定义了CONFIG_DRIVER_DM9000就将dm9000x.o编译进u-boot,在配置文件tq2440.h中定义该
#define CONFIG_DRIVER_DM9000
在第一步已经经网卡CS8900的相关配置注释掉了重新编译出错
在tq2440.h中添加定义
#define CONFIG_DM9000_NO_SROM
(如果不设置这个宏,uboot会打印类似:
Warning:    dm9000    MAC    addresses    don't    match:
Address    in    SROMis     ff:ff:ff:ff:ff:ff
Address    in    environmen    tis     00:0c:29:2a:5c:a5
的信息)
#define    CONFIG_DM9000_BASE     0x20000000 //tq2440开发板的网卡dm9000接在S3C2440的bank4
#define    DM9000_IO     CONFIG_DM9000_BASE
#define    DM9000_DATA (CONFIG_DM9000_BASE+4) //tq2440开发板的网卡dm9000的cmd引脚接在S3C2440的ADDR2
打开之前第一步暂时注释掉的宏
#define    CONFIG_CMD_PING
重新编译下载  看输出信息:



略~~~~~~~~~~~~~~~

九、支持烧写yaffs文件系统
执行:
Nguhyw # ? nand
查看输出信息并没有对yaffs的信息。
在内核里搜索 .yaffs
[root@localhost u-boot-2014.04]# grep "\.yaffs" * -nR
查看common/cmd_nand.c 第 709行。
发现宏 CONFIG_CMD_NAND_YAFFS 未定义,那好,既然你没有定义那我就来定义你不就可以了吗?
在tq244.h里定义这个宏。
然后覆盖到linux的文件上,重新编译,然后下载到开发板上。



设置参数
set ethaddr 00:12:34:56:ab:cd; set ipaddr 192.168.1.119; set serverip 192.168.1.123
或使用uboot来更新自己:
 tftp 30000000 u-boot.bin; nand erase.part u-boot; nand write 30000000 u-boot
Nguhyw # mtdpart default
set 'nand read 30000000 kernel;bootm 30000000'
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3
set machid 16a
mtdpart default
save
tftp 30000000 uImage; nand erase.part kernel; nand write 30000000 kernel
tftp 30000000 fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs 30000000 0x00460000 $filesize
已经挂载上yaffs2文件系统,因为yaffs文件系统是好的,所以是u-boot烧写yaffs文件系统的问题
YAFFS中,文件是以固定大小的数据块进行存储的,块的大小可以是512字节、1024字节或者2048
字节。这种实现依赖于它能够将一个数据块头和每个数据块关联起来。每个文件(包括目录)都有一
个数据块头与之相对应,数据块头中保存了ECC(ErrorCorrectionCode)和文件系统的组织信息,用于
错误检测和坏块处理。
查看代码common/cmd_nand.c
调 用 函 数drivers/mtd/nand/nand_util.c  函数nand_write_skip_bad 第 554行
if (!need_skip && !(flags & WITH_DROP_FFS)){
    rval=nand_write(nand,offset,length,buffer);
这里如果没有坏块而且没有指定WITH_DROP_FFS标志就执行nand_write(nand,offset,length,buffer);
而我们需要执行write_oob(nand,offset,&ops);所以应该加上之前传入的参数
 if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB)

和 WITH_YAFFS_OOB

设置参数
set ethaddr 00:12:34:56:ab:cd; set ipaddr 192.168.1.119; set serverip 192.168.1.123
或使用uboot来更新自己:
tftp 30000000 u-boot.bin; nand erase.part u-boot; nand write 30000000 u-boot
Nguhyw # mtdpart default
set bootcmd 'nand read 30000000 kernel;bootm 30000000'
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3
set machid 16a
save
tftp 30000000 uImage; nand erase.part kernel; nand write 30000000 kernel
tftp 30000000 fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs 30000000 0x00600000 $filesize
至此u-boot成功支持nand falsh的烧写 以及启动


十、 添加 NAND FLASH 硬件 ECC 
在tq2440.h 中定义如下宏定义。
#define CONFIG_S3C2440_NAND_HWECC
#ifdef CONFIG_S3C2440_NAND_HWECC
#define CONFIG_SYS_NAND_ECCSIZE 2048
#define CONFIG_SYS_NAND_ECCBYTES 4
#endif

修改 arch/arm/include/asm/arch-s3c24x0/s3c24x0.h:s3c2440_nand结构体,添加寄存器
 u32 nfstat0;
 u32 nfstat1;
 u32 nfmecc0;
 u32 nfmecc1;
 u32 nfsecc;
 u32 nfsblk;
 u32 nfeblk;

修改 drivers/mtd/nand/s3c2440_nand.c
修改函数s3c2440_nand_enable_hwecc 为:
修改函数s3c2440_nand_calculate_ecc  为:
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
          u_char *ecc_code)
{
 struct s3c2440_nand *nand = s3c2440_get_base_nand();
 writel(readl(&nand->nfcont) |(1<<5),&nand->nfcont);/* 锁定main区ECC*/
 u32 mecc0;
 mecc0 = readl(&nand->nfmecc0);
 ecc_code[0] = mecc0 & 0xff;
 ecc_code[1] = (mecc0 >> 8) & 0xff;
 ecc_code[2] = (mecc0>>16) & 0xff;
 ecc_code[3] = (mecc0>>24) & 0xff;
 debug("s3c2440_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
        mtd , ecc_code[0], ecc_code[1], ecc_code[2],ecc_code[3]);
 return 0;
}
修改s3c2440_nand_correct_data 函数 为:
static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char *dat,
         u_char *read_ecc, u_char *calc_ecc)
{
 struct s3c2440_nand *nand = s3c2440_get_base_nand();
 u32 meccdata0, meccdata1, estat0, err_byte_addr;
 int ret = -1;
 u8 repaired;
 meccdata0 = (read_ecc[1] << 16) | read_ecc[0];
 meccdata1 = (read_ecc[3] << 16) | read_ecc[2];
 writel(meccdata0, &nand->nfeccd0);
 writel(meccdata1, &nand->nfeccd1);
 /*Read ecc status */
 estat0 = readl(&nand->nfstat0);
 switch(estat0 & 0x3) {
 case 0: /* No error */
  ret= 0;
  break;
 case 1:
  /*
  * 1 bit error (Correctable)
  * (nfestat0 >> 7) & 0x7ff :error byte number
  * (nfestat0 >> 4) & 0x7 :error bit number
  */
  err_byte_addr = (estat0 >> 7) & 0x7ff;
  repaired = dat[err_byte_addr] ^ (1 << ((estat0 >> 4) & 0x7));
                                                                                                                     
  printf("s3c2440_nand_correct_data: 1 bit error detected at byte %ld. Correcting from 0x%02x to 0x%02x...OK\n",
    err_byte_addr, dat[err_byte_addr], repaired);
  dat[err_byte_addr] = repaired;
  ret= 0;
  break;
 case 2: /* Multiple error */
 case 3: /* ECC area error */
  printf("s3c2440_nand_correct_data: ECC uncorrectable errordetected. " "Not correctable.\n");
  ret= -1;
  break;
 }
 return ret;
}

在tq2440.h中定义CONFIG_MTD_NAND_VERIFY_WRITE实现把所写的数据再读取一遍,然后与被
写入的数据之间进行比较来判断所写数据的正确性。
#define CONFIG_MTD_NAND_VERIFY_WRITE


设置参数
mtdpart default
set ethaddr 00:12:34:56:ab:cd; set ipaddr 192.168.1.119; set serverip 192.168.1.123
或使用uboot来更新自己:

set bootcmd 'nand read 30000000 kernel;bootm 30000000'
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3
set machid 16a
save
tftp 30000000 u-boot.bin; nand erase.part u-boot; nand write 30000000 u-boot
tftp 30000000 uImage; nand erase.part kernel; nand write 30000000 kernel
tftp 30000000 fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs 30000000 0x00600000 $filesize
u-boot-2014.04移植手册(TQ2440成功).pdf

之前一直出现一个问题那就是添加硬件ecc的时候无法正常 的运行,经过检查之后发现
添加之后次啊不正常,这里配上能用的头文件
tq2440.h


















阅读(1736) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~