uboot移植——使用三星移植好的uboot开始移植
1:选择三星移植好的uboot,首先进行配置
因为我们用的是210的cpu所以选择三星的210开发板的配置:
在开始移植之前我们首先要把不相关的cpu、board、lib目录删除
首先来看board目录下:把不相关的开发板的文件全部删除只保留:board->samsung->common文件夹以及board->samsung->smdkc110文件夹
cpu目录下:只保留s5pc11x文件夹,其他全部删除;
include目录下:asm-开头的文件只保留asm-arm;asm-arm目录下arch-开头的文件只保留s5pc11x;
include/configs目录下:只保留smdkv210single.h文件
lib-开头文件夹保留lib_arm、lib_generic
然后在用sourceinsight生成project
2:在uboot根目录下进行配置make smdkv210single_config,然后make,生成uboot.bin文件。
接下来就是把生成的uboot.bin文件烧录到sd卡中。
打开sd_fusing文件,
make clean
make
sd_fusing文件中有几个关键文件:
./mkbl1 ../u-boot.bin SD-bl1-8k.bin 8192
C110-EVT1-mkbl1:这个文件是用来复制uboot.bin的前8k 复制到这个文件中SD-bl1-8k.bin
sd_fdisk 这个文件是用来对sd卡进行分区的;
然后使用sd_fusing.sh脚本烧录到sd卡中;
bl1_position=1
uboot_position=49 这里的49扇区,要和uboot重定位的时复制的扇区一致;
我们执行这个sd_fusing.sh脚本即可把bl1、uboot.bin烧录到sd卡中。
启动开发板 会发现电源置锁,只有一句SD checksum Error并没有打印出ok
通过这里分析一定是在电源置锁之后,串口初始化之前代码发生了错误;
看下面代码:
在lowlevel_init函数中有一段代码:
PMIC_InitIp有这么一个函数:这个函数的作用是用来管理电源的,因为我们的210开发板没有用到这个功能所以程序卡在这个函数中了,只要把这个函数注释掉即可
/* PS_HOLD pin(GPH0_0) set to high */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
ldr r1, [r0]
orr r1, r1, #0x300
orr r1, r1, #0x1
str r1, [r0]
/* 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 1f /* r0 == r1 then skip sdram init */
/* init PMIC chip */
bl PMIC_InitIp
/* init system clock */
bl system_clock_init
接下来编译执行:
串口输出信息如下:
开始打印U-BOOT的版本号,说明在启动的第一阶段已经没有问题了,下面打印出版本号是在
display_banner 这个函数中
我们要修改for SMDKV210这个信息只需在smdkv210single.h中修改这个定义即可
时钟的信息是正确的,时钟信息是在print_cpuinfo这个函数中打印出来的
这个信息是在checkboard函数中打印的,如果要修改这个信息可以在这个函数中修改;
下面看一下dram的打印信息
dram的配置在smdkv210single.h中进行配置的:
因为我们实际接的是512MB
修改#define SDRAM_BANK_SIZE 0x10000000 /* 256 MB */
#define PHYS_SDRAM_2 0x40000000
复制编译;现在dram 大小可以了并且可用了,可以用md命令来测试;
但是我们的起始内存起始地址为0x3000_0000——0x4FFF_FFFF
所以要修改这些地址;
(1)修改内存初始化时候的内存地址:看下面几句代码在这里是设置内存初始化的相关寄存器的,我们在裸机中讲到过这些寄存器
详细可以看这篇博客http://www.cnblogs.com/biaohc/p/6346949.html
#define DMC0_MEMCONFIG_0 0x20E01323 // MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC0_MEMCONFIG_1 0x40F01323 // MemConfig1
#define DMC0_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC0_TIMING_ROW 0x28233287 // TimingRow for @200MHz
#define DMC0_TIMING_DATA 0x23240304 // TimingData CL=3
#define DMC0_TIMING_PWR 0x09C80232 // TimingPower
#define DMC1_MEMCONTROL 0x00202400 // MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
#define DMC1_MEMCONFIG_0 0x40C01323 // MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC1_MEMCONFIG_1 0x00E01323 // MemConfig1
#define DMC1_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4
#define DMC1_TIMING_ROW 0x28233289 // TimingRow for @200MHz
#define DMC1_TIMING_DATA 0x23240304 // TimingData CL=3
#define DMC1_TIMING_PWR 0x08280232 // TimingPower
(2)MEMORY_BASE_ADDRESS为0x
(3) 因为uboot开启了mmu,虚拟地址物理地址映射的时候把0xc000_0000映射到了0x20000000
所以我们在这里要修改虚拟地址映射
这里的代码把0xc000_0000 到0xd000_0000映射到 0x3000_0000处
(4):之后继续执行出现下图,SD/MMC初始化失败,
打开mmu以后,这里有一个虚拟地址到物理地址的映射的函数,
这里要改成0x30000000
修改以后打印出现,下列错误
查找EXT_CSD,在下面这个函数中,读取版本号如果版本号 > 5的话打印下面信息,我们直接把5修改为8
(5):初始化dm9000网卡
因为我们用的是dm9000网卡芯片,所以在driver目录下的dm9000网卡驱动部分不用修改
只要修改dm9000初始化部分的代码即可:
dm9000初始化的代码在start_armboot最开始初始化的一堆函数数组中的board_init函数中,其中调用的是dm9000_pre_init这个函数
详细内容如下:
具体代码的函数可以看我的这篇博客:http://www.cnblogs.com/biaohc/p/6413547.html
static void dm9000_pre_init(void)
{
unsigned int tmp;
#if defined(DM9000_16BIT_DATA)
SROM_BW_REG &= ~(0xf << 20);
SROM_BW_REG |= (0<<23) | (0<<22) | (0<<21) | (1<<20);
#else
SROM_BW_REG &= ~(0xf << 20);
SROM_BW_REG |= (0<<19) | (0<<18) | (0<<16);
#endif
SROM_BC5_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0));
tmp = MP01CON_REG;
tmp &=~(0xf<<20);
tmp |=(2<<20);
MP01CON_REG = tmp;
}
第一步修改上面代码为:
static void dm9000_pre_init(void)
{
unsigned int tmp;
#if defined(DM9000_16BIT_DATA)
//SROM_BW_REG &= ~(0xf << 20);
//SROM_BW_REG |= (0<<23) | (0<<22) | (0<<21) | (1<<20);
SROM_BW_REG &= ~(0xf << 4);
/*
** 注意下面这里要修改为1111
*/
SROM_BW_REG |= (1<<7) | (1<<6) | (1<<5) | (1<<4);
#else
SROM_BW_REG &= ~(0xf << 20);
SROM_BW_REG |= (0<<19) | (0<<18) | (0<<16);
#endif
//SROM_BC5_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0));
SROM_BC1_REG = ((0<<28)|(1<<24)|(5<<16)|(1<<12)|(4<<8)|(6<<4)|(0<<0));
tmp = MP01CON_REG;
//tmp &=~(0xf<<20);
//tmp |=(2<<20);
tmp &=~(0xf<<4);
tmp |=(2<<4);
MP01CON_REG = tmp;
}
第二步:头文件中的关于dm9000网卡的代码也要做修改
#ifdef CONFIG_DRIVER_DM9000
//#define CONFIG_DM9000_BASE (0xA8000000)
#define CONFIG_DM9000_BASE (0x88000300)
#define DM9000_IO (CONFIG_DM9000_BASE)
#if defined(DM9000_16BIT_DATA)
//#define DM9000_DATA (CONFIG_DM9000_BASE+2)
#define DM9000_DATA (CONFIG_DM9000_BASE+4)
#else
#define DM9000_DATA (CONFIG_DM9000_BASE+1)
#endif
#endif
具体为什么这么修改可以看上面那篇博客;
------------------------------------------------------------------------------------------
未完待续。。。