程序卡OK6410裸板更新程序_update

新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正

    我用的飞淩ok6410开发板,DNW下载程序太易容出问题了,于是买了个openjtag,买回来才发明暂不支撑MLC NAND。我下决心写个有下载程序功能的裸板程序update.

    再也用不忍耐DNW了,并且还分析一种SD卡下载方法。先用飞淩供给的一键烧写具工,写mmc.bin到sd卡,再把自己要下载的程序以u-boot.bin定名,也拷到sd卡,

    mmc.bin会动自帮你把程序烧写到NAND,再从NAND动启就运行你的程序了。后以这片sd卡就相当于你的下载器,要需跑什么程序拷到sd卡就OK了。

    详细作操过程见前面,在现开始写update程序。

    系统:ubuntu 10.04.4
单板:ok6410
编译器:arm-linux-gcc-4.3.2
搭建开发环境详见ubuntu 10.04.4开发环境置配。

    标目:串口输出菜单,有以下·功能供选择

    *********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
                 date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:

    即现实读写nand,通过V2.2.exe/gtkterm发送文件到内存,再写到NADN flash 0地址,以及重启update程序。

    改程序主要功能是现实新更程序,以及把程序放到内存运行·。

    一、编写源代码

    根据s5pc100手册编写代码,包含源文件start.S clock.S  sdram.c init.c main.c boot.lds Makefile

    文件start.S:

.text	
.global _start
_start:
	/*0. 硬件关相的置设 */
	/* Peri port setup */
	ldr r0, =0x70000000
	orr r0, r0, #0x13
	mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)
	
	/*1.关看门狗*/
        ldr r0, =0x7E004000
	mov r1, #0
	str r1, [r0]

	ldr sp, =8*1024
	
	/*2.置设时钟*/
	bl  clock_init

	/*3.初始化SDRAM DDR*/
	bl  ddr_init

	/*4.重定位:把代码从flash复制到他的链接地址*/
	ldr sp, =0x58000000
	bl  nand_init

	mov r0, #0
	ldr r1, =_start
	ldr r2, =__bss_start
	sub r2, r2, r1

	bl copy_code_to_sdram
	bl clear_bss
	/*5.行执main*/
	ldr lr, =halt
	ldr pc, =main

halt:
	b   halt

    文件clock.S:

.globl clock_init

clock_init:
	
	/* 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时,要设为异步模式 */
	ldr r0, =OTHERS
	ldr r1, [r0]
	bic r1, r1, #0xc0	/* 1100,0000 */		
	str r1, [r0]

loop1:				/* 待等,直到CPU进入异步模式 */
	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的输出作为时钟源 */
	ldr r0, =0x7E00F01C
	ldr r1, =0x03
	str r1, [r0]
	
	mov pc, lr

    文件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( 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(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)
    {
      /*写胜利,是nand动启*/
      *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;
  /*如果是Nor动启*/
  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(src, dest, len);
    }
}

void nand_select(void)
{
  NFCONT &= ~(1<<1);
}

void nand_deselect(void)
{
  NFCONT |= (1<<1);
}


void nand_cmd(unsigned char cmd)
{
  NFCMMD = cmd;
}

void nand_addr(unsigned char addr)
{
  NFADDR = addr;
}

unsigned char nand_get_data(void)
{
  return NFDATA;
}

void nand_send_data(unsigned char data)
{
  NFDATA = data;
}

void wait_ready(void)
{
  while ((NFSTAT & 0x1) == 0);
}


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(void)
{
  /* 让xm0csn2用作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();
}

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(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)//前4页每次只能写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(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(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))//前2页每页只能写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 

static void delay(void)
{
  volatile int i = 10;
  while (i--);
}
void init_uart(void)
{
  GPACON &= ~0xff;
  GPACON |= 0x22;
  
  /* ULCON0 */
  ULCON0 = 0x3;  /* 数据位:8, 无较验, 停止位: 1, 8n1 */
  UCON0  = 0x5;  /* 使能UART发送、收接 */
#ifdef ENABLE_FIFO
  UFCON0 = 0x07; /* FIFO enable */
#else
  UFCON0 = 0x00; /* FIFO disable */
#endif
  UMCON0 = 0;
  
  /* 波特率 */
  /* DIV_VAL = (PCLK / (bps x 16 ) ) - 1 
   * bps = 115200
   * DIV_VAL = (66500000 / (115200 x 16 ) ) - 1 
   *         = 35.08
   */
  UBRDIV0   = 35;

  /* x/16 = 0.08
   * x = 1
   */
  UDIVSLOT0 = 0x1;
  
}

unsigned char getc(void)
{
#ifdef ENABLE_FIFO
  while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)delay();
#else
  while ((UTRSTAT0 & (1<<0)) == 0);
#endif
  
  return URXH0;
}

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

void putc(char c)
{
#ifdef ENABLE_FIFO
  while (UFSTAT0 & (1<<14))delay();
#else
  while ((UTRSTAT0 & (1<<2)) == 0);
#endif
  UTXH0 = c;
}

void puts(char *str)
{
  int i = 0;
  while (str[i])
    {
      putc(str[i]);
      i++;
    }
}

void puthex(unsigned int val)
{
  /* 0x1234abcd */
  int i;
  int j;

  puts("0x");

  for (i = 0; i < 8; i++)
    {
      j = (val >> ((7-i)*4)) & 0xf;
      if ((j >= 0) && (j <= 9))
	putc('0' + j);
      else
	putc('A' + j - 0xa);

    }

}
void putbyte(unsigned char val)
{
  /* 0x1234abcd */
  int i;
  int j;

  puts("0x");

  for (i = 0; i < 2; i++)
    {
      j = (val >> ((1-i)*4)) & 0xf;
      if ((j >= 0) && (j <= 9))
	putc('0' + j);
      else
	putc('A' + j - 0xa);

    }

}
    每日一道理
风,渐渐吹起,吹乱了我的发丝,也让我的长裙有些飘动。绿叶仿佛在风中起舞,离开了树,投向了大地,却不知这样会枯萎,我弯下腰,轻轻拾起一片树叶,那非常有序的茎脉,是一种美的点缀。我有些哀叹:绿叶啊,绿叶,你这般美丽地从树上轻轻飘下,随风起舞,却不知已被人称之为落叶!

    文件main.c:

extern void init_uart(void);
extern void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len);
extern void putc(char c);
extern void puts(char *str);
extern void puthex(unsigned int val);
extern unsigned char getc(void);
extern int getc_nowait(unsigned char *pChar);
extern void putbyte(unsigned char val);
extern void nand_erase_block(unsigned long addr);
extern void nand_write(unsigned int nand_start, unsigned char * buf, unsigned int len);


int strlen(char *str)
{
  int i = 0;
  while (str[i])
    {
      i++;
    }
  return i;
}
void nand_read_test(void)

{
  int i;
  char buf[100];
  unsigned long addr;
  unsigned long size;
 
  puts("enter the start address: 0x80000");

  //scanf("%s", buf);

  //addr = strtoul(buf, NULL, 0);
  addr = 0x80000;
  //puts("read addr = 0x%x\n\r", addr);

  puts("enter the size: 0x60");

  //scanf("%s", buf);
  //size = strtoul(buf, NULL, 0);
  size = 0x60;

  if (size > 100)
    {
      puts("the max size is 100\n\r");
      size = 100;
    }
  nand_read(addr, buf, size);

  puts("datas: \n\r");
  for (i = 0; i < size; i++)
    {
      // printf("%02x ", buf[i]);
      putbyte(buf[i]);
      puts("\t");
      if ((i+1) % 8 == 0)
	{
	  puts("\n\r");
	}
    }
  puts("\n\r");
}

void nand_erase_test(void)
{
  //char buf[100];
  unsigned long addr;
  
  puts("enter the start address: ");
  //scanf("%s", buf);
  //addr = strtoul(buf, NULL, 0);
  addr = 0x80000;
  puts("erase addr = ");
  puthex(addr);
  puts("\n\r");
  nand_erase_block(addr);
  
}

void nand_write_test(void)
{
  char buf[20] = {"abcd1234ABCD"};
  unsigned long addr;
  unsigned long size;
  
  puts("enter the start address:0x80000 ");
  //scanf("%s", buf);
  //addr = strtoul(buf, NULL, 0);
  addr = 0x80000;
  puts("enter the string:abcd1234ABCD ");
  //scanf("%s", buf);
  size = strlen(buf) + 1;
  puts(" size= ");
  puthex(size);
  puts("\n\r");
  nand_write(addr, buf, size);
  
}


void update_program(void)
{
  unsigned char *buf = (unsigned char *)0x52000000;
  unsigned long len = 0;
  int have_begin = 0;
  int nodata_time = 0;
  unsigned long erase_addr;
  char c;
  int i;

  /* 璇讳覆鍙h幏寰楁暟鎹?*/
  puts("\n\ruse V2.2.exe/gtkterm to send file\n\r");
  while (1)
    {
      if (getc_nowait(&buf[len]) == 0)
	{
	  have_begin = 1;
	  nodata_time = 0;
	  len++;
	}
      else
	{
	  if (have_begin)
	    {
	      nodata_time++;
	    }
	}

      if (nodata_time == 1000)
	{
	  break;
	}
    }
  puts("\n\rhave get data:");
  puthex(len);
  puts(" bytes\n\r");
  puts("the first 16 bytes data: \n\r");
  for (i = 0; i < 16; i++)
    {
      // put("%02x ", buf[i]);
      putbyte(buf[i]);
      puts("\t");
    }
  puts("\n\r");

  puts("Press Y to program the flash: \n\r");

  c = getc();
  putc(c);
  puts("\n\r");
  if (c == 'y' || c == 'Y')
    {
      /* 鐑у啓鍒皀and flash block 0 */
      for (erase_addr = 0; erase_addr < ((len + 0x1FFFF) & ~0x1FFFF); erase_addr += 0x20000)
	{
	  nand_erase_block(erase_addr);
	}
      nand_write(0, buf, len);
      
      puts("update program successful\n\r");
    }
  else
    {
      puts("Cancel program!\n\r");
    }
}

void run_program(void)
{
  unsigned char *buf = (unsigned char *)0x57e00000;
  unsigned long len = 0;
  int have_begin = 0;
  int nodata_time = 0;
  void (*theProgram)(void);
  int i;
  
  puts("\n\r use gtkterm to send file\n\r");
  while (1)
    {
      if (getc_nowait(&buf[len]) == 0)
	{
	  have_begin = 1;
	  nodata_time = 0;
	  len++;
	}
      else
	{
	  if (have_begin)
	    {
	      nodata_time++;
	    }
	}

      if (nodata_time == 1000)
	{
	  break;
	}
    }
  //printf("have get %d bytes data\n\r", len);
  puts("\n\r have get data:");
  puthex(len);
  puts(" bytes\n\r");
  puts("the first 16 bytes data: \n\r");
  for (i = 0; i < 16; i++)
    {
      // put("%02x ", buf[i]);                                                                     
      putbyte(buf[i]);
      puts("\t");
      //putc('\0');
    }
  puts("\n\r");
  puts("jump to 0x57e00000 to run it\n\r");
  
  theProgram = (void (*)(void))0x57e00000;

  theProgram();
}

int main(void)
{
  char c;
 
  init_uart();

  puts("\n\r*********************************\n\r");
  puts("update program with serial port\n\r");
  puts("The board:witech(ok6410)\n\r");
  puts("The NAND:K9GAG08U0D 2048MB\n\r");
  puts("The DDR:K4X1G163PCX2 256MB\n\r");
  puts("The NET:DM9000AEP\n\r");
  puts("                 date: 2013.4.26\n\r");
  puts("***********************************\n\r");

  while (1)
    {
      puts("the menu of the update programe:\n\r");
      puts("[w] write the nand flash\n\r");
      puts("[r] read the nand flash\n\r");
      puts("[e] erase the nand flash\n\r");
      puts("[g] get file, and write to nand flash 0 block\n\r");
      puts("[x] get file to ddr(0x57e00000), run it\n\r");
      puts("[s] reset the programe\n\r");
      puts("Please enter the chose:\n\r");

      do {
	c = getc();
	if (c == '\n' || c == '\r')
	  {
	    puts("\n\r");
	  }
	else
	  {
	    putc(c);
	  }
      } while (c == '\n' || c == '\r');
      
      switch (c)
	{
	case 'w':
	case 'W':
	  {
	    nand_write_test();
	    break;
	  }

	case 'r':
	case 'R':
	  {
	    nand_read_test();
	    break;
	  }

	case 'e':
	case 'E':
	  {
	    nand_erase_test();
	    break;
	  }

	case 'g':
	case 'G':
	  {
	    update_program();
	    break;
	  }

	case 'x':
	case 'X':
	  {
	    run_program();
	    break;
	  }

	case 's':
	case 'S':
	  {
	    void (*theProgram)(void);
	    theProgram = (void (*)(void))0x57e00000;
	    theProgram();
	    break;
	  }
	
	}
    }

  return 0;
}

    文件boot.lds:

SECTIONS {
    . = 0x57e00000;
    .text : { *(.text) }
    
    . = ALIGN(4);
    .rodata : {*(.rodata*)} 
    
    . = ALIGN(4);
    .data : { *(.data) }
    
    . = ALIGN(4);
    __bss_start = .;
    .bss : { *(.bss)  *(COMMON) }
    __bss_end = .;
}

    文件Makefile:

CC      = arm-linux-gcc
LD      = arm-linux-ld 
AR      = arm-linux-ar
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump

CFLAGS 		:= -Wall -O2
CPPFLAGS   	:= -nostdinc -nostdlib -fno-builtin

objs := start.o clock.o sdram.o init.o main.o

update.bin: $(objs)
	${LD} -Tboot.lds -o boot.elf $^
	${OBJCOPY} -O binary -S boot.elf $@
	${OBJDUMP} -D -m arm boot.elf > boot.dis

%.o:%.c
	${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o:%.S
	${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:
	rm -f *.o *.bin *.elf *.dis

    二、编译源程序

    change@change:~/Si/OK6410/update$ cd /home/change/
change@change:~$ cd Si/OK6410/update/
change@change:~/Si/OK6410/update$ make clean
rm -f *.o *.bin *.elf *.dis
change@change:~/Si/OK6410/update$ make
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o start.o start.S
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o clock.o clock.S
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o sdram.o sdram.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o init.o init.c
arm-linux-gcc -nostdinc -nostdlib -fno-builtin -Wall -O2 -c -o main.o main.c
main.c: In function 'nand_read_test':
main.c:50: warning: passing argument 2 of 'nand_read' makes integer from pointer without a cast
main.c: In function 'nand_write_test':
main.c:98: warning: pointer targets in passing argument 2 of 'nand_write' differ in signedness
arm-linux-ld  -Tboot.lds -o boot.elf start.o clock.o sdram.o init.o main.o
arm-linux-objcopy -O binary -S boot.elf update.bin
arm-linux-objdump -D -m arm boot.elf > boot.dis
change@change:~/Si/OK6410/update$ 

    这都是经过修改后的终究编译结果,所以没有错误。

    三、烧写、试测

    用新想到的方法烧写程序,用不面前说的u-boot下载程序。先用飞淩供给的一键烧写具工,写mmc.bin到sd卡,再把面下编译成生的update.bin以u-boot.bin定名,并拷到sd卡,接着把单板拨到sd卡动启。我的OK6410在NAND动启的情况下直接把6、7拨到on就成变SD动启了。单板SD卡动启上电,串口(115200 8 n 1)输出如下:

    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:  1877 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


5228 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烧写毕完。烧写mmc.bin的SD卡,会动自帮你把程序烧写到NAND。接着断电下取SD卡,单板拨到NAND动启,串口输出如下:

    *********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
                 date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:

    用串口具工v2.2.exe,演示update程序功能如下:

    
*********************************
update program with serial port
The board:witech(ok6410)
The NAND:K9GAG08U0D 2048MB
The DDR:K4X1G163PCX2 256MB
The NET:DM9000AEP
                 date: 2013.4.26
***********************************
the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:

    g
use V2.2.exe/gtkterm to send file

    接着选要择发送的文件eg:u-boot.bin,并发送文件,发送毕完输出如下:

have get data:0x0003A6BC bytes
the first 16 bytes data: 
0x150x00 0x000xEA 0x140xF0 0x9F0xE5 0x140xF0 0x9F0xE5 0x140xF0 0x9F0xE5
Press Y to program the flash: 

    接着手动发送y,这里要慎谨作操,因为一旦入输y,程序就会擦除之前的程序。串口输出如下:

    update program successful

the menu of the update programe:
[w] write the nand flash
[r] read the nand flash
[e] erase the nand flash
[g] get file, and write to nand flash 0 block
[x] get file to ddr(0x57e00000), run it
[s] reset the programe
Please enter the chose:

    看到update program successful面下程序新更毕完。面下来验证,断电重启,串口输出如下:

    

U-Boot 2012.04.01 (Nov 25 2012 - 21:01:21) for SMDK6410




CPU:     S3C6400@532MHz
         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode) 
Board:   SMDK6410
DRAM:  128 MiB
WARNING: Caches not enabled
Flash: 0 KB
NAND:  select s3c_nand_oob_mlc_64
id_data[0] = 0xec id_data[1] = 0xd5 id_data[2] = 0x94 id_data[3] = 0x29 id_data[4] = 0x34 id_data[5] = 0x41 id_data[6] = 0xec id_data[7] = 0xd5 NAND_ECC_NONE selected by board driver. This is not recommended !!
2048 MiB
realpage value:255
page value:255
ret value:0
*** Warning - bad CRC, using default environment


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


##### 100ask Bootloader for OpenJTAG #####
[n] Download u-boot to Nand Flash
[k] Download Linux kernel uImage
[j] Download root_jffs2 image
[y] Download root_yaffs image
[d] Download to SDRAM & Run
[z] Download zImage into RAM
[g] get file, and write to nand flash 0 block
[f] Format the Nand Flash
[s] Set the boot parameters
[b] Boot the system
[r] Reboot u-boot
[q] Quit from menu
Enter your selection: q
SMDK6410 #

    明说u-boot经已下载毕完,当然之前的程序也就擦掉了。经过试测基本OK,可能还存在bug,横竖人多力量大,可以提出一同处理。

文章结束给大家分享下程序员的一些笑话语录: 刹车失灵
有一个物理学家,工程师和一个程序员驾驶着一辆汽车行驶在阿尔卑斯山脉 上,在下山的时候,忽然,汽车的刹车失灵了,汽车无法控制地向下冲去, 眼看前面就是一个悬崖峭壁,但是很幸运的是在这个悬崖的前面有一些小树 让他们的汽车停了下来, 而没有掉下山去。 三个惊魂未定地从车里爬了出来。
物理学家说, “我觉得我们应该建立一个模型来模拟在下山过程中刹车片在高 温情况下失灵的情形”。
工程师说, “我在车的后备厢来有个扳手, 要不我们把车拆开看看到底是什么 原因”。
程序员说,“为什么我们不找个相同的车再来一次以重现这个问题呢?”

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3045727.html