ok6410 u-boot-2012.04.01移植二修改源码支持单板

2024-05-09 04:48

本文主要是介绍ok6410 u-boot-2012.04.01移植二修改源码支持单板,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

继ok6410 u-boot-2012.04.01移植一后修改代码,对ok6410单板初始化,主要包括时钟、串口、NAND、DDR等初始化。这些工作在以前的裸板程序都写了,直接拿来用。我觉得先写裸板程序对移植u-boot还是很有帮助的,以前写的裸板代码不管是在u-boot移植还是后面的驱动开发,都用得着。

开发环境:
系统:ubuntu 10.04.4
单板:ok6410
NAND FLASH:K9GAG08U0D 2048MB
DDR:K4X1G163PCX2 256MB
NET:DM9000AEP
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境配置。
目标:
1.板级初始化,支持单板ok6410
2.增加菜单update功能
3.修改u-boot,支持NAND启动
4.增加MLC NAND支持
5.支持DM9000,网卡下载程序
6.修改环境变量以及mtdpart分区
7.u-boot裁剪及制作补丁

一、修改时钟配置

查看代码,从start.S开始,发现时钟、内存、NAND等都在bl lowlevel_init完成,进入board\samsung\smdk6410\lowlevel_init.S:修改95: bl system_clock_init,将时钟初始化换成如下代码(以前写的裸板代码):

board\samsung\smdk6410\lowlevel_init.S 151:system_clock_init:

system_clock_init:
//ldr	r0, =ELFIN_CLOCK_POWER_BASE	/* 0x7e00f000 */
/* 1.设置LOCK_TIME */
ldr r0, =0x7E00F000  /* APLL_LOCK */
ldr r1, =0x0000FFFF
str r1, [r0]
str r1, [r0, #4]	 /* MPLL_LOCK */
str r1, [r0, #8]	 /* EPLL_LOCK */	
#define OTHERS		0x7e00f900
@ set async mode  /* 当CPU时钟 != HCLK时,要设为异瞈u0153模蔦u0153 */
ldr r0, =OTHERS
ldr r1, [r0]
bic r1, r1, #0xc0	/* 1100,0000 */		
str r1, [r0]
loop1:				/* 等\u017d钡\u0153CPU\u0153胍觳\u0153模蔦u0153 */
ldr r0, =OTHERS
ldr r1, [r0]
and r1, r1, #0xf00					
cmp r1, #0
bne loop1			
/* SYNC667 */
/* MISC_CON[19] = 0 */
#define ARM_RATIO    0   /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1)    */
#define HCLKX2_RATIO 1   /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
#define HCLK_RATIO   1   /* HCLK = HCLKX2 / (HCLK_RATIO + 1)       */
#define PCLK_RATIO   3   /* PCLK   = HCLKX2 / (PCLK_RATIO + 1)     */
#define MPLL_RATIO   0   /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1)     */
ldr r0, =0x7E00F020  /* CLK_DIV0 */
ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)
str r1, [r0]
/* 2.配置时钟 */
/* 2.1 配置APLL */
/* 2.1.1 设置APLL
* 2.1.2 MUXAPLL
* 2.1.3 SYNC667
* 2.1.4 DIVAPLL
*/
#define APLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
ldr r0, =0x7E00F00C
ldr r1, =APLL_CON_VAL
str r1, [r0]		/* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  */
/* 2.2 配置MPLL */
/* 2.2.1 设置MPLL
* 2.2.2 MUXMPLL
* 2.2.3 SYNCMUX
* 2.2.4 SYNC667
* 2.2.5 HCLKX2_RATIO
* 2.2.6 PCLK_RATIO
*/
#define MPLL_CON_VAL  ((1<<31) | (266 << 16) | (3 << 8) | (1))
ldr r0, =0x7E00F010
ldr r1, =MPLL_CON_VAL
str r1, [r0]		/* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz  */
/* 3.选择PLL的输出作为时钟診u017d */
ldr r0, =0x7E00F01C
ldr r1, =0x03
str r1, [r0]
mov pc, lr
二、修改串口初始化

board\samsung\smdk6410\lowlevel_init.S 226:uart_asm_init:换成如下代码

uart_asm_init:
/* set GPIO to enable UART */
ldr	r0, =ELFIN_GPIO_BASE
ldr	r1, =0x220022
str	r1, [r0, #GPACON_OFFSET]
ldr   r0, =0x7F005000/*ULCON0 = 0x3;*/
ldr   r1, =0x3
str   r1, [r0]
ldr   r0, =0x7F005004/*UCON0  = 0x5;*/
ldr   r1, =0x5
str   r1, [r0]  
ldr   r0, =0x7F005008/*UFCON0 = 0x07; FIFO enable */
ldr   r1, =0x07
str   r1, [r0]
ldr   r0, =0x7F00500C/*UMCON0 = 0;*/
ldr   r1, =0x00
str   r1, [r0]
ldr   r0, =0x7F005028/*UBRDIV0   = 35;*/
ldr   r1, =0x23
str   r1, [r0]
ldr   r0, =0x7F00502C/*UDIVSLOT0 = 0x1;*/
ldr   r1, =0x01
str   r1, [r0]
mov	pc, lr
三、修改NAND、DDR初始化代码

把board\samsung\smdk6410\lowlevel_init.S关于NAND、DDR初始化部分代码去掉,我们换成C语言代码在start.S实现

104: //bl nand_asm_init
107: /* Memory subsystem address 0x7e00f120 */
//ldr r0, =ELFIN_MEM_SYS_CFG
/* Xm0CSn2 = NFCON CS0, Xm0CSn3 = NFCON CS1 */
//mov r1, #S3C64XX_MEM_SYS_CFG_NAND
//str r1, [r0]
//bl mem_ctrl_asm_init
/* Wakeup support. Don't know if it's going to be used, untested. */
// ldr r0, =(ELFIN_CLOCK_POWER_BASE + RST_STAT_OFFSET)/*RST_STAT*/
/* ldr r1, [r0]
bic r1, r1, #0xfffffff7
cmp r1, #0x8
beq wakeup_reset
1:
mov lr, r12
mov pc, lr
wakeup_reset:
*/
/* Clear wakeup status register */
// ldr r0, =(ELFIN_CLOCK_POWER_BASE + WAKEUP_STAT_OFFSET)/*WAKEUP_STAT*/
// ldr r1, [r0]
// str r1, [r0]
/* LED test */
// ldr r0, =ELFIN_GPIO_BASE
// ldr r1, =0x9
// str r1, [r0, #GPMDAT_OFFSET]
/* Load return address and jump to kernel */
// ldr r0, =(ELFIN_CLOCK_POWER_BASE + INF_REG0_OFFSET)/*INFORM0*/
/* r1 = physical address of s3c6400_cpu_resume function */
// ldr r1, [r0]
/* Jump to kernel (sleep-s3c6400.S) */
// mov pc, r1
mov lr, r12
mov pc, lr
nop
nop
接着在arch\arm\cpu\arm1176\start.S中增加对NAND、DDR等支持

在225:bl lowlevel_init后增加如下代码

ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)/*sp=0x0c00if80 ISRAM*/
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

bl    ddr_init_ll
bl    nand_init_ll
bl dm9000aep_init
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/*from ISRAM jump to SDRAM*/

上面函数的实现,直接拷贝以前的update裸板代码。直接在board\samsung\smdk6410增加sdram.c、init.c两个文件。代码如下

文件sdram.c:

//#include <common.h>
#define MEMCCMD	0x7e001004
#define P1REFRESH	0x7e001010
#define P1CASLAT	0x7e001014
#define MEM_SYS_CFG	0x7e00f120
#define P1MEMCFG	0x7e00100c
#define P1T_DQSS	0x7e001018
#define P1T_MRD		0x7e00101c
#define P1T_RAS		0x7e001020
#define P1T_RC		0x7e001024
#define P1T_RCD		0x7e001028
#define P1T_RFC		0x7e00102c
#define P1T_RP		0x7e001030
#define P1T_RRD		0x7e001034
#define P1T_WR		0x7e001038
#define P1T_WTR		0x7e00103c
#define P1T_XP		0x7e001040
#define P1T_XSR		0x7e001044
#define P1T_ESR		0x7e001048
#define P1MEMCFG2	0X7e00104c
#define P1_chip_0_cfg	0x7e001200
#define P1MEMSTAT	0x7e001000
#define P1MEMCCMD	0x7e001004
#define P1DIRECTCMD	0x7e001008
	
#define HCLK	133000000
#define nstoclk(ns)	(ns/( 1000000000/HCLK)+1)
#define vi *( volatile unsigned int * ) 
#define set_zero( addr, bit ) ( (vi addr) &= ( ~ ( 1 << (bit) ) ) )
#define set_one( addr, bit ) ( (vi addr) |= ( 1 << ( bit ) ) )
#define set_bit( addr, bit, val ) ( (vi addr) = (( vi addr)&=(~(1<<(bit))) ) | ( (val)<<(bit) ) )
#define set_2bit( addr, bit, val ) ( (vi addr) = (( vi addr)&(~(3<<(bit))) ) | ( (val)<<(bit) ) )
#define set_nbit( addr, bit, len,  val ) \
( (vi addr) = ((( vi addr)&(~(( ((1<<(len))-1) )<<(bit))))  | ( (val)<<(bit) ) ))
#define get_bit( addr, bit ) ( (( vi addr ) & ( 1 << (bit) )) > 0  )
#define get_val( addr, val ) ( (val) = vi addr )
#define read_val( addr ) ( vi ( addr ) )
#define set_val( addr, val ) ( (vi addr) = (val) )
#define or_val( addr, val ) ( (vi addr) |= (val) )
void ddr_init_ll( void )
{
	// tell dramc to configure				
	set_val( MEMCCMD, 0x4 );
	// set refresh period	
	set_val( P1REFRESH, nstoclk(7800) );
	// set timing para		
	set_val( P1CASLAT, ( 3 << 1 ) );  
	set_val( P1T_DQSS, 0x1 );	// 0.75 - 1.25
	set_val( P1T_MRD, 0x2 );
	set_val( P1T_RAS, nstoclk(45) );
	set_val( P1T_RC, nstoclk(68) );		
	unsigned int trcd = nstoclk( 23 );
	set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
	unsigned int trfc = nstoclk( 80 );
	set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );   
	unsigned int trp = nstoclk( 23 );
	set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) ); 
	set_val( P1T_RRD, nstoclk(15) );
	set_val( P1T_WR, nstoclk(15) );
	set_val( P1T_WTR, 0x7 );
	set_val( P1T_XP, 0x2 );
	set_val( P1T_XSR, nstoclk(120) );
	set_val( P1T_ESR, nstoclk(120) );
	
	// set mem cfg 
	set_nbit( P1MEMCFG, 0, 3, 0x2 );  /* 10 column address */
	/* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */
	
	set_nbit( P1MEMCFG, 3, 3, 0x2 );  /* 13 row address */
	set_zero( P1MEMCFG, 6 );		  /* A10/AP */
	set_nbit( P1MEMCFG, 15, 3, 0x2 ); /* Burst 4 */
	
	set_nbit( P1MEMCFG2, 0, 4, 0x5 );
	set_2bit( P1MEMCFG2, 6, 0x1 );		/* 32 bit */
	set_nbit( P1MEMCFG2, 8, 3, 0x3 );	/* Mobile DDR SDRAM */
	set_2bit( P1MEMCFG2, 11, 0x1 );
	set_one( P1_chip_0_cfg, 16 );		/* Bank-Row-Column organization */
	// memory init
	set_val( P1DIRECTCMD, 0xc0000 ); // NOP
	set_val( P1DIRECTCMD, 0x000 );	// precharge
	set_val( P1DIRECTCMD, 0x40000 );// auto refresh
	set_val( P1DIRECTCMD, 0x40000 );// auto refresh
	set_val( P1DIRECTCMD, 0xa0000 ); // EMRS
	set_val( P1DIRECTCMD, 0x80032 ); // MRS
	set_val( MEM_SYS_CFG, 0x0 );
					
	// set dramc to "go" status	
	set_val( P1MEMCCMD, 0x000 );
	// wait ready
	while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));
}
文件init.c:

#define MEM_SYS_CFG     (*((volatile unsigned long *)0x7E00F120))
#define NFCONF          (*((volatile unsigned long *)0x70200000))
#define NFCONT          (*((volatile unsigned long *)0x70200004))
#define NFCMMD          (*((volatile unsigned long *)0x70200008))
#define NFADDR          (*((volatile unsigned long *)0x7020000C))
#define NFDATA          (*((volatile unsigned char *)0x70200010))
#define NFSTAT          (*((volatile unsigned long *)0x70200028))
void nand_read_ll(unsigned int nand_start, unsigned int ddr_start, unsigned int len);
int isBootFromNorFlash(void)
{
volatile int *p = (volatile int *)0;
int val;
val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/*鍐欐垚鍔燂紝鏄痭and鍚姩*/
*p = val;
return 0;
}
else
{
/*Nor涓嶈兘鍍忓唴瀛樹竴鏍峰啓*/
return 1;
}
}
void copy_code_to_sdram(unsigned int src, unsigned int dest, unsigned int len)
{
int i = 0;
/*濡傛灉鏄疦or鍚姩*/
unsigned char *src_start = (unsigned char *)src;
unsigned char *dest_start = (unsigned char *)dest;
if(isBootFromNorFlash())
{
while (i < len)
{
dest_start[i] = src_start[i];
i++;
}
}
else
{
//nand_init();                                                                                
//nand_resd(src, dest, len)                                                                   
nand_read_ll(src, dest, len);
}
}
static void nand_select(void)
{
NFCONT &= ~(1<<1);
}
static void nand_deselect(void)
{
NFCONT |= (1<<1);
}
static void nand_cmd(unsigned char cmd)
{
NFCMMD = cmd;
}
static void nand_addr(unsigned char addr)
{
NFADDR = addr;
}
static unsigned char nand_get_data(void)
{
return NFDATA;
}
static void nand_send_data(unsigned char data)
{
NFDATA = data;
}
static void wait_ready(void)
{
while ((NFSTAT & 0x1) == 0);
}
static void nand_reset(void)
{
/* 閫変腑 */
nand_select();
/* 鍙戝嚭0xff鍛戒护 */
nand_cmd(0xff);
/* 绛夊緟灏辩华 */
wait_ready();
/* 鍙栨秷閫変腑 */
nand_deselect();
}
void clear_bss(void)
{
extern int __bss_start, __bss_end__;
int *p = &__bss_start;
for (; p < &__bss_end__; p++)
*p = 0;
}
void nand_init_ll(void)
{
/* 璁﹛m0csn2鐢ㄤ綔nand flash cs0 鐗囬€夊紩鑴?*/
MEM_SYS_CFG &= ~(1<<1);
/* 璁剧疆鏃堕棿鍙傛暟 */
#define TACLS     0
#define TWRPH0    2
#define TWRPH1    1
NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));
NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));
/* 浣胯兘nand flash controller */
NFCONT |= 1;
NFCONT &= ~(1<<16); /* 妫soft lock */
nand_reset();
}
static void nand_send_addr(unsigned int addr)
{
#if 1
unsigned int page   = addr / 4096;
unsigned int colunm = addr & (4096 - 1);
/* 杩欎袱涓湴鍧€琛ㄧず浠庨〉鍐呭摢閲屽紑濮?*/
nand_addr(colunm & 0xff);
nand_addr((colunm >> 8) & 0xff);
/* 涓嬮潰涓変釜鍦板潃琛ㄧず鍝竴椤?*/
nand_addr(page & 0xff);
nand_addr((page >> 8) & 0xff);
nand_addr((page >> 16) & 0xff);
#else
nand_addr(addr & 0xff);         /* a0~a7 */
nand_addr((addr >> 8) & 0x1f);   /* 绋嬪簭鐨勮搴? a8~a12 */
nand_addr((addr >> 13) & 0xff); /* 绋嬪簭鐨勮搴? a13~a20 */
nand_addr((addr >> 21) & 0xff); /* 绋嬪簭鐨勮搴? a21~a28 */
nand_addr((addr >> 29) & 0x7); /* 绋嬪簭鐨勮搴? a29   ~ */
#endif
}
void nand_read_ll(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
unsigned int addr = nand_start;
int i = nand_start % 4096;
int left = i;
int count = 0;
unsigned char *dest = (unsigned char *)ddr_start;
unsigned char data = 0;
/* 閫変腑鑺墖 */
nand_select();
while (count < len)
{
/* 鍙戝嚭鍛戒护0x00 */
nand_cmd(0x00);
/* 鍙戝嚭鍦板潃 */
nand_send_addr(addr);
/* 鍙戝嚭鍛戒护0x30 */
nand_cmd(0x30);
/* 绛夊緟灏辩华 */
wait_ready();
/* 璇绘暟鎹?*/
for (; i < (4096-left) && count < len; i++)//浠庢煇椤电殑i澶勫紑濮嬭
{
data = nand_get_data();
if(addr<16384)//鍓?椤垫瘡娆″彧鑳藉啓2K
{
if(i<(2048-left))
{
dest[count++] = data;
}
}
else
{
dest[count++] = data;
}
//dest[count++] = nand_get_data();
addr++;
}
i = 0;
left = i;
}
/* 鍙栨秷鐗囬€?*/
nand_deselect();
// return 0;
}
void nand_erase_block_ll(unsigned long addr)
{
int page = addr / 4096;
nand_select();
nand_cmd(0x60);
nand_addr(page & 0xff);
nand_addr((page >> 8) & 0xff);
nand_addr((page >> 16) & 0xff);
nand_cmd(0xd0);
wait_ready();
nand_deselect();
}
void nand_write_ll(unsigned int nand_start, unsigned char * buf, unsigned int len)
{
unsigned long count = 0;
unsigned long addr  = nand_start;
int i = nand_start % 4096;
int left = i;
nand_select();
while (count < len)
{
nand_cmd(0x80);
nand_send_addr(addr);
for (; i < (4096-left) && count < len; i++)
{
if(addr<16384)//鍐欏墠2K
{
if(i<(2048-left))//鍓?椤垫瘡椤靛彧鑳藉啓2K
{
nand_send_data(buf[count++]);
}
}
else
{
nand_send_data(buf[count++]);
}
//nand_send_data(buf[count++]);
addr++;
}
nand_cmd(0x10);
wait_ready();
i = 0;
left = i;
}
nand_deselect();
}
#define ULCON0     (*((volatile unsigned long *)0x7F005000))
#define UCON0      (*((volatile unsigned long *)0x7F005004))
#define UFCON0     (*((volatile unsigned long *)0x7F005008))
#define UMCON0     (*((volatile unsigned long *)0x7F00500C))
#define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))
#define UFSTAT0    (*((volatile unsigned long *)0x7F005018))
#define UTXH0      (*((volatile unsigned char *)0x7F005020))
#define URXH0      (*((volatile unsigned char *)0x7F005024))
#define UBRDIV0    (*((volatile unsigned short *)0x7F005028))
#define UDIVSLOT0  (*((volatile unsigned short *)0x7F00502C))
#define GPACON     (*((volatile unsigned long *)0x7F008000))
#define ENABLE_FIFO 
int getc_nowait(unsigned char *pChar)
{
#ifdef ENABLE_FIFO
if ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)
#else
if ((UTRSTAT0 & (1<<0)) == 0)
#endif
{
return -1;
}
else
{
*pChar = URXH0;
return 0;
}
}
#define SROM_BW     (*((volatile unsigned long *)0x70000000))
void dm9000aep_init(void)
{
SROM_BW |=  (0XFF<<4);	
}
增加文件还要修改board\samsung\smdk6410下的Makefile:修改37行

COBJS-y := smdk6410.o sdram.o init.o

上面的代码都是我直接从以前的裸板update程序拷贝过来的,实现了NAND、DDR初始化以及拷贝代码到内存。分析u-boot-2012.04.01的重定位写的很复杂,这里还是沿用以前那种简单的重定位,有兴趣的可以分析它的重定位代码,下面继续修改

241:修改call_board_init_f成如下:

call_board_init_f:
ldr r0,=0x00000000
bl board_init_f
/*r0=(unsigned int)id */
ldr   r1, _TEXT_BASE/*link address*/
ldr   sp, base_sp //add*** you must add sp, otherwise,Saving Environment to NAND... 

/*jump to second step code*/
bl    board_init_r

这里新用到变量base_sp ,需要定义134:增加

.globl base_sp //add***
base_sp:
.long 0

同时去掉u-boot自带的重定位代码,下面这部分代码可以全部去掉,这里没有用

/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
.globl	relocate_code
relocate_code:
mov	r4, r0	/* save addr_sp */
mov	r5, r1	/* save addr of gd */
mov	r6, r2	/* save addr of destination */
/* Set up the stack						    */
stack_setup:
mov	sp, r4
adr	r0, _start
cmp	r0, r6
beq	clear_bss		/* skip relocation */
mov	r1, r6			/* r1 <- scratch for copy_loop */
ldr	r3, _bss_start_ofs
add	r2, r0, r3		/* r2 <- source end address	    */
copy_loop:
ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
stmia	r1!, {r9-r10}		/* copy to   target address [r1]    */
cmp	r0, r2			/* until source end address [r2]    */
blo	copy_loop
#ifndef CONFIG_SPL_BUILD
/*
* fix .rel.dyn relocations
*/
ldr	r0, _TEXT_BASE		/* r0 <- Text base */
sub	r9, r6, r0		/* r9 <- relocation offset */
ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
add	r10, r10, r0		/* r10 <- sym table in FLASH */
ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
fixloop:
ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
add	r0, r0, r9		/* r0 <- location to fix up in RAM */
ldr	r1, [r2, #4]
and	r7, r1, #0xff
cmp	r7, #23			/* relative fixup? */
beq	fixrel
cmp	r7, #2			/* absolute fixup? */
beq	fixabs
/* ignore unknown type of fixup */
b	fixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
add	r1, r10, r1		/* r1 <- address of symbol in table */
ldr	r1, [r1, #4]		/* r1 <- symbol value */
add	r1, r1, r9		/* r1 <- relocated sym addr */
b	fixnext
fixrel:
/* relative fix: increase location by offset */
ldr	r1, [r0]
add	r1, r1, r9
fixnext:
str	r1, [r0]
add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
cmp	r2, r3
blo	fixloop
#endif
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
/* enable domain access */
ldr	r5, =0x0000ffff
mcr	p15, 0, r5, c3, c0, 0	/* load domain access register */
/* Set the TTB register */
ldr	r0, _mmu_table_base
ldr	r1, =CONFIG_SYS_PHY_UBOOT_BASE
ldr	r2, =0xfff00000
bic	r0, r0, r2
orr	r1, r0, r1
mcr	p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mrc	p15, 0, r0, c1, c0, 0
orr	r0, r0, #1		/* Set CR_M to enable MMU */
/* Prepare to enable the MMU */
adr	r1, skip_hw_init
and	r1, r1, #0x3fc
ldr	r2, _TEXT_BASE
ldr	r3, =0xfff00000
and	r2, r2, r3
orr	r2, r2, r1
b	mmu_enable
.align 5
/* Run in a single cache-line */
mmu_enable:
mcr	p15, 0, r0, c1, c0, 0
nop
nop
mov	pc, r2
skip_hw_init:
#endif
clear_bss:
#ifndef CONFIG_SPL_BUILD
ldr	r0, _bss_start_ofs
ldr	r1, _bss_end_ofs
mov	r4, r6			/* reloc addr */
add	r0, r0, r4
add	r1, r1, r4
mov	r2, #0x00000000		/* clear			    */
clbss_l:str	r2, [r0]		/* clear loop...		    */
add	r0, r0, #4
cmp	r0, r1
bne	clbss_l
#ifndef CONFIG_NAND_SPL
bl coloured_LED_init
bl red_led_on
#endif
#endif
进入bl board_init_f 还要修改arch\arm\lib\board.c

在265:声明前面start.S定义的变量

extern ulong base_sp;//**add

在373行修改如下:

//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = _TEXT_BASE;//0x57e0000
在439行修改如下去掉重定位,返回堆栈

base_sp = addr_sp;//**add
//relocate_code(addr_sp, id, addr);
return (unsigned int)id;

既然return (unsigned int)id;那么还要修改函数类型

259:void board_init_f(ulong bootflag)改为unsigned int board_init_f(ulong bootflag)

继续修改arch\arm\config.mk 75:

#LDFLAGS_u-boot += -pie

u-boot运行后,不管是NNAD还是NOR Flash启动,都会进行重定位,即把代码拷到内存运行,就像PC机一样程序都是在内存运行的。那么支持NAND启动的u-boot,重定位之前代码必须小于4KB,才能跑起来。分析现在较新的u-boot源码(以后在另外文章分析),代码连接时加-pie选项,重定位成位置无关代码,搞的很高级,不利于像S3C2440这样片内SRAM十分有限的SOC跑。这里修改重定位代码,支持NAND启动。故去掉-pie

在board\samsung\smdk6410/u-boot-nand.lds:38增加

board/samsung/smdk6410/libsmdk6410.o (.text)

这样做是为了保证重定位前的代码放在最前面4K以内。

上面修改了很多地方,先编译,有问题再修改

change@change:/si/OK6410/u-boot-2012.04.01$ make

board.c:259: error: conflicting types for 'board_init_f'
/si/OK6410/u-boot-2012.04.01/include/common.h:276: error: previous declaration of 'board_init_f' was here
make[1]: *** [board.o] Error 1
make[1]: Leaving directory `/si/OK6410/u-boot-2012.04.01/arch/arm/lib'
make: *** [arch/arm/lib/libarm.o] Error 2
change@change:/si/OK6410/u-boot-2012.04.01$

出错了,跟着提示include/common.h:276: error: previous declaration of 'board_init_f' was here去include/common.h:276看看

果然有问题,去掉noreturn,修改函数类型如下:

unsigned int board_init_f  (ulong);
void board_init_r  (gd_t *, ulong);

再编译change@change:/si/OK6410/u-boot-2012.04.01$ make

编译通过了,现在的程序串口应该能正常输出了

四、烧写测试

现在的u-boot肯定还是不能用,如果你想烧进去看看现象,这里介绍一种好方法烧写程序。先用飞淩提供的一键烧写工具,写mmc.bin到sd卡,再把上面编译生成的u-boot.bin拷到sd卡,接着把单板拨到sd卡启动。我的OK6410在NAND启动的情况下直接把6、7拨到on就变成SD启动了。单板SD卡启动上电,串口(115200 8 n 1)输出如下:

U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410


****************************************
**    u-boot 1.1.6                    **
**    Updated for TE6410 Board        **
**    Version 1.0 (10-01-15)          **
**    OEM: Forlinx Embedded           **
**    Web: http://www.witech.com.cn   **
****************************************


CPU:     S3C6410 @532MHz
         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode) 
Board:   SMDK6410
DRAM:    128 MB
Flash:   0 kB
NAND:    tmp = 29
select s3c_nand_oob_mlc_128
2048 MB 
SD/MMC:  1904 MB 
*** Warning - bad CRC or moviNAND, using default environment


In:      serial
Out:     serial
Err:     serial
Hit any key to stop autoboot:  0 


NAND erase: device 0 whole chip
Skipping bad block at  0x00800000                                            
Skipping bad block at  0x0e400000                                            
Skipping bad block at  0x0e780000                                            
Skipping bad block at  0x13b80000                                            
Skipping bad block at  0x27a80000                                            
Skipping bad block at  0x7e280000                                            
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
error found: 0010

很不幸遇到error,再网上看了很多贴找到了解决方法。

在这里http://www.pc6.com/softview/SoftView_66768.html下载Aomei Partition Assistant Professional Edition 4.0,用该分区根据将以前分区删除,然后新建分区就行了,记住只选择你的SD卡盘,不要把自己系统盘给删了,那就亏大了。还是简单说明哈操作,解压进入运行PartAssist.exe,在看到最下面的sd卡盘,选择你的sd卡盘,单击左侧Delete All Partitions,再单击上面的Aplly.完成后同样的操作新建分区即可。不清楚可以问我,要是系统盘给自己格了,别怪我。重新分区后的SD卡启动如下

K
U-Boot 1.1.6 (Dec 15 2010 - 09:02:39) for SMDK6410
****************************************
**    u-boot 1.1.6                    **
**    Updated for TE6410 Board        **
**    Version 1.0 (10-01-15)          **
**    OEM: Forlinx Embedded           **
**    Web: http://www.witech.com.cn   **
****************************************
CPU:     S3C6410 @532MHz
         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode) 
Board:   SMDK6410
DRAM:    128 MB
Flash:   0 kB
NAND:    tmp = 29
select s3c_nand_oob_mlc_128
2048 MB 
SD/MMC:  1904 MB 
*** Warning - bad CRC or moviNAND, using default environment
In:      serial
Out:     serial
Err:     serial
Hit any key to stop autoboot:  0 

NAND erase: device 0 whole chip
Skipping bad block at  0x00800000                                            
Skipping bad block at  0x0e400000                                            
Skipping bad block at  0x0e780000                                            
Skipping bad block at  0x13b80000                                            
Skipping bad block at  0x27a80000                                            
Skipping bad block at  0x7e280000                                            
Erasing at 0x7ff80000 -- 100% complete.
OK
reading u-boot.bin
242792 bytes read
NAND write: device 0 offset 0x0, size 0x100000
 1032192 bytes written: OK
reading zImage

** Unable to read "zImage" from mmc 0:1 **

就说明u-boot.bin烧写完毕了,没有放zImage当然Unable to read "zImage"。没关系,断电将ok6410拨码开关6、7拨到off就变成NAND启动了。启动输出如下:

U-Boot 2012.04.01 (Jun 24 2013 - 23:27:16) for SMDK6400


CPU:     S3C6400@532MHz
         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board:   SMDK6400
DRAM:  128 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###

还有很多问题,串口基本正常输出了。根据u-boot输出的Flash: *** failed ***,根据以往经验应该是没有检测到板子的NOR FLASH就卡住了,问题不大,好吧继续修改

进入arch/arm/lib/board.c 530修改如下

  //puts(failed);
  //hang();
  puts("0 KB\n\r");

没有检测到就hang();,屏蔽让它输出OKB,修改后继续编译,编译OK按照上面的方法烧到单板,NAND启动输出如下:

U-Boot 2012.04.01 (Jun 24 2013 - 23:35:21) for SMDK6400


CPU:     S3C6400@532MHz
         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board:   SMDK6400
DRAM:  128 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND:  No oob scheme defined for oobsize 218
2048 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0
Hit any key to stop autoboot:  0
SMDK6400 #

基本OK了,这篇修改的代码有点多,先写到这吧。

 

这篇关于ok6410 u-boot-2012.04.01移植二修改源码支持单板的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/972428

相关文章

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

集中式版本控制与分布式版本控制——Git 学习笔记01

什么是版本控制 如果你用 Microsoft Word 写过东西,那你八成会有这样的经历: 想删除一段文字,又怕将来这段文字有用,怎么办呢?有一个办法,先把当前文件“另存为”一个文件,然后继续改,改到某个程度,再“另存为”一个文件。就这样改着、存着……最后你的 Word 文档变成了这样: 过了几天,你想找回被删除的文字,但是已经记不清保存在哪个文件了,只能挨个去找。真麻烦,眼睛都花了。看

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

如何在运行时修改serialVersionUID

优质博文:IT-BLOG-CN 问题 我正在使用第三方库连接到外部系统,一切运行正常,但突然出现序列化错误 java.io.InvalidClassException: com.essbase.api.base.EssException; local class incompatible: stream classdesc serialVersionUID = 90314637791991