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:
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 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.
Previous article:S3C2440 old version uboot relocation analysis
Next article:ARM-GCC has compilation errors for function pointer calls? [The cause has been found]
- Popular Resources
- Popular amplifiers
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- Terminal software that supports automatic serial port search
- Last day! If you don't do this, your electric car will not be able to drive on the road
- RISC-V MCU Development (XI): Cross-core Engineering Conversion
- There is no spring that will not come
- MPLAB X display issues
- (Transfer) Overview of CC2640R2F BLE5.0 Bluetooth Protocol Stack
- Small base stations, big science!
- IP Design Specifications in the 2021 Standard for Very Large Scale Integrated Circuit (VLSI) Design Flow
- ST60 short-distance contactless 60GHz millimeter wave connector actual test
- [ST NUCLEO-H743ZI Review] Establishing a modbus/TCP slave