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
NOR Flash:EN29LV160AB 2MB
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等都在bllowlevel_init完成,进入boardsamsungsmdk6410lowlevel_init.S:修改95: bl system_clock_init,将时钟初始化换成如下代码(以前写的裸板代码):

boardsamsungsmdk6410lowlevel_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��钡u0153CPUu0153�胍觳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

二、修改串口初始化

boardsamsungsmdk6410lowlevel_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初始化代码

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

104://bl nand_asm_init
107:/* Memory subsystem address 0x7e00f120 */
//ldrr0, =ELFIN_MEM_SYS_CFG
/* Xm0CSn2 = NFCON CS0, Xm0CSn3 = NFCON CS1 */
//movr1, #S3C64XX_MEM_SYS_CFG_NAND
//strr1, [r0]
//blmem_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]
bicr1, r1, #0xfffffff7
cmpr1, #0x8
beqwakeup_reset
1:
movlr, r12
movpc, 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
movlr, r12
mov pc, lr
nop
nop
接着在archarmcpuarm1176start.S中增加对NAND、DDR等支持

在225:bllowlevel_init后增加如下代码

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

bl    ddr_init_ll
bl    nand_init_ll
bldm9000aep_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裸板代码。直接在boardsamsungsmdk6410增加sdram.c、init.c两个文件。代码如下

文件sdram.c:

//#include <common.h>


#define MEMCCMD0x7e001004
#define P1REFRESH0x7e001010
#define P1CASLAT0x7e001014
#define MEM_SYS_CFG0x7e00f120
#define P1MEMCFG0x7e00100c
#define P1T_DQSS0x7e001018
#define P1T_MRD0x7e00101c
#define P1T_RAS0x7e001020
#define P1T_RC0x7e001024
#define P1T_RCD0x7e001028
#define P1T_RFC0x7e00102c
#define P1T_RP0x7e001030
#define P1T_RRD0x7e001034
#define P1T_WR0x7e001038
#define P1T_WTR0x7e00103c
#define P1T_XP0x7e001040
#define P1T_XSR0x7e001044
#define P1T_ESR0x7e001048
#define P1MEMCFG20X7e00104c
#define P1_chip_0_cfg0x7e001200


#define P1MEMSTAT0x7e001000
#define P1MEMCCMD0x7e001004
#define P1DIRECTCMD0x7e001008



#define HCLK133000000


#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);	
}

增加文件还要修改boardsamsungsmdk6410下的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:
ldrr0,=0x00000000
blboard_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

进入blboard_init_f 还要修改archarmliboard.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)

继续修改archarmconfig.mk 75:

#LDFLAGS_u-boot += -pie

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

在boardsamsungsmdk6410/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);
voidboard_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 ");

没有检测到就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了,这篇修改的代码有点多,先写到这吧。

原文地址:https://www.cnblogs.com/jiangu66/p/3155367.html