According to the previous sdram code, the startup code turns off the watchdog, initializes the storage controller (mainly Norflash of BANK0 and SDRAM of BANK6), sets the stack to the highest address of SDRAM, and takes the data of the text segment directly from Norflash.
The code is as follows:
head.S
@*************************************************************************
@ File:head.S
@ Function: Set up SDRAM, set the stack to SDRAM, and then continue execution
@*************************************************************************
.equMEM_CTL_BASE, 0x48000000
.equSDRAM_BASE, 0x30000000
.text
.global _start
_start:
b reset
reset:
bl disable_watch_dog @ Disable WATCHDOG, otherwise the CPU will restart continuously
bl memsetup@ Set up the memory controller
ldr sp, =0x34000000 @ Set up the stack
bl main
halt_loop:
b halt_loop
disable_watch_dog:
@ Write 0 to the WATCHDOG register
move r1, #0x53000000
mov r2, #0x0
str r2, [r1]
mov pc, lr @ return
memsetup:
@ Set up the memory controller to use peripherals such as SDRAM
mov r1, #MEM_CTL_BASE @ The starting address of the 13 registers of the storage controller
adrlr2, mem_cfg_val @ The starting storage address of these 13 values
add r3, r1, #52 @ 13*4 = 54
@ Write the memory control unit's SDRAM initialization parameters to the registers in sequence
str_loop:
ldr r4, [r2], #4@ Read the setting value and add 4 to r2
str r4, [r1], #4@ Write this value to the register and add 4 to r1
cmp r1, r3 @ Determine whether all 13 registers have been set
bne str_loop@ If not written, continue
mov pc, lr @ return
.align 4
mem_cfg_val:
@ Storage controller 13 register settings
.long 0x22011110 @ BWSCON
.long 0x00000700 @ BANKCON0
.long 0x00000700 @ BANKCON1
.long 0x00000700 @ BANKCON2
.long 0x00000700 @ BANKCON3
.long 0x00000700 @ BANKCON4
.long 0x00000700 @ BANKCON5
.long 0x00018005 @ BANKCON6
.long 0x00018005 @ BANKCON7
.long 0x008C07A3 @ REFRESH
.long 0x000000B1 @ BANKSIZE
.long 0x00000030 @ MRSRB6
.long 0x00000030 @ MRSRB7
nand.c
#define LARGER_NAND_PAGE
#define GSTATUS1 (*(volatile unsigned int *)0x560000B0)
#define BUSY 1
#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
#define NAND_SECTOR_SIZE_LP 2048
#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1)
typedef unsigned int S3C24X0_REG32;
/* NAND FLASH (see S3C2410 manual chapter 6) */
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFECC;
} S3C2410_NAND;
/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */
typedef struct {
S3C24X0_REG32 NFCONF;
S3C24X0_REG32 NFCONT;
S3C24X0_REG32 NFCMD;
S3C24X0_REG32 NFADDR;
S3C24X0_REG32 NFDATA;
S3C24X0_REG32 NFMECCD0;
S3C24X0_REG32 NFMECCD1;
S3C24X0_REG32 NFSECCD;
S3C24X0_REG32 NFSTAT;
S3C24X0_REG32 NFESTAT0;
S3C24X0_REG32 NFESTAT1;
S3C24X0_REG32 NFMECC0;
S3C24X0_REG32 NFMECC1;
S3C24X0_REG32 NFSECC;
S3C24X0_REG32 NFSBLK;
S3C24X0_REG32 NFEBLK;
} S3C2440_NAND;
typedef struct {
void (*nand_reset)(void);
void (*wait_idle)(void);
void (*nand_select_chip)(void);
void (*nand_deselect_chip)(void);
void (*write_cmd)(int cmd);
void (*write_addr)(unsigned int addr);
unsigned char (*read_data)(void);
}t_nand_chip;
static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
static t_nand_chip nand_chip;
/* Function for external calls*/
void nand_init(void);
void nand_read(unsigned char *buf, unsigned long start_addr, int size);
/* The total entry for NAND Flash operations, which will call the corresponding functions of S3C2440*/
static void nand_reset(void);
static void wait_idle(void);
static void nand_select_chip(void);
static void nand_deselect_chip(void);
static void write_cmd(int cmd);
static void write_addr(unsigned int addr);
static unsigned char read_data(void);
/* S3C2440 NAND Flash processing function*/
static void s3c2440_nand_reset(void);
static void s3c2440_wait_idle(void);
static void s3c2440_nand_select_chip(void);
static void s3c2440_nand_deselect_chip(void);
static void s3c2440_write_cmd(int cmd);
static void s3c2440_write_addr(unsigned int addr);
static unsigned char s3c2440_read_data(void);
/* S3C2440 NAND Flash operation function*/
/* Reset */
static void s3c2440_nand_reset(void)
{
s3c2440_nand_select_chip();
s3c2440_write_cmd(0xff); // reset command
s3c2440_wait_idle();
s3c2440_nand_deselect_chip();
}
/* Wait for NAND Flash to be ready */
static void s3c2440_wait_idle(void)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
while(!(*p & BUSY))
for(i=0; i<10; i++);
}
/* Send chip select signal */
static void s3c2440_nand_select_chip(void)
{
int i;
s3c2440nand->NFCONT &= ~(1<<1);
for(i=0; i<10; i++);
}
/* Cancel chip select signal*/
static void s3c2440_nand_deselect_chip(void)
{
s3c2440nand->NFCONT |= (1<<1);
}
/* Issue a command */
static void s3c2440_write_cmd(int cmd)
{
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
*p = cmd;
}
/* Sending address */
static void s3c2440_write_addr(unsigned int addr)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
*p = addr & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 9) & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 17) & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 25) & 0xff;
for(i=0; i<10; i++);
}
static void s3c2440_write_addr_lp(unsigned int addr)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
int col, page;
col = addr & NAND_BLOCK_MASK_LP;
page = addr / NAND_SECTOR_SIZE_LP;
*p = col & 0xff; /* Column Address A0~A7 */
for(i=0; i<10; i++);
*p = (col >> 8) & 0x0f; /* Column Address A8~A11 */
for(i=0; i<10; i++);
*p = page & 0xff; /* Row Address A12~A19 */
for(i=0; i<10; i++);
*p = (page >> 8) & 0xff; /* Row Address A20~A27 */
for(i=0; i<10; i++);
*p = (page >> 16) & 0x03; /* Row Address A28~A29 */
for(i=0; i<10; i++);
}
/* Read data */
static unsigned char s3c2440_read_data(void)
{
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
return *p;
}
/* Reset NAND Flash before using it for the first time */
static void nand_reset(void)
{
nand_chip.nand_reset();
}
static void wait_idle(void)
{
nand_chip.wait_idle();
}
static void nand_select_chip(void)
{
int i;
nand_chip.nand_select_chip();
for(i=0; i<10; i++);
}
static void nand_deselect_chip(void)
{
nand_chip.nand_deselect_chip();
}
static void write_cmd(int cmd)
{
nand_chip.write_cmd(cmd);
}
static void write_addr(unsigned int addr)
{
nand_chip.write_addr(addr);
}
static unsigned char read_data(void)
{
return nand_chip.read_data();
}
/* Initialize NAND Flash */
void nand_init(void)
{
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
nand_chip.nand_reset = s3c2440_nand_reset;
nand_chip.wait_idle = s3c2440_wait_idle;
nand_chip.nand_select_chip = s3c2440_nand_select_chip;
nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
nand_chip.write_cmd = s3c2440_write_cmd;
#ifdef LARGER_NAND_PAGE
nand_chip.write_addr = s3c2440_write_addr_lp;
#else
nand_chip.write_addr = s3c2440_write_addr;
#endif
nand_chip.read_data = s3c2440_read_data;
/* Set timing */
s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* Enable NAND Flash controller, initialize ECC, disable chip select*/
s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
/* Reset NAND Flash */
nand_reset();
}
/* Read function */
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
#ifdef LARGER_NAND_PAGE
if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
return ; /* Address or length is not aligned */
}
#else
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return ; /* Address or length is not aligned */
}
#endif
/* Select chip */
nand_select_chip();
for(i=start_addr; i < (start_addr + size);) {
/* Issue READ0 command */
write_cmd(0);
/* Write Address */
write_addr(i);
#ifdef LARGER_NAND_PAGE
write_cmd(0x30);
#endif
wait_idle();
#ifdef LARGER_NAND_PAGE
for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
#else
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
#endif
*buf = read_data();
buf++;
}
}
/* Cancel chip select signal*/
nand_deselect_chip();
return ;
}
int main(void)
{
unsigned int buffer;
unsigned long nandPtr = 0x00000000;
nand_init();
while(1)
{
nand_read((unsigned char *)&buffer, nandPtr, 4);
nandPtr = nandPtr + 4;
}
return 0;
}
Makefile
CROSS_TOOLCHAIN := arm-linux
nand.bin : head.S nand.c
$(CROSS_TOOLCHAIN)-gcc -g -nostdlib -c -o head.o head.S
$(CROSS_TOOLCHAIN)-gcc -g -nostdlib -c -o nand.o nand.c
$(CROSS_TOOLCHAIN)-ld -Ttext 0x00000000 head.o nand.o -o nand_elf
$(CROSS_TOOLCHAIN)-objcopy -O binary -S nand_elf nand.bin
Previous article:About the use of 128M memory in ARM9 S3C2440 wince6.0
Next article:Embedded bare-metal development using the GNU toolchain
Recommended ReadingLatest update time:2024-11-15 07:32
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Basic principles and driving waveforms of BLDC six-step commutation method
- [Xianji HPM6750EVKMINI Review] 5# HPM6750 Camera Usage
- MSP430FR604x, MSP430FR504x for Air and Water Flow Metering Applications Datasheet
- I think this is Japanese anime——【Electronic comic series】
- Overview of three types of losses and four effects of wireless signal transmission and technology
- Xiaomi Constant Temperature Kettle Repair Notes
- [Xianji HPM6750 Review] Running the Edge AI Framework - TFLM Benchmark
- Analysis of capacitor filtering and EMC rectification suggestions
- Verilog HDL models at different abstraction levels.pdf
- Asking for advice: How to deal with the bit error rate when using usart to RS485 for Huada chip HC32F460?