u-boot2041.01移植

/*
 * 作者:韦访   rookie_wei
 * 说明:本文以JZ2440开发板为例,CUP为S3C2440,烧写工具为JLINK,基于Ubuntu
 *       u-boot版本为u-boot2014.01
 *
 *注:本文参考的是韦东山毕业班课程
 *
 *日期:2014.7.21
 *
 */
 
 第一步----分析启动过程
 启动从arch\arm\cpu\arm920t\start.S开始


1.跳转到start_code处
2.将CPU设置为SVC32模式
3.关看门狗
4.屏蔽所有IRQ
5.向INTSUBMSK子中断屏蔽寄存器写入0x3ff
6.设置分频系数,即FCLK:HCLK:PCLK
7.调用cpu_init_crit
a.激活v4 I/D caches
b.关闭MMU stuff和caches
//重定位代码前,需要启动RAM timing
 c.调用lowlevel_init,设置内存控制器bank0--bank7   (在lowlevel_init.S )
8. bl _main  //通过搜索_mian,发现在文件(arch/arm/lib/crt0.S)有ENTRY(_main)根据注释,判断就是跳转到这里,
9. Set up initial C runtime environment and call board_init_f(0).
10. bl board_init_f 
 init_sequence   //主要进行下列初始化工作,很重要
  arch_cpu_init
  mark_bootstage
  board_early_init_f   //配置MPLL,UPLL, 设置IO端口  
  timer_init    
  env_init   //环境初始化
  init_baudrate   //波特率初始化
  serial_init     //串口初始化
  console_init_f  //控制台初始化
  display_banner
  print_cpuinfo   //显示CPU信息
  dram_init       //配置有效的RAM banks
 
 
 
 
 第二步-----新建单板
  tar -xjf u-boot-2014.01.tar.bz2    //解压
  cd board/samsung/                  //到三星单板目录
  cp smdk2410/ smdk2440 -rf //拷贝smdk2410为smdk2440
  cd smdk2440/  
  mv smdk2410.c smdk2440.c //将smdk2410.c改为smdk2440.c 
  vim Makefile //打开当前目录下的Makefile文件
   obj-y   := smdk2410.o
改为 obj-y   := smdk2440.o
cd ../../../include/configs/
cp smdk2410.h smdk2440.h
vim boards.cfg //打开u-boot-2014.01下的boards.cfg 
复制Active  arm         arm920t        s3c24x0     samsung         -                   smdk2410  
  将2410改为2440,这样就可以执行make smdk2440_config 配置2440开发板了
 
 
vim Makefile  //打开u-boot-2014.01下的Makefile
//主要是将编译器改为arm-linux-gcc,否则编译出错
找到 ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif
改为   ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=arm-linux-   //注意此处-后面不能有空格
endif

 第三步----编译运行
 3.1执行make smdk2440_config
  make
  生成文件u-boot.bin即可执行代码,将其烧写到开发板
 
 3.2启动开发板,串口没有任何信息,说明不能用
 
 第四步----修改代码
 4.1 arch\arm\cpu\arm920t\start.S
  将/* FCLK:HCLK:PCLK = 1:2:4 */
  /* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
改为:
/* FCLK:HCLK:PCLK = 1:4:8 */
/* default FCLK is 400MHz ! */
ldr r0, =CLKDIVN
mov r1, #5
str r1, [r0]
mrc p15, 0, r1, c1, c0, 0  
orr r1, r1, #0xc0000000  
   mcr p15, 0, r1, c1, c0, 0
编译、烧写到开发板,发现串口有输出,但是乱码

4.2 由于是串口出现的问题,所以,找到串口初始化函数serial_init
get_current
default_serial_console()
s3c24xx_serial0_device
宏DECLARE_S3C_SERIAL_FUNCTIONS
serial_init_dev
_serial_setbrg
get_PCLK
get_HCLK
由上追踪发现,如果定义了CONFIG_S3C2440则HCLK按2440,否则为2410,所以要在smdk2440.h
里定义CONFIG_S3C2440且去掉CONFIG_S3C2410。

4.3 执行make,出错,根据错误信息分析
提示的错误是在s3c2410_nand.c,与nand flash有关,但是目前最紧迫的问题是串口问题,所以
应该屏蔽掉nand Flash的操作,将smdk2440.h的#define CONFIG_CMD_NAND注释掉,执行make。
仍然出错,提示错误文件为yaffs_uboot_glue.c,与yaffs文件系统有关,照样屏蔽,#define CONFIG_YAFFS2。
执行make编译通过,烧写到开发板,串口问题解决,OK。
4.4 发现打印出的时钟有点偏差,如下
CPUID: 32440001
FCLK:  405.600 MHz
HCLK:  101.400 MHz
PCLK:   50.700 MHz
DRAM:  64 MiB、
肯定是时钟设置不对,找到时钟设置MPLL在smdk2440.c文件里
/* configure MPLL */
writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,&clk_power->mpllcon);
根据芯片手册和开发板原理图知,开发板晶振为12M,所以想要主频为400M,则需要将
MDIV 设为0x5c   PDIV为ox01  SDIV为0x01
所以,改为
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0x5c
#define M_PDIV 0x01
#define M_SDIV 0x01

执行make,烧写到开发板,正确显示如下
CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB

4.5 发现打印有提示
WARNING: Caches not enabled
搜索Caches not enabled,发现在arch\arm\lib\Cache.c,enable_caches(void)函数
并没有实现功能,所以要实现enable_caches(void)函数,在arch\arm\lib\board.c加上,如下
void enable_caches()
{
__asm__(

"mrc p15, 0, r0, c1, c0, 0\n"
"orr r0, r0, #(1<<12)\n"
"mcr p15, 0, r0, c1, c0, 0\n"
);
}
编译烧写运行,成功去掉提示信息。

4.6 发现打印信息有提示:
Flash: *** failed ***
搜索Flash: ,发现在common\Board_r.c里,代码分析:
initr_flash
flash_init
flash_detect_legacy
flash_read_jedec_ids(info);
   debug("JEDEC PROBE: ID %x %x %x\n",
info->manufacturer_id,
info->device_id,
info->device_id2);
可以看出,有能打印出设备ID的调试信息,但是得在smdk2440.h加上#define DEBUG

 编译烧写到开发板
打印出信息:
Flash: fwc addr 00000000 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 00000000 cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID c2 2249 0
fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
fwc addr 00000000 cmd 90 0090 16bit x 16 bit
fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
JEDEC PROBE: ID 13 ea00 0
*** failed ***
开发板所用的norflash 是AM29LV160DB,根据芯片手册发现,该设备ID为2249
所以上面打印的信息是正确的,但是却还报错,继续分析代码。
上面信息打印正确,那么错误的应该是在它后面,进入函数
jedec_flash_match
jedec_table
jedec_table在文件drivers\mtd\jedec_flash.c
jedec_table里面罗列的一些FLASH的信息,
在smdk2440.c的board_flash_get_legacy函数提示默认的芯片是AM29LV800BB,
与本开发板不符。
仿照jedec_table别的设备,添加如下:
#ifdef CONFIG_SYS_FLASH_LEGACY_2Mx16
{
.mfr_id = (u16)MX_MANUFACT,
.dev_id = AM29LV160DB,
.name = "AMD AM29LV160DB",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = CFI_CMDSET_AMD_LEGACY,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(16 * 1024, 1),
ERASEINFO(8  * 1024, 2),
ERASEINFO(32 * 1024, 1),
ERASEINFO(64 * 1024, 31),
}
}
#endif
并在smdk2440.h中将CONFIG_SYS_FLASH_LEGACY_512Kx16
替换为CONFIG_SYS_FLASH_LEGACY_2Mx16
去掉#define DEBUG

编译烧写运行,打印出:
CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
Flash: 2 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0
SMDK2410 # 
说明已经识别出norflash并且能进入SMDK2410 #,但是有提示Flash: ERROR: too many flash sectors
搜索too many flash sectors
找到原因是宏CONFIG_SYS_MAX_FLASH_SECT定位19,但是我们的扇区却为35,将其改为任意大于35的即可
#define CONFIG_SYS_MAX_FLASH_SECT (50)
编译运行,问题解决


4.7 由于u-boot主要是启动内核,上述操作虽然能启动了u-boot,但还远远不够,首要任务是驱动nand flash
  以存放内核和文件系统等数据
  还记得上面已经把nand flash屏蔽了吧,现在把它打开,在smdk2440.h里将#define CONFIG_CMD_NAND解注。
 
  编译,出错,根据提示知道是drivers/mtd/nand/s3c2410_nand.c文件出错,为了不破坏s3c2410_nand.c源码,将其复制为s3c2440_nand.c,
  并在其目录下的Makefile添加obj-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o。
  将smdk2440.h里的CONFIG_NAND_S3C2410改为CONFIG_NAND_S3C2440。
  将s3c2440_nand.c所有2410改为2440。
  将
#define S3C2440_NFCONF_TACLS(x)    ((x)<<8)
#define S3C2440_NFCONF_TWRPH0(x)   ((x)<<4)
#define S3C2440_NFCONF_TWRPH1(x)   ((x)<<0)
 改为(请参考s3c2440手册nand flash控制器篇)
 #define S3C2440_NFCONF_TACLS(x)    ((x)<<12)
#define S3C2440_NFCONF_TWRPH0(x)   ((x)<<8)
#define S3C2440_NFCONF_TWRPH1(x)   ((x)<<4)
 并将cfg = S3C2440_NFCONF_EN;注释 
 
 由于2410和2440 nand flash控制器的区别,2440不仅要操作nfconf,还有操作nfcont,
 所以在
//cfg = S3C2440_NFCONF_EN;
cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
writel(cfg, &nand_reg->nfconf);
后加上nfcont寄存器的操作,
//使能nand flash控制器,Initialize ECC decoder/encoder
writel((1<<4)|(1<<0),&nand_reg->nfcont); 


 
 nand 启动分析:
  nand_init
  nand_init_chip
  board_nand_init   //单板nand初始化,非常重要
  nand_scan
  nand_scan_ident
  nand_set_defaults   //提供nand_chip结构体基本的nand操作函数
  nand_get_flash_type
  select_chip(mtd, 0);  //片选芯片,第二个参数很重要,记住,选中是0
  chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); //读设备ID
  .....
 
 
在s3c2440_nand.c文件发现代码nand->select_chip = NULL,如此重要的片选操作居然没有对应函数实现。
在s3c2440_nand.c添加以下函数,并且将
nand->select_chip = NULL
改为
nand->select_chip = s3c2440_nand_select_chip;

static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();

switch(chip)
{
case -1:    //disable chip select
writel(readl(&nand->nfcont) | ((1<<1)), &nand->nfcont);
break;
case 0:    //enable chip select
writel(readl(&nand->nfcont) & (~(1<<1)), &nand->nfcont);
break;
default:
debug("chip select error!\n");
}

}

将函数s3c2440_hwcontrol改为如下,因为2410和2440的nand flash控制器不同。
该函数用于选择是命令操作还是地址操作。

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();

debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

if (ctrl & NAND_CLE)
{
writeb(cmd, &nand->nfcmd);  //前8位有效,所以用writeb写入足以
}
else if (ctrl & NAND_ALE)
{
writeb(cmd, &nand->nfaddr);
}
}

编译运行,能识别nand flash:
CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
Flash: 2 MiB
NAND:  256 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0
SMDK2410 # 

OK,继续修改

4.8 修改网卡
由输出信息知,u-boot默认的网卡是CS8900,但是我们的开发板用的是DM9000网卡,所以并不能使用。
网络相关的在目录drivers/net下,打开其目录下的Makefile,发现DM9000与宏CONFIG_DRIVER_DM9000有关。
CS8900和CONFIG_CS8900有关
在smdk2440.h里将CONFIG_CS8900有关的注释掉,添加CONFIG_DRIVER_DM9000
编译
发现错误如下
dm9000x.c:148: error: 'DM9000_DATA' undeclared (first use in this function)

搜索DM9000_DATA,仿照mini2440.h里的DM9000,向smdk2440.h添加
#define CONFIG_DRIVER_DM9000
#define CONFIG_DRIVER_DM9000_NO_EEPROM
#define CONFIG_DM9000_BASE 0x20000300
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4)

编译运行,发现如下错误
Net:   No ethernet found.
搜索Net:
在文件arch/arm/lib/board.c里发现
eth_initialize
board_eth_init
cs8900_initialize
发现默认的还是cs8900,
试着把cs8900_initialize改成dm9000_initialize,发现有此函数,搜索dm9000_initialize,
仿照别的代码
添加
#ifdef CONFIG_DRIVER_DM9000
rc = dm9000_initialize(bis);
#endif

编译运行,成功识别dm9000

In:    serial
Out:   serial
Err:   serial
Net:   dm9000

在串口运行print,可以看到
ethact=dm9000
ipaddr=10.0.0.110
netmask=255.255.255.0
serverip=10.0.0.1
stderr=serial
stdin=serial
stdout=serial

搜索ipaddr=,进入宏CONFIG_IPADDR
发现可以修改IP和网关等信息,可以根据需要修改,也可以不改,
添加#define CONFIG_ETHADDR 00:0c:29:78:c8:73 设置MAC地址
试一下能ping通电脑



4.9 修改默认参数
由打印提示信息*** Warning - bad CRC, using default environment,
我们搜索using default environment
在文件common\Env_common.c找到相关语句

在Env_common.c 里发现default_environment数组,这个数值很重要。
在smdk2440.h里添加
#define CONFIG_BOOTARGS "console=ttySAC0,115200 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND "nand read 30000000 0xa0000 0x400000; bootm 30000000"
注:0xa0000是nand flash里的内核分区首地址,0x400000是内核分区的大小

倒推出环境变量的保存地址,在u-boot串口输入 ? save 找到命令saveenv,在源码搜索saveenv。
在common/env_nand.c里有,vi common/Makefile发现    obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o,
所以要定义CONFIG_ENV_IS_IN_NAND。进入env_nand.c发现CONFIG_ENV_OFFSET,即环境偏移地址,需要定义。
还发现CONFIG_ENV_SIZE,也要定义,还发现CONFIG_ENV_RANGE,也要设置。
先去掉//#define CONFIG_ENV_IS_IN_FLASH以免与CONFIG_ENV_IS_IN_NAND冲突
所以要在smdk2440.h里添加:
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x00080000   //根据分区定义值得到
#define CONFIG_ENV_SIZE   0x20000
#define CONFIG_ENV_RANGE  CONFIG_ENV_SIZE


4.10 定义分区
在u-boot输入 "?"
找到命令mtdparts,即分区的命令
搜索源码  find -name *mtdparts*
发现/common/cmd_mtdparts.c
打开其文件夹下的Makefile
发现obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o
所以要在smdk2440.h里添加
#define CONFIG_CMD_MTDPARTS
随便搜索一下源码
grep "define CONFIG_CMD_MTDPARTS" -Rn
随便找一个文件(也不是那么随意,注意是nand flash,别的有可能是nor flash)。参考其写如下代码添加到smdk2440.h
 
 #define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_PARTITIONS
#define MTDIDS_DEFAULT "nand0=rookie_wei-nand"
#define MTDPARTS_DEFAULT \
   "mtdparts=rookie_wei-nand:" \
  "512k(bootloader)," \
  "128k(params)," \
 "4m(kernel)," \
  "-(root)"
 
再在board.c里的board_init_r加上
    run_command("mtdparts default",1);
    这样启动就会自动分区了,不需要每次都输入.


4.11、支持yaffs文件系统
还记得4.3步的时候我们把 #define CONFIG_YAFFS2注释掉了吗?
解注,编译,运行
在u-boot命令行输入nand ?
居然没有发现nand write.yaffs
搜索nand write
在cmd_nand.c文件发现,原来没有定义头文件CONFIG_CMD_NAND_YAFFS
在smdk2440.h添加:
#define CONFIG_CMD_NAND_YAFFS
再编译运行查看,有
nand write.yaffs - addr off|partition size
   write 'size' bytes starting at offset 'off' with yaffs format
   from memory address 'addr', skipping bad blocks.
烧写文件系统,启动,没有成功
 
搜索函数nand_write_skip_bad,#ifdef CONFIG_CMD_NAND_YAFFS下面,将ops.mode = MTD_OPS_AUTO_OOB;,改为ops.mode = MTD_OPS_RAW;。
将 if (!rval)
break;
改为
if (rval)
break;
 
4.12、支持启动yaffs
将\drivers\mtd\nand\Nand_util.c的nand_write_skip_bad函数的
if (!need_skip && !(flags & WITH_DROP_FFS)) 改为
if (!need_skip && !(flags & WITH_DROP_FFS)&&!(flags & WITH_YAFFS_OOB))



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值