Read data from NAND Flash and move the code to SDRAM for execution

Publisher:素雅之韵Latest update time:2021-09-15 Source: eefocusKeywords:NAND Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Because we rely on the S3C2440 to automatically copy data from Nandflash to the on-chip SRAM for execution when it boots up, the size of our executable program cannot be larger than the 4KB limit. However, our program is very close to this limit, so we must break through this limit in order to continue development. To do this, we need to implement the code transfer function, transfer the program from Nandflash to SDRAM, and jump to SDRAM for execution.


Why doesn't this article implement NandFlash writing? Because there is no demand for our implementation yet. More importantly, the write operation involves erasure, and even more so the life of NandFlash. In order to reduce the number of writes and extend the life of NandFlash, write caching is generally implemented at the software layer. This involves a lot of code, which will deviate from the subject of our experiment - code transfer. It will not be too late to implement the write function when it is really necessary to save data to NandFlash in the future.


1 NAND Flash Basics

1.1 Basic information of TQ2440 onboard Nandflash chip

As a storage chip, NAND Flash requires specific timing and specifications for read and write operations. In fact, there are also relevant industrial standards to standardize Nand Flash read and write operations.

Unlike RAM and ROM, NAND Flash uses the same set of pins to transmit data, addresses, and commands, which are distinguished by different timings. The following figure is a diagram of the Nandflash interface on the TQ2440 development board:

Write the picture description here

Its interface is very simple.


IO0-IO7, 8 pins are used to transmit data, address, and commands.

WP, write protect, directly grounded.

WE, write enable

RE, read enable

CE, chip select

ALE, address latch

RDY/B, busy/idle status

CLE, command latch

VSS, ground

VCC, power supply


1.2 Nand flash basic terminology

Page: NandFlash reads and writes in pages. Common page sizes are 512B, 1KB, 2KB, etc.

Block (BLOCK), NandFlash must be erased (write 1) before writing data, and the smallest unit of erase is the block, and the common block size is 64 pages.


Erase. NandFlash must be erased before writing, that is, all written as 1. Because when writing, only 0 can be written, not 1.


Data bandwidth, that is, the number of bits of data transmitted each time (number of I/O pins), is commonly 8 or 16.

Address cycle, to transmit a complete address, it is necessary to send data several times.


1.3 S3C2440 on-chip NandFlash controller

(1) Hardware reading

The S3C2440 chip integrates a NandFlash controller. When booting, the page size, data width, address cycle and other factors are obtained through the hardware configuration of the external pin level, so that the NandFlash can be read to SRAM at boot time.


(2) Software reading

The S3C2440's on-chip NandFlash controller is also open to users, allowing them to read and write NandFlash using software.


2 Using the S3C2440 on-chip NandFlash controller to read NandFlash data

2.1 Related registers

NFCONF configuration register, used to set NandFlash timing

NFCONT control register, used to control chip select and other signals

GPACON pin multiplexing, GPIO and NandFlash control signal switching

NFCMD command register, automatically sends when the command is written

NFADDR address register, automatically sends when the address is written

NFDATA data register, automatically sent when data is written, automatically updated when data is read.

NFSTAT status register, detects whether NANDFLASH is busy


Other ECC related registers are used for error checking and can be temporarily unused.

For specific settings, please refer to the S3C2440 data sheet and Nandflash data sheet.


2.2 Initialization

void nand_init()

{

    rGPACON |= (0x3F << 17); /* GPIO */

    rNFCONF &= ~(3<<12 | 7<<8 | 7<<4); /* clock */

    rNFCONF |= (1<<12 | 4<<8 | 0<<4);


    rNFCONT |= 1; /* enable NF controller */

    rNFCONT &= ~(1<<1); /* Chip select */

    rNFCONT &= ~(1<<12); /* disable soft lock */


    rNFSTAT |= 1<<2; /* clear BUSY */

    nand_send_cmd(CMD_RESET);

    nand_wait();

}


2.3 Read Anywhere on Page

NandFlash generally reads in the smallest unit of page. Some NandFlash also supports single-byte reading, but it is not commonly used. We can read any size within the page by reading a page first and then selectively saving the data.


/* read [start,start+count) in a page */

int nand_read_page(unsigned char* buf, int iPage, int start, int count)

{

    nand_chip_enable();

    nand_send_cmd(CMD_PAGE_READ);

    nand_send_addr(0x00);

    nand_send_addr(0x00);

    nand_send_addr(iPage & 0xFF);

    nand_send_addr( (iPage >> 8) & 0xFF);

    nand_send_addr( (iPage >> 16) & 0x1);

    nand_send_cmd(CMD_PAGE_READ_CONFIRM);

    nand_wait();

    unsigned char * p = buf;


    int i;

    unsigned char c;

    for (i=0; i<2048; i++) {

        if ( i=start+count ) {

            c = rNFDATA8;

        }else {

            *p++ = rNFDATA8;

        }

    }

    nand_chip_disable();

    return count;

}


2.4 Full range arbitrary read

Based on the arbitrary read within the page, we can further realize arbitrary read in the entire range. The principle is as follows:

There are only two cases where any read operation involves a range:

(1) All the required data happens to belong to the same page. In this case, you can execute any read operation within the page.

(2) The required data spans two or more pages. In this case, you can perform arbitrary reads on each page in sequence. However, you may only need to read part of the data on the first and last pages, while the pages in between need to be read in full.

The implementation code is as follows:


/* read size bytes starting from addr */

int nand_read(unsigned char* buf, unsigned int addr, int size)

{

    int startPage = addr / 2048;

    int endPage = (addr+size-1) / 2048;

    int startByte = addr % 2048;

    /* if the range is in only one page */

    if (startPage == endPage) {

        return nand_read_page(buf, startPage, startByte, size);

    }


    /* if the range is across 2 or more pages */

    int n = nand_read_page(buf, startPage, startByte, 2048-startByte); /* the first page */

    int page = startPage+1;

    while (page < endPage) { /* middle page(s) */

        n += nand_read_page(buf+n, page, 0, 2048);

        page ++;

    }

    n += nand_read_page(buf+n, endPage, 0, (size-n)); /* last page */

    return n;


}


3 Code Porting

3.1 Demand Analysis

(1) The first 4KB of the program needs to complete the basic functions: CPU clock initialization, SDRAM initialization, NandFlash initialization, UART0 initialization. Then copy the entire program in NandFlash to SDRAM, and finally enable interrupts and jump to the Main function for execution.

(2) Since the MMU has not been started, the exception vector entry is located at the absolute physical address 0, which is in SRAM.

(3) The program after 4KB completes other hardware initialization.


3.2 Key technologies

3.2.1 Position-Independent Code

The first 4KB of the program is first automatically copied to SRAM by the hardware for execution, and then moved to SDRAM for execution, which requires this part to be address-independent code. Specifically:


Program jumps require the use of relative jump instructions, such as B and BL, which are relative to the current PC value and increase or decrease the appropriate offset to complete the jump.


The C language will automatically give priority to relative jump instructions based on the jump range. The jump range of our program is less than 32MB, so the C compiler will automatically generate position-independent code.


3.2.2 Absolute address jump

This is exactly the opposite of relative address jumps, absolute address jump instructions such as BX, or instructions that directly assign values ​​to PC such as mov pc, Rn, add pc, rn, rm, etc. They all force the PC to be assigned directly, thus jumping within the 4GB range.


The SRAM address space is [0x00000000, 0x00001000), while the SDRAM address range is [0x30000000, 0x34000000). Obviously, the minimum distance between the two is far beyond the range of relative jump.


Currently, the places where absolute address jumps are required are:


Jump to Main() function

Jump to exception handler

3.2.3 Control of the linking process

The functionality of the porting code needs to be in the first 4KB of the executable, which can be controlled by the linker script. Our linker script is as follows.


ENTRY(ResetEntry)

SECTIONS {

    . = 0x30000000;

    .text ALIGN(4): {

        init.o(.*)

        boot.o(.*)

        uart.o(.*)

        nand.o(.*)

        *(.text)

    }

    .data ALIGN(4): {

        *(.data)

        *(.rodata)

    }

    .bss ALIGN(4): {

        *(.bss)

    }

}


The files that need to be run in SRAM are: init.s, boot.c, and uart.c.


3.3 Source code guide

The basic process is:

(1) init.s completes CPU clock initialization, SDRAM initialization, stack initialization for each mode, and establishment of exception vector table.

(2) Then call the boot() function in boot.c, which calls the function in uart.c to complete the serial port initialization and calls the function in nand.c to complete the code transfer.

(3) Jump to the Main() function of main.c.

Keywords:NAND Reference address:Read data from NAND Flash and move the code to SDRAM for execution

Previous article:S3C2440 old version uboot relocation analysis
Next article:ARM-GCC has compilation errors for function pointer calls? [The cause has been found]

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号