NandFlash application of S5PV210 (I)

Publisher:婉如ChanelLatest update time:2020-04-01 Source: eefocusKeywords:S5PV210 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Prepare for analysis


The title has a (I) in it, which means that this is not very deep into NandFlash, and only implements the read operation. It is still 16k code, this time reading from NandFlash, and reading the address 0xD0024000 in iRAM. And calling main to run. As shown in the figure below: (CPU will automatically copy the code in area B to area A, I use the code in area A to copy the code in area B to area C, and call main to run)

Resource Tools

Same as "LED Application of S5PV210 (I)"

NandFlash: K9GAG08U0F (2G)


Start writing the program

The code copy in start.S is very important, and the link address in Makefile is very important.


/*

 * $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

//#include

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

{

fly *buf = (fly *)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< {

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

@ Function: Start code, set up stack, copy 16k to 0xd0020000

@******************************************************************************  

.text

 

.global _start

 

_start:

ldr sp, =0xD0037D80 @ Set up the stack to call the C function

adr r0, _start @ relocation

                            @ _start is currently located at: 0xd0020010 (with 16-bit header information in front)

ldr r1, =_start @ _start link address: 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 @ Jump

 

 

halt:

b stop

 

 

led_debug:     

ldr R0,=0xE0200280 @ R0 is set to GPJ2CON register. This register

                                        @ is used to select the function of each pin of port J:

                                        @ is output, input, or something else

move R1, #0x00000001        

str R1,[R0] @ Set GPJ2_0 as output port, bit [10:9] = 0b01

ldr R0,=0xE0200284 @ R0 is set to GPJ2DAT register. This register

                                        @ Used to read/write data of each pin of port GPJ2

mov R1,#0x00000000 @ Change the value to 0x00000001,

                                        @ can turn off LED1

str R1,[R0] @ GPJ2_0 output 0, LED1 lights up

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)

 

// Delay function

void delay(unsigned long count)

{

volatile unsigned long i = count;

while (i--)

;

}

 

void main() //LED flashing

{

GPJ2CON = 0x00001111; //Configure pins

while(1) // flash

{

GPJ2DAT = 0; // LED on

delay(0x100000);

GPJ2DAT = 0xf; // LED off

delay(0x100000);

}

}


Download and run


Same as "LED Application of S5PV210 (I)"


Run Debug

       

At first I thought the program would be difficult, it should be MLC, such NandFlash involves ECC verification, which is quite troublesome, but after thinking about it, it would be a little simpler to only implement the read operation. In the end I found that there were not many problems when reading. It was not that difficult. nand_asm_init and nand_cp.c were extracted from u-boot and transplanted.


Remaining problem

  

1. None


Keywords:S5PV210 Reference address:NandFlash application of S5PV210 (I)

Previous article:S5PV210 IRAM Application
Next article:NandFlash Application of S5PV210 (Part 3)

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号