历史上的今天
返回首页

历史上的今天

今天是:2025年04月01日(星期二)

正在发生

2020年04月01日 | S5PV210的NandFlash应用(一)

2020-04-01 来源:eefocus

准备分析


标题挂了一个(一),代表这个是涉及到NandFlash并不深入,只实现读操作。还是16k的代码,这次从NandFlash中读取,读到iRAM中地址为0xD0024000的地方。并调用main运行。如下图所示:(CPU会自动把B区代码拷贝到A区,我用A区代码从将B区代码拷贝到C区,并调用main运行)

资源工具

同《 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

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

{

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< {

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

@ 功能:启动代码,设置栈,拷贝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, 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)

 

// 延时函数

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.无


推荐阅读

史海拾趣

CMD公司的发展小趣事

CMD技术公司成立于1986年,当时的市场正处于计算机技术的飞速发展时期。公司初期主要聚焦于为DEC计算机系统开发SCSI主机适配器,这一决策在当时看来是富有远见的。随着个人电脑的普及,CMD的产品迅速获得了市场的认可,为后续的发展奠定了坚实的基础。

GigPeak公司的发展小趣事

在快速发展的过程中,GigPeak深刻认识到与产业链上下游企业合作的重要性。公司积极寻求与芯片制造商、设备供应商和系统集成商等合作伙伴建立长期稳定的合作关系。通过资源共享、技术交流和联合研发等方式,GigPeak与合作伙伴共同构建了一个完整的产业生态体系。这一生态体系的建立不仅提升了GigPeak的市场竞争力,还促进了整个行业的健康发展。

Ethertronics公司的发展小趣事

在快速发展的过程中,GigPeak深刻认识到与产业链上下游企业合作的重要性。公司积极寻求与芯片制造商、设备供应商和系统集成商等合作伙伴建立长期稳定的合作关系。通过资源共享、技术交流和联合研发等方式,GigPeak与合作伙伴共同构建了一个完整的产业生态体系。这一生态体系的建立不仅提升了GigPeak的市场竞争力,还促进了整个行业的健康发展。

EMS GmbH公司的发展小趣事

近年来,随着汽车行业向电动化、智能化方向发展,汽车转换器注塑件的需求也发生了变化。EMS GmbH公司积极应对行业挑战,加大研发投入,推动产品向智能化、绿色化方向转型。同时,公司还关注新兴领域的发展机会,如新能源汽车、自动驾驶等领域,寻求新的增长点。这些努力使EMS GmbH公司能够保持行业领先地位,并在未来市场中保持竞争力。

Fischer Connectors公司的发展小趣事

EMS GmbH公司自创立之初,就专注于汽车转换器注塑件(微动开关)的研发和生产。公司投入大量资源进行技术创新,逐步积累起了一系列核心专利技术。这些技术不仅涵盖了汽车转换器注塑件生产的所有关键技术,还获得了多个国际品质管理组织机构及主流整车厂的双重、三重认证。这些专利技术的积累,使EMS GmbH公司在汽车转换器注塑件领域确立了行业领先地位。

EFINIX公司的发展小趣事

为了加速Quantum™可编程加速器技术的商业化进程,EFINIX公司与中芯国际集成电路制造有限公司展开合作。中芯国际是世界领先的集成电路晶圆代工企业之一,其先进的制造能力为EFINIX公司提供了强有力的支持。双方合作仅用了不到六个月的时间,就成功交付了首批Quantum™可编程加速器产品样本,创造了行业内的里程碑。

问答坊 | AI 解惑

武汉理工大学-2009初赛题——挺不错!

本帖最后由 paulhyde 于 2014-9-15 08:58 编辑 在nuedc上看到的! 不错,当做比赛预测题来做吧!  …

查看全部问答>

对比一下欧洲某大学的考试题,国内工程师请进!

注:看了国内某电子工程师考试题,觉得国内注重实践,不知道是否知其然并知其所以然,因此小弟在此首次灌水,希望抛砖引玉,了解一下国内工程师的水平。 1。普通二极管和电力电子用的二极管在结构上有什么区别?提示:psn结构,s层的作用是什么? ...…

查看全部问答>

P0口与地址译码

一个这样的电路:主要有AT89C51、74LS32(或门)、74LS273!接法大致如下:               P3.6(WR)和P2.7(A15)接74LS32(或门)的出入;            &nb ...…

查看全部问答>

Quartus 警告中文说明

Error: Quartus II Analysis & Synthesis was unsuccessful. 1 error, 0 warnings   Error: Quartus II Analysis & Synthesis was unsuccessful. 1 error, 0 warnings   Error: Top-level design entity \"ctrl\" is und ...…

查看全部问答>

下面的结构体类型定义中的冒号代表什么?

typedef struct bGPIOx_CRL { unsigned int MODE0 :2; unsigned int CNF0  :2; unsigned int MODE1 :2; unsigned int CNF1  :2; unsigned int MODE2 :2; unsigned int CNF2  :2; unsigned int M ...…

查看全部问答>

AD7793的高精度温度测量系统--进展贴

没有按时间完成整个项目,PCB,硬件电路已完成。 电路图打包…

查看全部问答>

贴士:脉冲IV测试有讲究

之前,与大家聊了那么多关于脉冲IV测试的内容;今天,为大家总结了进行脉冲IV测试的几点注意事项:(好好收藏,一生享用!)   1、 确认连接:在连接到设备之后,执行任何脉冲测试前,使用scope-shot进行第一次测试以确认到DUT[1]的连接是正 ...…

查看全部问答>

为什么我的Application UART驱动无法安装???

我用的MSP430 G2231,电脑里装有CCS5.1,但为什么我把launchpad 接电脑usb上后无法安装驱动啊???哪位大神能帮帮忙???跪谢。。。我试过右键点更新驱动,手动找到CCS5.1的安装文件夹下的驱动,无法安装,还试过装TIUSBFET,CP2012之类的,都无效啊 ...…

查看全部问答>

请问如何测量51单片机的功耗?

低功耗的产品设计。   目前采用串入电流表分段测量。长期2uA。短期4.5mA。瞬间20mA. 有什么好方法能用示波器测量电流的波形来看时间算功耗呢 ?…

查看全部问答>

用示波器表比勾上SPI的脉冲和数据线才能使SPI工作的疑惑?

DSP 2812调试SPI,出现了下面的问题: 示波器两通道探头加上数据线和时钟线上,两通道的地都接电源地,SPI才能正常工作。松开数据线和时钟线上的波器的探头,SPI就立即停止工作。 问题可能出在哪里了呢? [ 本帖最后由 niu506 于 2012-9-9 18:12 ...…

查看全部问答>