S5PV210的NandFlash应用(一)
发布时间:2020-12-15 18:06:53 所属栏目:百科 来源:网络整理
导读:准备分析 ? ? ? ? 标题挂了一个(一),代表这个是涉及到NandFlash并不深入,只实现读操作。还是16k的代码,这次从NandFlash中读取,读到iRAM中地址为 0xD0024000 的地方。并调用main运行。如下图所示:( CPU会自动把B区代码拷贝到A区,我用A区代码从将B区
准备分析
资源工具
? ? ? ? 同《?
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,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,#(0x3<<8) str r1,#MP01CON_OFFSET] ldr r1,#MP01PUD_OFFSET] bic r1,#(0x3<<4) str r1,#MP01PUD_OFFSET] ldr r1,#MP03CON_OFFSET] bic r1,#0xFFFFFF ldr r2,=0x22222222 orr r1,r2 str r1,#MP03CON_OFFSET] ldr r1,#MP03PUD_OFFSET] ldr r2,=0x3fff bic r1,#MP03PUD_OFFSET] ldr r0,=ELFIN_NAND_BASE ldr r1,#NFCONF_OFFSET] ldr r2,=0x777F bic r1,r2 ldr r2,=NFCONF_VAL orr r1,#NFCONF_OFFSET] ldr r1,#NFCONT_OFFSET] ldr r2,=0x707C7 bic r1,=NFCONT_VAL orr r1,#NFCONT_OFFSET] ldr r1,#NFCONF_OFFSET] orr r1,#0x70 orr r1,#0x7700 str r1,#NFCONT_OFFSET] orr r1,#0x03 str r1,#NFCONT_OFFSET] mov pc,lrmain.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.无
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |