历史上的今天
返回首页

历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2021年10月11日 | S3C2440裸机------NandFlash编程_数据读取

2021-10-11 来源:eefocus

1.NandFlash结构介绍

 一个page是由2028的page data和64字节的OOB(out of bank)组成的, 


位反转:NandFlash在读一页数据或者写一页数据的时候有可能会发生位反转,就是在读某一页数据的时候,里面有某一位可能是错误的,为了解决这个问题引入了oob区,写页数据的时候,把数据写进去,同时会生成一个校验码,把校验码写到oob区里面,读数据的时候,读出一页数据,使用oob里面的校验码对数据进行修正,oob的存在是为了解决NandFlash的缺点。


2.读数据

我们想读取NandFlash的时候,所谓的行地址是指在哪一个page上面,所谓的列地址是指在这个page上的哪一个地址(0-2047)。


void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)

{

int i = 0;

int page = addr / 2048;

int col  = addr & (2048 - 1);

nand_select(); 

 

while (i < len)

{

/* 发出00h命令 */

nand_cmd(00);

 

/* 发出地址 */

/* col addr */

nand_addr_byte(col & 0xff);

nand_addr_byte((col>>8) & 0xff);

 

/* row/page addr */

nand_addr_byte(page & 0xff);

nand_addr_byte((page>>8) & 0xff);

nand_addr_byte((page>>16) & 0xff);

 

/* 发出30h命令 */

nand_cmd(0x30);

 

/* 等待就绪 */

wait_ready();

 

/* 读数据 */

for (; (col < 2048) && (i < len); col++)

{

buf[i++] = nand_data();

}

if (i == len)

break;

 

col = 0;

page++;

}

nand_deselect();

}


这里的wait_ready()函数是根据S3C2440的这个寄存器写的

void wait_ready(void)

{

while (!(NFSTAT & 1));

}

3.支持NandFlash启动

下面修改程序,保证当我们的代码大于4K时也能从NandFlash启动,首先修改我们之前的copy2sdram函数,增加一个NandFlash分支。


int isBootFromNorFlash(void)

{

volatile unsigned int *p = (volatile unsigned int *)0;

unsigned int val = *p;

 

*p = 0x12345678;

if (*p == 0x12345678)

{

/* 写成功, 对应nand启动 */

*p = val;

return 0;

}

else

{

return 1;

}

}

 

void copy2sdram(void)

{

/* 要从lds文件中获得 __code_start, __bss_start

* 然后从0地址把数据复制到__code_start

*/

 

extern int __code_start, __bss_start;

 

volatile unsigned int *dest = (volatile unsigned int *)&__code_start;

volatile unsigned int *end = (volatile unsigned int *)&__bss_start;

volatile unsigned int *src = (volatile unsigned int *)0;

int len;

 

len = ((int)&__bss_start) - ((int)&__code_start);

 

if (isBootFromNorFlash())

{

while (dest < end)

{

*dest++ = *src++;

}

}

else

{

nand_init();

nand_read(src, dest, len);

}

}

这里的isBootFromNorFlas函数是根据,假如是NorFalsh启动,那么0地址不能像内存一样去写。


4.完整代码

#include "s3c2440_soc.h"

#include "my_printf.h"

 

void nand_init(void)

{

#define  TACLS   0

#define  TWRPH0  1

#define  TWRPH1  0

/*设置NAND FLASH的时序*/

NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);

/*使能NAND FLASH控制器,初始化ECC,禁止片选*/

NFCONT = (1<<4) | (1<<1) | (1<<0);

}

 

void nand_select(void)

{

/*使能片选*/

NFCONT &=~(1<<1);

}

 

void nand_deselect(void)

{

/*禁止片选*/

NFCONT |= (1<<1);

}

 

void nand_cmd(unsigned char cmd)

{

volatile int i;

NFCCMD = cmd;

for(i=0; i<10; i++);

}

 

void nand_addr_byte(unsigned char addr)

{

volatile int i;

NFADDR = addr;

for(i=0; i<10; i++);

}

 

unsigned char nand_data(void)

{

return NFDATA;

}

 

void wait_ready(void)

{

while (!(NFSTAT & 1));

}

 

void nand_chip_id(void)

unsigned char buf[5]={0};

nand_select(); 

nand_cmd(0x90);

nand_addr_byte(0x00);

 

buf[0] = nand_data();

buf[1] = nand_data();

buf[2] = nand_data();

buf[3] = nand_data();

buf[4] = nand_data();

nand_deselect();

 

printf("maker   id  = 0x%xnr",buf[0]);

printf("device  id  = 0x%xnr",buf[1]);

printf("3rd byte    = 0x%xnr",buf[2]);

printf("4th byte    = 0x%xnr",buf[3]);

printf("page  size  = %d kbnr",1  <<  (buf[3] & 0x03));

printf("block size  = %d kbnr",64 << ((buf[3] >> 4) & 0x03));

printf("5th byte    = 0x%xnr",buf[4]);

 

}

 

 

void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)

{

int i = 0;

int page = addr / 2048;

int col  = addr & (2048 - 1);

nand_select(); 

 

while (i < len)

{

/* 发出00h命令 */

nand_cmd(00);

 

/* 发出地址 */

/* col addr */

nand_addr_byte(col & 0xff);

nand_addr_byte((col>>8) & 0xff);

 

/* row/page addr */

nand_addr_byte(page & 0xff);

nand_addr_byte((page>>8) & 0xff);

nand_addr_byte((page>>16) & 0xff);

 

/* 发出30h命令 */

nand_cmd(0x30);

 

/* 等待就绪 */

wait_ready();

 

/* 读数据 */

for (; (col < 2048) && (i < len); col++)

{

buf[i++] = nand_data();

}

if (i == len)

break;

 

col = 0;

page++;

}

nand_deselect();

}

 

 

void nand_flash_test(void)

{

char c;

 

while (1)

{

/* 打印菜单, 供我们选择测试内容 */

printf("[s] Scan nand flashnr");

printf("[e] Erase nand flashnr");

printf("[w] Write nand flashnr");

printf("[r] Read nand flashnr");

printf("[q] quitnr");

printf("Enter selection: ");

 

c = getchar();

printf("%cnr", c);

 

/* 测试内容:

* 1. 识别nand flash

* 2. 擦除nand flash某个扇区

* 3. 编写某个地址

* 4. 读某个地址

*/

switch (c)  

{

case 'q':

case 'Q':

return;

break;

case 's':

case 'S':

nand_chip_id();

break;

 

case 'e':

case 'E':

break;

 

case 'w':

case 'W':

break;

 

case 'r':

case 'R':

break;

default:

break;

}

}

}

推荐阅读

史海拾趣

GHI Electronics公司的发展小趣事

GHI Electronics深知技术创新是企业持续发展的关键。因此,公司不断加大研发投入,致力于开发具有自主知识产权的产品。其中,ARM微控制器、显示模块、空气质量传感器、模块化系统以及微处理器等主打产品系列,凭借其卓越的性能和稳定的品质,在消费电子、便携设备、通讯/网络等领域获得了广泛应用。这些技术创新不仅巩固了GHI Electronics在市场上的领先地位,也为其未来的发展奠定了坚实的基础。

Chino-Excel公司的发展小趣事

在发展过程中,Chino-Excel公司注重品牌建设和市场推广。公司投入大量资金进行品牌宣传和推广活动,提升品牌知名度和美誉度。同时,公司积极参加国际电子展会和行业交流活动,与国内外客户建立广泛的联系和合作,为公司的快速发展奠定了坚实基础。

Dfx公司的发展小趣事

在智能手机行业快速发展的背景下,某知名手机制造商面临着如何将更多功能集成到更小空间的挑战。通过引入DFX的设计理念,该公司成功实现了硬件的小型化,同时保持了高性能和可靠性。通过优化内部布局、采用先进封装技术和选用高性能元器件,该手机制造商在保持产品竞争力的同时,满足了消费者对轻薄、高性能手机的需求。

鞍山圣罗佳(ASL)公司的发展小趣事

某半导体企业在生产过程中面临着生产效率低下、成本过高的问题。为了提高生产效率并降低成本,该企业引入了DFX的设计理念,对生产线进行了全面优化。通过改进设备布局、优化工艺流程和采用自动化生产技术等手段,该企业成功提高了生产效率并降低了成本,增强了市场竞争力。

FINECHIPS公司的发展小趣事

FINECHIPS公司始终坚持客户导向的经营理念,深入了解客户需求,提供定制化的产品和服务。在一次与某知名电子产品制造商的合作中,FINECHIPS根据客户的特殊需求,迅速调整产品设计和生产流程,成功开发出了一款符合客户要求的定制化芯片。这次合作不仅加深了双方的合作关系,还为FINECHIPS赢得了更多潜在客户的信任和青睐。

ELEMENT14公司的发展小趣事

ELEMENT14公司最初是一家电子元器件分销商,但随着市场的变化和客户需求的升级,公司决定转型为提供一站式服务的平台。这一转变意味着公司不仅要提供电子元器件,还要提供软件、技术支持、在线社区等全方位的服务。通过不断的投入和努力,ELEMENT14成功转型为一个综合性的电子元器件服务平台,满足了客户多样化的需求。

问答坊 | AI 解惑

基于台达PLC 的工厂产量监控查询系统

:局限于技术条件,目前生产中在统计生产产品产量方面不少还是依靠人工进行统计。在实际操作过程中,往往出现产品严重丢失,投入的原料量和产出的成品量严重失衡,因此,有必要采用工厂产量监控查询系统对整个工厂的产品产量进行准确的计量,文章基 ...…

查看全部问答>

旋转编码器

谁用过旋转编码器啊 我现在编码器 用的时候会出现漏状态啊 100次会出现3次左右吧?…

查看全部问答>

节能灯的标准长度

节能灯的标准长度怎么规定?有标准的规定吗?…

查看全部问答>

cpld资源问题讨论

cpld在编码和译码的时候占用的资源很大,不知哪位大虾可有什么妙法来减少资源的使用吗?如何较少宏单元的使用呢?…

查看全部问答>

碰到了令牌错误了。大家来帮帮忙。

代码都没有,怎么会有这个错误啊,怎么解决?…

查看全部问答>

GPRS模块

M660是一款可支持开放平台的GSM/GPRS工业无线模块,预留了CPU资源以及丰富的硬件接口,可以提供高品质的语音、短信、数据业务等功能,在各种工业和民用领域得到广泛的应用。 产品特性:  双频:900M / 1800M  可靠性高:特殊EMI ...…

查看全部问答>

业余时间想做个遥控小车,问个问题?

我想用wifi控制小车,并在小车上装个摄像头,把视频传到PC端显示,看到网上很多成功的,但不知道具体的实现,有谁做过吗?比如小车上用什么操作系统?实时性怎么样?用arm直接控制马达还是单加一个单片机?越具体越好,谢谢大家了…

查看全部问答>

【C2000 LaunchPad】单相交流电压+电流表__算法篇

目前,电力行业里面计算电量参数使用最多的是傅里叶算法(FFT)。网上有一篇非常经典的关于FFT的介绍文章“FFT结果的物理意义”,作者是网络名人“电脑圈圈”。我就不多说了。直接转载过来,给大家参考。    FFT是离散傅立叶变换的快 ...…

查看全部问答>