S5PC100裸板更新程序_update

以前的裸板程序都是通过u-boot或自我更新程序update下载到内存运行,今天实现更新程序update,程序运行时会输出一个菜单供选择。

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

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

[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(0x22000000), run it
[s] reset the programe

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

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

一、编写源代码

根据s5pc100手册编写代码,包括源文件start.S clock.S  cpu_init.S nand.c main.c uart.c lib.c lib.h Makefile

文件start.S:

.global

_start:
	/*1. Disable Watchdog */
	/*1.鍏崇湅闂ㄧ嫍*/
	ldr	r0, =0xEA200000
	mov	r1, #0
	str	r1, [r0]

	bl	clock_init
	//bl	test
	bl	mp1_x_drive_strength_init
	bl	mem_ctrl_asm_init
	ldr	sp, =0xD0038000
	bl	init_uart
	bl	nand_init
	//bl	test
	ldr	r0, =0x0
	ldr	r1, =0x21000000
	ldr	r2, =bss_start
	sub	r2, r2, r1
	bl	copy_code_to_sdram
	//bl	test
	//b	main

clean_bss:
	ldr r0, =bss_start
	ldr r1, =bss_end
	mov r3, #0
	cmp r0, r1
	ldreq pc, =on_ddr
	
clean_loop:
	str r3, [r0], #4
	cmp r0, r1
	bne clean_loop
	ldr pc, =on_ddr

on_ddr:
	ldr sp, =0x21800000    /* 设置堆栈*/
	//bl  test
	ldr pc, =main

文件clock.S:

.globl clock_init

clock_init:
	
	/* 1.设置LOCK_TIME */
	ldr r0, =0xe0100000  	//CLOCK_POWER_BASE
	mov r1, #0xe00
	orr r1, r1, #0x10
	str r1, [r0, #0x0]		/* APLL_LOCK */
	str r1, [r0, #0x4]	 /* MPLL_LOCK */
	str r1, [r0, #0x8]	 /* EPLL_LOCK */
	str r1, [r0, #0x0c]	//HPLL_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]
/* CLK_DIV0 */
#define APLL_RATIO	0
#define ARM_RATIO	4
#define D0_BUS_RATIO	8
#define PCLKD0_RATIO	12
#define SECSS_RATIO	16
	
	ldr r1, [r0, #0x300]	//CLK_DIV0 Clock divider
	ldr r2, =0x3fff
	bic r1, r1, r2

	ldr r2, =(1<<APLL_RATIO) | (0<<ARM_RATIO) | (4<<D0_BUS_RATIO) | (1<<PCLKD0_RATIO) | (1<<SECSS_RATIO)
	orr r1, r1, r2
	str r1, [r0, #0x300]	//CLK_DIV0

	ldr r2, =((1<<16) | (1<<12) | (1<<8) | (1<<4))
	orr r1 ,r1, r2
	str r1, [r0, #0x304]	//CLD_DIV1
	/* 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  */
#define APLL_VAL  ((1<<31) | (417 << 16) | (3 << 8) | (0))	
	//ldr r0, =0xe0100100	//APLL_CON
	ldr r1, =APLL_VAL
	str r1, [r0, #0x100]		/* MPLL_CON, FOUTMPL = 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))
//CONFIG_CLK_833_166_66
#define MPLL_VAL  ((1<<31) | (89 << 16) | (2 << 8) | (1))
#define EPLL_VAL  ((1<<31) | (135 << 16) | (3 << 8) | (3))
#define HPLL_VAL  ((1<<31) | (96 << 16) | (6 << 8) | (3))

	ldr r1, =MPLL_VAL
	str r1, [r0, #0x104]

	ldr r1, =EPLL_VAL
	str r1, [r0, #0x108]

	ldr r1, =HPLL_VAL
	str r1, [r0, #0x10c]
	
	/* 3.选择PLL的输出作为时钟源 */
	ldr r1, [r0, #0x200]	//CLK_SRC0 0xe0100200
	ldr r2, =0x1111
	orr r1, r1, r2
	str r1, [r0, #0x200]	//FOUT: APLL MPLL EPLL HPLL

	mov 	r1, #0x10000
1:	subs	r1, r1, #1
	bne	1b

	mov pc, lr
文件cpu_init.S:

//#include "s5pc100.h"
/* Port Group MP1_X Drive Strength Control */
#define MP1_0DRV_OFFSET			0x03CC
#define MP1_1DRV_OFFSET			0x03EC
#define MP1_2DRV_OFFSET			0x040C
#define MP1_3DRV_OFFSET			0x042C
#define MP1_4DRV_OFFSET			0x044C
#define MP1_5DRV_OFFSET			0x046C
#define MP1_6DRV_OFFSET			0x048C
#define MP1_7DRV_OFFSET			0x04AC
#define MP1_8DRV_OFFSET			0x04CC

/*
 * Bus Matrix
 */
#define ELFIN_MEM_SYS_CFG		0x7e00f120

/*
 * Memory controller
 */
#define ELFIN_SROM_BASE			0xE7000000

#define SROM_BW_REG			__REG(ELFIN_SROM_BASE+0x0)
#define SROM_BC0_REG			__REG(ELFIN_SROM_BASE+0x4)
#define SROM_BC1_REG			__REG(ELFIN_SROM_BASE+0x8)
#define SROM_BC2_REG			__REG(ELFIN_SROM_BASE+0xC)
#define SROM_BC3_REG			__REG(ELFIN_SROM_BASE+0x10)
#define SROM_BC4_REG			__REG(ELFIN_SROM_BASE+0x14)
#define SROM_BC5_REG			__REG(ELFIN_SROM_BASE+0x18)

/*
 * SDRAM Controller
 */
#define APB_DMC_BASE			0xE6000000

#define	DMC_CONCONTROL			0x00
#define	DMC_MEMCONTROL			0x04
#define	DMC_MEMCONFIG0			0x08
#define	DMC_MEMCONFIG1			0x0C
#define	DMC_DIRECTCMD			0x10
#define	DMC_PRECHCONFIG			0x14
#define	DMC_PHYCONTROL0			0x18
#define	DMC_PHYCONTROL1			0x1C
#define	DMC_PHYCONTROL2			0x20
#define	DMC_PWRDNCONFIG 		0x28
#define	DMC_TIMINGAREF  		0x30
#define	DMC_TIMINGROW   		0x34
#define	DMC_TIMINGDATA  		0x38
#define	DMC_TIMINGPOWER 		0x3C
#define	DMC_PHYSTATUS0  		0x40
#define	DMC_PHYSTATUS1  		0x44
#define	DMC_CHIP0STATUS 		0x48
#define	DMC_CHIP1STATUS 		0x4C
#define	DMC_AREFSTATUS  		0x50
#define	DMC_MRSTATUS    		0x54
#define	DMC_PHYTEST0    		0x58
#define	DMC_PHYTEST1    		0x5C
#define	DMC_QOSCONTROL0 		0x60
#define	DMC_QOSCONFIG0  		0x64
#define	DMC_QOSCONTROL1 		0x68
#define	DMC_QOSCONFIG1  		0x6C
#define	DMC_QOSCONTROL2 		0x70
#define	DMC_QOSCONFIG2  		0x74
#define	DMC_DMC_QOSCONTROL3 		0x78
#define	DMC_QOSCONFIG3  		0x7C
#define	DMC_QOSCONTROL4 		0x80
#define	DMC_QOSCONFIG4  		0x84
#define	DMC_QOSCONTROL5 		0x88
#define	DMC_QOSCONFIG5  		0x8C
#define	DMC_QOSCONTROL6 		0x90
#define	DMC_QOSCONFIG6  		0x94
#define	DMC_QOSCONTROL7 		0x98
#define	DMC_QOSCONFIG7  		0x9C

/*
* Memory Chip direct command
*/
#define PRO_ID_BASE			0xE0000000
#define PRO_ID_OFFSET			0x00
#define OMR_OFFSET			0x04

/*
 * GPIO
 */
#define ELFIN_GPIO_BASE			0xE0300000


.globl	mp1_x_drive_strength_init
/*
 * Init MP1_X Driver Strength for SDRAM
 * void mp1_x_drive_strength_init(void)
 */
 mp1_x_drive_strength_init:
 
	ldr	r0, =ELFIN_GPIO_BASE
	ldr	r1, =0xaaaa
	str   	r1, [r0, #MP1_0DRV_OFFSET]
	str   	r1, [r0, #MP1_1DRV_OFFSET]
	str   	r1, [r0, #MP1_2DRV_OFFSET]
	str   	r1, [r0, #MP1_3DRV_OFFSET]
	str   	r1, [r0, #MP1_4DRV_OFFSET]
	str   	r1, [r0, #MP1_5DRV_OFFSET]
	str   	r1, [r0, #MP1_6DRV_OFFSET]	
	str   	r1, [r0, #MP1_7DRV_OFFSET]
	str   	r1, [r0, #MP1_8DRV_OFFSET]	
	
	mov pc, lr

	.globl mem_ctrl_asm_init
mem_ctrl_asm_init:

	ldr	r0, =APB_DMC_BASE			@APB_DMC_BASE 0xE6000000

	ldr	r1, =PRO_ID_BASE
	ldr	r2, [r1, #PRO_ID_OFFSET]
	bic	r2, #0xfffffdff
	mov	r2, r2, lsr #9
	cmp	r2, #0x1
	beq	onenand_pop

single:

/************ delay loop *************/

#if 0
	ldr		r1, =0x10000000
	mov 		r2, #0
loop1:

	cmp		r2, r1
	addne	r2, r2, #0x1
	bne loop1
#endif

/************ DLL initialization *************/
      
        ldr     r1, =0x6A101000				@ Phycontrol0 DLL parameter setting
        str     r1, [r0, #DMC_PHYCONTROL0]

        ldr     r1, =0x000084F4                       	 @Phycontrol1 DLL parameter setting
        str     r1, [r0, #DMC_PHYCONTROL1]

        ldr     r1, =0x00000000                        	 @Phycontrol2 DLL parameter setting
        str     r1, [r0, #DMC_PHYCONTROL2]

        ldr     r1, =0x6A101002			    	  @DLL on
        str     r1, [r0, #DMC_PHYCONTROL0]

        ldr     r1, =0x6A101003			  	@Dll start
        str     r1, [r0, #DMC_PHYCONTROL0]



	ldr	r2, = 0xE6000040		@DMC_PHYSTATUS0

loop1:

	ldr	r1, [r2]				@Check DLL lock
	ands	r1, r1, #4
	beq	loop1

	ldr	r1, [r2]
	mov	r1, r1,  LSR #(0x6)
	and	r1, r1, #(0xff)
	mov	r1, r1, LSL  #(0x18)
    ldr 	r2,  = 0xE6000018			@DMC_PHYCONTROL0
	ldr	r3, [r2]
	bic	r3,  r3, #(0xff000000)
	orr	r1, r3, r2
	str	r1, [r2]



        ldr     r1, =0x6A101003			@Force Value locking
        str     r1, [r0, #DMC_PHYCONTROL0]

        ldr     r1, =0x6A101009			@Dll off
        str     r1, [r0, #DMC_PHYCONTROL0]



#if 0
        ldr     r1, =0x6A101000				@ Phycontrol0 DLL parameter setting
        str     r1, [r0, #DMC_PHYCONTROL0]

        ldr     r1, =0x00008484                             @Phycontrol1 DLL parameter setting
        str     r1, [r0, #DMC_PHYCONTROL1]

        ldr     r1, =0x00000000                             @Phycontrol2 DLL parameter setting
        str     r1, [r0, #DMC_PHYCONTROL2]

#endif
/************ DLL initialization - END *************/




        ldr     r1, =0x0FF01010                         @auto refresh off
        str     r1, [r0, #DMC_CONCONTROL]

        ldr     r1, =0x00202400                         @ BL=4 , 1 chip , DDR2
        str     r1, [r0, #DMC_MEMCONTROL]

#if 1	// add xxs 256MB enable
        ldr     r1, =0x20F01323
        str     r1, [r0, #DMC_MEMCONFIG0]

        ldr     r1, =0x40F00323
        str     r1, [r0, #DMC_MEMCONFIG1]
#else	// 128MB enable
        ldr     r1, =0x20F81313						
        str     r1, [r0, #DMC_MEMCONFIG0]

        ldr     r1, =0x40F80313
        str     r1, [r0, #DMC_MEMCONFIG1]
#endif
  
        ldr     r1, =0x20000000		
        str     r1, [r0, #DMC_PRECHCONFIG]


 		ldr     r1, =0x00100004			@ PwrdnConfig
        str     r1, [r0, #DMC_PWRDNCONFIG]

#ifdef	CONFIG_HCLKD0_222
	ldr 	r1, =0x000006c3 						@7.8us*222MHz=0x6c3, 7.8us*166MHz=1294(0x50E)
       str     r1, [r0, #DMC_TIMINGAREF]
	/* T-rfc   127.5nS/5ns  64 */
       ldr     r1, =0x202332C8                         		@TimingRow      @222MHz
       str     r1, [r0, #DMC_TIMINGROW]

       ldr     r1, =0x24450304							@CL=5
       str     r1, [r0, #DMC_TIMINGDATA]

 #else


      	ldr     r1, =0x0000050E		
        str     r1, [r0, #DMC_TIMINGAREF]

		ldr	 r1, =0x16233297						 @TimingRow 	 @166MHz
        str     r1, [r0, #DMC_TIMINGROW]

@;		ldr	 r1, =0x24250304						 @CL=5
		ldr	 r1, =0x23230000						 @CL=3
        str     r1, [r0, #DMC_TIMINGDATA]
 #endif

        ldr     r1, =0x07c80232    	                   @ Timing Power
        str     r1, [r0, #DMC_TIMINGPOWER]

/* Direct Command for DDR2 */
        ldr     r1, =0x07000000                         @chip0 Deselect
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x01000000                        @chip0 PALL
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x00020000                         @chip0 EMRS2
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x00030000                         @chip0 EMRS3
        str     r1, [r0, #DMC_DIRECTCMD]

		ldr     r1, =0x00010400                         @chip0 EMRS1 (MEM DLL on = DQS# disable)
        str     r1, [r0, #DMC_DIRECTCMD]

@;		ldr     r1, =0x00000552                         @chip0 MRS (MEM DLL reset) CL=5, Burst Length=4
        ldr     r1, =0x00000532                         @chip0 MRS (MEM DLL reset) CL=3, Burst Length=4
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x01000000                         @chip0 PALL
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x05000000                         @chip0 REFA
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x05000000                         @chip0 REFA
        str     r1, [r0, #DMC_DIRECTCMD]

@;		ldr     r1, =0x00000452                         @chip0 MRS (MEM DLL unreset) , BL=4 , CL=5
		ldr     r1, =0x00000432                         @chip0 MRS (MEM DLL unreset) , BL=4 , CL=3 
        str     r1, [r0, #DMC_DIRECTCMD]

        ldr     r1, =0x00010780                         @chip0 EMRS1 (OCD default)
        str     r1, [r0, #DMC_DIRECTCMD]


// 	    ldr     r1, =0x00010400                         @chip0 EMRS1 (OCD exit)
	    ldr     r1, =0x00010402                         @chip0 EMRS1 (OCD exit)  Reduced Strength
//      ldr     r1, =0x00010000                         @chip0 EMRS1 (OCD exit)  ODT Disabled
        str     r1, [r0, #DMC_DIRECTCMD]


/* Direct Command for LPDDR  - END */
 
	ldr     r1, =0x00FF20B0			@ConControl auto refresh on
        str     r1, [r0, #DMC_CONCONTROL]

#if 0
        ldr     r1, =0x001000FF			@ PwrdnConfig
        str     r1, [r0, #DMC_PWRDNCONFIG]
#endif

        ldr     r1, =0x00212413		        @ MemControl
        str     r1, [r0, #DMC_MEMCONTROL]

        b	exit_cpu_init


onenand_pop:
	ldr	r1, =0x50101000				@Phycontrol0 DLL parameter setting
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0x000000F4				@Phycontrol1 DLL parameter setting
	str	r1, [r0, #DMC_PHYCONTROL1]

	ldr	r1, =0x00000000				@Phycontrol2 DLL parameter setting
	str	r1, [r0, #DMC_PHYCONTROL2]

	ldr	r1, =0x50101002				@Dll on
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0x50101003				@dll start
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0x50101003				@Force Value locking
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0x50101001				@Dll off
	str	r1, [r0, #DMC_PHYCONTROL0]

	ldr	r1, =0xFF001010				@auto refresh off
	str	r1, [r0, #DMC_CONCONTROL]

	ldr	r1, =0x00212100				@Dll off
	str	r1, [r0, #DMC_MEMCONTROL]

@;	ldr	r1, =0x28F80222
	ldr	r1, =0x28F00222
	str	r1, [r0, #DMC_MEMCONFIG0]

	ldr	r1, =0x20F80222
	str	r1, [r0, #DMC_MEMCONFIG1]

	ldr	r1, =0x20000000
	str	r1, [r0, #DMC_PRECHCONFIG]

	ldr	r1, =0x0000050E
	str	r1, [r0, #DMC_TIMINGAREF]

	ldr	r1, =0x0C233287				@TimingRow	@133MHz
	str	r1, [r0, #DMC_TIMINGROW]

	ldr	r1, =0x32330303
	str	r1, [r0, #DMC_TIMINGDATA]

	ldr	r1, =0x04141433				@Timing Power
	str	r1, [r0, #DMC_TIMINGPOWER]

	ldr	r1, =0x07000000				@chip0 Deselect
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x01000000				@chip0 PALL
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x05000000				@chip0 REFA
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x05000000				@chip0 REFA
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00000032				@chip0 MRS
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x07100000				@chip1 Deselect
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x01100000				@chip1 PALL
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x05100000				@chip1 REFA
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x05100000				@chip1 REFA
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0x00100032				@chip1 MRS
	str	r1, [r0, #DMC_DIRECTCMD]

	ldr	r1, =0xFF002030				@ConControl auto refresh on
	str	r1, [r0, #DMC_CONCONTROL]

	ldr	r1, =0x00100002				@PwrdnConfig
	str	r1, [r0, #DMC_PWRDNCONFIG]

@;	ldr	r1, =0xFF212113				@MemControl
	ldr	r1, =0xFF212100				@MemControl
	str	r1, [r0, #DMC_MEMCONTROL]

	b	exit_cpu_init

exit_cpu_init:
	mov	pc, lr

文件nand.c:

//#define MEM_SYS_CFG     (*((volatile unsigned long *)0x7E00F120))
#define NFCONF          (*((volatile unsigned long *)0xE7200000))
#define NFCONT          (*((volatile unsigned long *)0xE7200004))
#define NFCMMD          (*((volatile unsigned long *)0xE7200008))
#define NFADDR          (*((volatile unsigned long *)0xE720000C))
#define NFDATA          (*((volatile unsigned char *)0xE7200010))
#define NFSTAT          (*((volatile unsigned long *)0xE7200028))

void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len);

void copy_code_to_sdram(unsigned int src, unsigned int dest, unsigned int 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     7
#define TWRPH0    7
#define TWRPH1    7
  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 / 2048;
  //unsigned int colunm = addr & (2048 - 1);
  unsigned int colunm = addr % 2048;
  volatile int i;
  /* 这两个地址表示从页内哪里开始 */
  nand_addr(colunm & 0xff);
  for (i = 0; i < 10; i++);
  nand_addr((colunm >> 8) & 0xff);
  for (i = 0; i < 10; i++);
  /* 下面三个地址表示哪一页 */
  nand_addr(page & 0xff);
  for (i = 0; i < 10; i++);
  nand_addr((page >> 8) & 0xff);
  for (i = 0; i < 10; i++);
  nand_addr((page >> 16) & 0xff);
  for (i = 0; i < 10; i++);
#else
  nand_addr(addr & 0xff);         /* a0~a7 */
  nand_addr((addr >> 8) & 0x0f);   /* 程序的角度: a8~a11 */

  nand_addr((addr >> 12) & 0xff); /* 程序的角度: a12~a19 */
  nand_addr((addr >> 20) & 0xff); /* 程序的角度: a20~a27 */
  nand_addr((addr >> 28) & 0x7); /* 程序的角度: a28 ~a30 */
  
#endif
}

void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
  unsigned int addr = nand_start;
  int i = nand_start % 2048;
  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处开始读
      for (; i < (2048-left) && count < len; i++)//从某页的i处开始读
	{
	  data = nand_get_data();
	  /*(addr<16384)//前4页每次只能写2K
	    {
	      if(i<(2048-left))
		{
		  dest[count++] = data;
		}
	    }
	  else
	    {
	      dest[count++] = data;
	      }*/
	  dest[count++] = data;
	  addr++;
	}

      i = 0;
      left = i;
    }

  /* 取消片选 */
  nand_deselect();
  // return 0;
}

void nand_erase_block(unsigned long addr)
{
  int page = addr / 2048;
  
  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 % 2048;
  //int left = i;
  
  nand_select();
  while (count < len)
    {
      nand_cmd(0x80);
      nand_send_addr(addr);
      //for (; i < (2048-left) && count < len; i++)
      for (; i < 2048 && 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();
  
}
文件main.c:

#include "lib.h"
#define GPH1CON (*(volatile unsigned int *)0xe0300C20)
#define GPH1DAT (*(volatile unsigned int *)0xe0300c24)

extern void nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len);
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_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 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 update_program(void)
{
  unsigned char *buf = (unsigned char *)0x22000000;
  //unsigned char *buf = (unsigned char *)0xD0036000;
  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 *)0x22000000;
  //unsigned char *buf = (unsigned char *)0xD0036000;
  unsigned long len = 0;
  int have_begin = 0;
  int nodata_time = 0;
  void (*theProgram)(void);
  int i;
  /* 璇讳覆鍙h幏寰楁暟鎹?*/
  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 == 10000)
	{
	  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 0x22000000 to run it\n\r");
  
  theProgram = (void (*)(void))0x22000000;

  theProgram();
}

int main()
{
  char c;
  volatile unsigned long *mem = (volatile unsigned long *)0x22000000;
  volatile unsigned long *tmem = (volatile unsigned long *)0x21000010;
  volatile unsigned long *tsram = (volatile unsigned long *)0xD0034010;

  printf("\n\r[0x22000000] = %x\n\r",*mem);
  printf("[0x21000010] = %x\n\r",*tmem);
  printf("[0xD0034010] = %x\n\r",*tsram);

  printf("\n\r********************************\n\r");
  printf("        The board:CES-100(s5pc100)\n\r");
  printf("        The NAND:K9K8G08U0B %dMB\n\r",1024);
  printf("           The DDR:K4T1G164QQ-HCE6\n\r");
  printf("                 The NET:DM9000CEP\n\r");
  printf("                 date: %d,.%d,.%d \n\r",2013,4,25);
  printf("***********************************\n\r");

  while (1)
    {
      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(0x22000000), 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':
	  {
	    //volatile unsigned long *mcode = (volatile unsigned long *)0x21000010;
	    void (*theProgram)(void);
	    //printf("the 0x21000010 value:%x\n\r",*mcode);
	    theProgram = (void (*)(void))0xD0034010;
	    theProgram();

	    break;
	  }
	
	}
    }

  return 0;
}
文件uart.c:

#define ULCON0     (*((volatile unsigned long *)0xEC000000))
#define UCON0      (*((volatile unsigned long *)0xEC000004))
#define UFCON0     (*((volatile unsigned long *)0xEC000008))
#define UMCON0     (*((volatile unsigned long *)0xEC00000C))
#define UTRSTAT0   (*((volatile unsigned long *)0xEC000010))
#define UFSTAT0    (*((volatile unsigned long *)0xEC000018))
#define UTXH0      (*((volatile unsigned char *)0xEC000020))
#define URXH0      (*((volatile unsigned char *)0xEC000024))
#define UBRDIV0    (*((volatile unsigned long *)0xEC000028))
#define UDIVSLOT0  (*((volatile unsigned long *)0xEC00002C))

#define GPACON     (*((volatile unsigned long *)0xE0300000))

#define ENABLE_FIFO 

void init_uart(void)
{
  GPACON &= ~0xffff;
  GPACON |= 0x2222;
  
  /* ULCON0 */
  ULCON0 = 0x3;  
  UCON0  = 0x5;  
#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 = 3;
  
  UTXH0 = 0x4f4f4f4f;
}
文件lib.c:

#define UTRSTAT0   (*((volatile unsigned long *)0xEC000010))
#define UFSTAT0    (*((volatile unsigned long *)0xEC000018))
#define UTXH0      (*((volatile unsigned char *)0xEC000020))
#define URXH0      (*((volatile unsigned char *)0xEC000024))

#define ENABLE_FIFO 
static void delay1(void)
{
  volatile int i = 10;
  while (i--);
}
unsigned char getc(void)
{
#ifdef ENABLE_FIFO
  while ((UFSTAT0 & (1<<6)) == 0 && (UFSTAT0 & 0x3f) == 0)delay1();
#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))delay1();
#else
  while ((UTRSTAT0 & (1<<2)) == 0);
#endif
  UTXH0 = c;
}

void puts(char *str)
{
  int i = 0;
  while (str[i])
    {
      putc(str[i]);
      i++;
    }
}
void test()
{
  puts("init: OK\n\r");
}
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);
    }
}

char * itoa(int a, char * buf)

{
  int num = a;
  int i = 0;
  int len = 0;
  do 
    {
      buf[i++] = num % 10 + '0';
      num /= 10;
    } while (num);

  buf[i] = '\0';
  len = i;
  for (i = 0; i < len/2; i++)
    {
      char tmp;
      tmp = buf[i];
      buf[i] = buf[len-i-1];
      buf[len-i-1] = tmp;
    }
  return buf;
}

typedef int * va_list;
#define va_start(ap, A)(ap = (int *)&(A) + 1)
#define va_arg(ap, T)(*(T *)ap++)
#define va_end(ap)((void)0)

int printf(const char * format, ...)
{
  char c;
  va_list ap;
  va_start(ap, format);

  while ((c = *format++) != '\0')
    {
      switch (c)
	{
	case '%':
	  c = *format++;
	  
	  switch (c)
	    {
	      char ch;
	      char * p;
	      int a;
	      char buf[100];
	   
	    case 'c':
	      ch = va_arg(ap, int);
	      putc(ch);
	      break;
	    case 's':
	      p = va_arg(ap, char *);
	      puts(p);
	      break;
	    case 'x':
	      a = va_arg(ap, int);
	      puthex(a);
	      break;
	    case 'd':
	      a = va_arg(ap, int);
	      itoa(a, buf);
	      puts(buf);
	      break;	    
	    default:

	      break;
	    }
	  break;
	 
	default:
	  putc(c);
	  break;
	}
    }
  return 0;
}
文件lib.h:

unsigned char getc(void);
int getc_nowait(unsigned char *pChar);
void putc(char c);
void puts(char *str);
//int puts(const char * s);
void test();
void puthex(unsigned int val);
//void puthex(int a);
void putbyte(unsigned char val);
char * itoa(int a, char * buf);
int printf(const char * format, ...);
文件Makefile:

update.bin:start.S clock.S cpu_init.S nand.c main.c uart.c lib.c
	arm-linux-gcc -c start.S -o start.o
	arm-linux-gcc -c clock.S -o clock.o
	arm-linux-gcc -c cpu_init.S -o cpu_init.o 
	arm-linux-gcc -c main.c -o main.o
	arm-linux-gcc -c nand.c -o nand.o
	arm-linux-gcc -c uart.c -o uart.o
	arm-linux-gcc -c lib.c -o lib.o	
	arm-linux-ld -T bootloader.lds start.o clock.o cpu_init.o nand.o main.o uart.o lib.o -o update_elf
	arm-linux-objcopy -O binary -S update_elf update.bin
clean:
	rm -rf *.o *.bin update_elf *.dis

二、编译源代码

change@change:~$ cd Si/s5pc100/update/

change@change:~/Si/s5pc100/update$ make
arm-linux-gcc -c start.S -o start.o
arm-linux-gcc -c clock.S -o clock.o
arm-linux-gcc -c cpu_init.S -o cpu_init.o 
arm-linux-gcc -c main.c -o main.o
In file included from main.c:1:
lib.h:4: warning: conflicting types for built-in function 'putc'
lib.h:5: warning: conflicting types for built-in function 'puts'
main.c: In function 'nand_read_test':
main.c:66: warning: passing argument 2 of 'nand_read' makes integer from pointer without a cast
arm-linux-gcc -c nand.c -o nand.o
arm-linux-gcc -c uart.c -o uart.o
uart.c: In function 'init_uart':
uart.c:45: warning: large integer implicitly truncated to unsigned type
arm-linux-gcc -c lib.c -o lib.o
lib.c:40: warning: conflicting types for built-in function 'putc'
lib.c:50: warning: conflicting types for built-in function 'puts'
arm-linux-ld -T bootloader.lds start.o clock.o cpu_init.o nand.o main.o uart.o lib.o -o update_elf
arm-linux-objcopy -O binary -S update_elf update.bin
change@change:~/Si/s5pc100/update$ ./mktiny210spl.exe update.bin updates.bin

change@change:~/Si/s5pc100/update$ cp updates.bin /home/change/work/tftpboot/

三、烧写、测试

通过单板已有u-boot烧写程序,系统从NAND启动上电:

OK


U-Boot 1.3.4-dirty (Nov 19 2012 - 10:50:02) for CES-C100


************************************************************
**                 CES-C100 Nand boot                     **
**    Shenzhen Haitianxiong Electronic Co.,Ltd.(China)    **
**              http://www.ces-tech.com                   **
************************************************************


CPU:     S5PC100@834MHz
         Fclk = 1668MHz, Hclk = 166MHz, Pclk = 66MHz, Serial = PCLK 
Board:   CES-C100
I2C:   ready
VGA:   OK
DRAM:    256 MB
Net:  DM9000cep
NAND:    s3c_nand_oob_slc_64 is selected1024 MB 
*** Warning - using default environment


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


##### s5pc100 Bootloader for OpenJTAG #####
[n] Download u-boot to Nand Flash
[o] Download u-boot to Nor 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] Read the Nand Flash
[w] Write the nand flash
[e] Erase one nand block
[s] Set the boot parameters
[b] Boot the system
[r] Reboot u-boot
[q] Quit from menu
Enter your selection: q
CES-C100 # set ipaddr 172.16.1.133
CES-C100 # set gatewayip 172.16.1.1
CES-C100 # set serverip 172.16.1.135
CES-C100 # ping 172.16.1.135
ERROR: resetting DM9000 -> not responding
dm9000 i/o: 0x88000000, id: 0x90000a46 
DM9000: running in 16 bit mode
MAC: 00:40:5c:26:0a:5b
operating at 100M full duplex mode
host 172.16.1.135 is alive
CES-C100 # tftp 0x22000000 updates.bin
ERROR: resetting DM9000 -> not responding
dm9000 i/o: 0x88000000, id: 0x90000a46 
DM9000: running in 16 bit mode
MAC: 00:40:5c:26:0a:5b
operating at 100M full duplex mode
TFTP from server 172.16.1.135; our IP address is 172.16.1.133
Filename 'updates.bin'.
Load address: 0x22000000
Loading: ##
done
Bytes transferred = 24576 (0x6000)
CES-C100 # nand erase 0 0x40000


NAND erase: device 0 offset 0x0, size 0x40000
Erasing at 0x20000 -- 100% complete.
OK
CES-C100 # nand write 0x22000000 0 0x40000


NAND write: device 0 offset 0x0, size 0x40000
 262144 bytes written: OK
CES-C100 # 

烧写完毕,单板接着断电重启,设置串口com0 115200 8 n 1,串口输出如下:

O[0x22000000] = 0xFFFFFFFF
[0x21000010] = 0xE59F005C
[0xD0034010] = 0xE59F005C


********************************
       The board:CES-100(s5pc100)
        The NAND:K9K8G08U0B 1024MB
         The DDR:K4T1G164QQ-HCE6
          The NET:DM9000CEP
                  date: 2013,.4,.25 
***********************************
[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(0x22000000), run it
[s] reset the programe
Please enter the chose:

接着选择相应选型即可,均通过测试OK。eg:

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

注:update更新程序是通过v2.2.exe或者gtkterm传送文件到单板内存,再从单板内存写到NAND Flash。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值