S5PV210的NandFlash应用(一)

准备分析

        标题挂了一个(一),代表这个是涉及到NandFlash并不深入,只实现读操作。还是16k的代码,这次从NandFlash中读取,读到iRAM中地址为 0xD0024000 的地方。并调用main运行。如下图所示:(CPU会自动把B区代码拷贝到A区,我用A区代码从将B区代码拷贝到C区,并调用main运行
        
资源工具

        同《  S5PV210的LED应用(一)
        NandFlash: K9GAG08U0F (2G)

着手写程序
        start.S中的代码拷贝很重要,Makefile中的链接地址很重要。

/*
 * $Id: nand_cp.c,v 1.1 2008/11/20 01:08:36 boyko Exp $
 *
 * (C) Copyright 2006 Samsung Electronics
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*
 * You must make sure that all functions in this file are designed
 * to load only U-Boot image.
 *
 * So, DO NOT USE in common read.
 *
 * By scsuh.
 */


/*
 * Standard NAND flash commands
 */
#define NAND_CMD_READ0		0
#define NAND_CMD_READ1		1
#define NAND_CMD_RNDOUT		5
#define NAND_CMD_PAGEPROG	0x10
#define NAND_CMD_READOOB	0x50
#define NAND_CMD_ERASE1		0x60
#define NAND_CMD_STATUS		0x70
#define NAND_CMD_STATUS_MULTI	0x71
#define NAND_CMD_SEQIN		0x80
#define NAND_CMD_RNDIN		0x85
#define NAND_CMD_READID		0x90
#define NAND_CMD_PARAM		0xec
#define NAND_CMD_ERASE2		0xd0
#define NAND_CMD_RESET		0xff

/* Extended commands for large page devices */
#define NAND_CMD_READSTART	0x30
#define NAND_CMD_RNDOUTSTART	0xE0
#define NAND_CMD_CACHEDPROG	0x15

#define NAND_DISABLE_CE()	(NFCONT_REG |= (1 << 1))
#define NAND_ENABLE_CE()	(NFCONT_REG &= ~(1 << 1))
#define NF_TRANSRnB()		do { while(!(NFSTAT_REG & (1 << 0))); } while(0)

//#include <asm/io.h>
//#include <linux/mtd/nand.h>
#include "s5pc110.h"
#define	COPY_BL2_SIZE		0x80000

#define NAND_CONTROL_ENABLE()	(NFCONT_REG |= (1 << 0))

/*
 * address format
 *              17 16         9 8            0
 * --------------------------------------------
 * | block(12bit) | page(5bit) | offset(9bit) |
 * --------------------------------------------
 */

static int nandll_read_page (uchar *buf, ulong addr, int large_block)
{
	int i;
	int page_size = 512;

	if (1 == large_block)
		page_size = 2048;
		
	else if (2 == large_block)
		page_size = 8192;

	NAND_ENABLE_CE();

	NFCMD_REG = NAND_CMD_READ0;

	/* Write Address */
	NFADDR_REG = 0;

	if (large_block)
		NFADDR_REG = 0;

	NFADDR_REG = (addr) & 0xff;
	NFADDR_REG = (addr >> 8) & 0xff;
	NFADDR_REG = (addr >> 16) & 0xff;

	if (large_block)
		NFCMD_REG = NAND_CMD_READSTART;

        NF_TRANSRnB();

	/* for compatibility(2460). u32 cannot be used. by scsuh */
	for(i=0; i < page_size; i++) {
                *buf++ = NFDATA8_REG;
        }

        NAND_DISABLE_CE();
        return 0;
}

/*
 * Read data from NAND.
 */
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
{
	uchar *buf = (uchar *)dst_addr;
	int i;
	uint page_shift = 9;

	if (1 == large_block)
	{
		page_shift = 11;
	
		/* Read pages */
		for (i = (0x6000>>page_shift); i < (size>>page_shift); i++, buf+=(1<<page_shift)) 
		{
			nandll_read_page(buf, i, large_block);
		}
	}
	else if(2 == large_block)
	{
		page_shift = 12;
		for (i = 0; i < (size>>page_shift); i++, buf+=(1<<(page_shift-1))) 
		{
		        nandll_read_page(buf, i, large_block);
		}
	}
        
	return 0;
}

int copy_uboot_to_ram_nand (void)
{
	int large_block = 0;
	int i;
	vu_char id;

	NAND_CONTROL_ENABLE();
        NAND_ENABLE_CE();
        NFCMD_REG = NAND_CMD_READID;
        NFADDR_REG =  0x00;

	/* wait for a while */
        for (i=0; i<200; i++);
	id = NFDATA8_REG;
	id = NFDATA8_REG;

	if (id > 0x80)
		large_block = 1;
		
	if(id == 0xd5)
	{
		large_block = 2;
	}

	/* read NAND Block.
	 * 128KB ->240KB because of U-Boot size increase. by scsuh
	 * So, read 0x3c000 bytes not 0x20000(128KB).
	 */
	//return nandll_read_blocks(CONFIG_SYS_TEXT_BASE, COPY_BL2_SIZE, large_block);
	return nandll_read_blocks(0xd0024000, 0x4000, large_block);
}
void board_init_f_nand(unsigned long bootflag)
{
        __attribute__((noreturn)) void (*uboot)(void);
        copy_uboot_to_ram_nand();

        /* Jump to U-Boot image */
        uboot = (void *)0xd024010;
	(*uboot)();
        /* Never returns Here */
}
@******************************************************************************
@ File:start.S
@ 功能:启动代码,设置栈,拷贝16k到0xd0020000处
@******************************************************************************  
.text

.global _start

_start:
	
	ldr	sp, =0xD0037D80       @ 设置栈,以便调用c函数						
	
	adr r0, _start  		      @ 重定位	
                            @ _start当前所位于的地址:0xd0020010 (前边放有16bit的头信息)
	
	ldr r1, =_start           @ _start的链接地址:0xd0024010 	
	
	ldr r2, =0xd0028000       @ 0xd0028000 = 0xd0024000 + 0x4000(16k) 
	cmp r0, r1
	beq run_on_dram

	bl  nand_asm_init
	bl  copy_uboot_to_ram_nand

	
run_on_dram:			 
	ldr pc, =main             @ 跳转		


halt:
	b halt


led_debug:     
	ldr     R0,=0xE0200280      @ R0设为GPJ2CON寄存器。此寄存器
                                        @ 用于选择端口J各引脚的功能:
                                        @ 是输出、是输入、还是其他
	mov     R1,#0x00000001        
	str     R1,[R0]             @ 设置GPJ2_0为输出口, 位[10:9]=0b01
	ldr     R0,=0xE0200284      @ R0设为GPJ2DAT寄存器。此寄存器
                                        @ 用于读/写端口GPJ2各引脚的数据
	mov     R1,#0x00000000      @ 此值改为0x00000001,
                                        @ 可让LED1熄灭
	str     R1,[R0]             @ GPJ2_0输出0,LED1点亮
	mov pc, lr



	/* Setting GPIO for NAND */
	/* This setting is NAND initialze code at booting time in iROM. */
	
nand_asm_init:
	
/*
 * Nand Interface Init for SMDKC110
 */
 
#define ELFIN_GPIO_BASE			0xE0200000 
#define ELFIN_NAND_BASE			0xB0E00000
#define NFCONF_VAL	(7<<12)|(7<<8)|(7<<4)|(0<<3)|(0<<2)|(1<<1)|(0<<0)
#define NFCONT_VAL      (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x2<<1)|(1<<0)

#define MP01CON_OFFSET 			0x2E0
#define MP01PUD_OFFSET 			0x2E8
#define MP03CON_OFFSET      0x320
#define MP03PUD_OFFSET      0x328
#define NFCONF_OFFSET       0x00
#define NFCONT_OFFSET       0x04
 

	ldr	r0, =ELFIN_GPIO_BASE

	ldr	r1, [r0, #MP01CON_OFFSET]
	bic	r1, r1, #(0xf<<8)
	orr	r1, r1, #(0x3<<8)
	str	r1, [r0, #MP01CON_OFFSET]

	ldr	r1, [r0, #MP01PUD_OFFSET]
	bic	r1, r1, #(0x3<<4)
	str	r1, [r0, #MP01PUD_OFFSET]

	ldr	r1, [r0, #MP03CON_OFFSET]
	bic	r1, r1, #0xFFFFFF
	ldr	r2, =0x22222222
	orr	r1, r1, r2
	str	r1, [r0, #MP03CON_OFFSET]

	ldr	r1, [r0, #MP03PUD_OFFSET]
	ldr	r2, =0x3fff
	bic	r1, r1, r2
	str	r1, [r0, #MP03PUD_OFFSET]

	ldr	r0, =ELFIN_NAND_BASE

	ldr	r1, [r0, #NFCONF_OFFSET]
	ldr	r2, =0x777F
	bic	r1, r1, r2
	ldr	r2, =NFCONF_VAL
	orr	r1, r1, r2
	str	r1, [r0, #NFCONF_OFFSET]

	ldr	r1, [r0, #NFCONT_OFFSET]
	ldr	r2, =0x707C7
	bic	r1, r1, r2
	ldr	r2, =NFCONT_VAL
	orr	r1, r1, r2
	str	r1, [r0, #NFCONT_OFFSET]

	ldr	r1, [r0, #NFCONF_OFFSET]
	orr	r1, r1, #0x70
	orr	r1, r1, #0x7700
	str     r1, [r0, #NFCONF_OFFSET]

	ldr	r1, [r0, #NFCONT_OFFSET]
	orr	r1, r1, #0x03
	str     r1, [r0, #NFCONT_OFFSET]

	mov	pc, lr
main.c
#define 	GPJ2CON 	(*(volatile unsigned long *) 0xE0200280)
#define 	GPJ2DAT		(*(volatile unsigned long *) 0xE0200284)

// 延时函数
void delay(unsigned long count)
{
	volatile unsigned long i = count;
	while (i--)
		;
}

void main()				//LED 闪烁
{
	GPJ2CON = 0x00001111;		// 配置引脚
	while(1)					// 闪烁
	{
		GPJ2DAT = 0;			// LED on
		delay(0x100000);
		GPJ2DAT = 0xf;			// LED off
		delay(0x100000);
	}
}

下载运行

        同《  S5PV210的LED应用(一)

运行调试
       
        一开始以为程序会很难,应该MLC的,这样的NandFlash涉及到了ECC校验,颇为麻烦,但是细想,只实现读操作,会少许简单一些。最后发现读的时候问题并不多。也并不是那么困难。nand_asm_init和nand_cp.c提取于u-boot,并加以移植。

遗留问题
  
        1.无



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁保康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值