这节我们实现nand的ecc,保存环境变量到nand flash 中。然后把我们之前的led灯烧写到nand flash 中。开机启动。在 tiny210.h 中定义宏 CONFIG_S5PV210_NAND_HWECC、CONFIG_SYS_NAND_ECCSIZE、CONFIG_SYS_NAND_ECCBYTES

CONFIG_SYS_NAND_ECCSIZE 定义了消息长度。即每多少字节进行 1 次 ECC 校验

CONFIG_SYS_NAND_ECCBYTES 定义为 13Byte,将 drivers/mtd/nand/s5pv210_nand.c 中的 CONFIG_S3C2410_NAND_HWECC 替换为CONFIG_S5PV210_NAND_HWECC,我们仅仅进行 ECC 校验写。ECC 校验读使用三星提供的函数。我们必须依照三星手冊规定的 ECC 校验码在
Spare Field  中的存储格式进行存储。

因此我们须要自己定义 nand_ecclayout 结构体,这个结构体描写叙述了怎样存储 ECC 数据,同一时候将这个结构体赋值给 nand->ecc.layout

其它的代码请看源代码:

/*
* (C) Copyright 2006 OpenMoko, Inc.
* Author: Harald Welte <laforge@openmoko.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/ #include <common.h> #include <nand.h>
#include <asm/arch/nand_reg.h>
#include <asm/io.h> #define MP0_1CON (*(volatile u32 *)0xE02002E0)
#define MP0_3CON (*(volatile u32 *)0xE0200320)
#define MP0_6CON (*(volatile u32 *)0xE0200380) /* modied by shl */
static void s5pv210_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
struct s5pv210_nand *nand = (struct s5pv210_nand *)samsung_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
ulong IO_ADDR_W = (ulong)nand;
if (ctrl & NAND_CTRL_CHANGE) { if (ctrl & NAND_CLE)
IO_ADDR_W = IO_ADDR_W | 0x8; /* Command Register */
else if (ctrl & NAND_ALE)
IO_ADDR_W = IO_ADDR_W | 0xC; /* Address Register */ chip->IO_ADDR_W = (void *)IO_ADDR_W; if (ctrl & NAND_NCE) /* select */
writel(readl(&nand->nfcont) & ~(1 << 1), &nand->nfcont);
else /* deselect */
writel(readl(&nand->nfcont) | (1 << 1), &nand->nfcont);
} if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
else
chip->IO_ADDR_W = &nand->nfdata; } static int s5pv210_dev_ready(struct mtd_info *mtd)
{
struct s5pv210_nand *nand = (struct s5pv210_nand *)samsung_get_base_nand();
debug("dev_ready\n");
return readl(&nand->nfstat) & 0x01;
} #ifdef CONFIG_S5PV210_NAND_HWECC
void s5pv210_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
struct s5pv210_nand *nand = (struct s5pv210_nand *)samsung_get_base_nand();
debug("s5pv210_nand_enable_hwecc(%p, %d)\n", mtd, mode); writel(readl(&nand->nfconf) | (0x3 << 23), &nand->nfconf); if (mode == NAND_ECC_READ)
{
}
else if (mode == NAND_ECC_WRITE)
{
/* set 8/12/16bit Ecc direction to Encoding */
writel(readl(&nand->nfecccont) | (0x1 << 16), &nand->nfecccont);
/* clear 8/12/16bit ecc encode done */
writel(readl(&nand->nfeccstat) | (0x1 << 25), &nand->nfeccstat);
} /* Initialize main area ECC decoder/encoder */
writel(readl(&nand->nfcont) | (0x1 << 5), &nand->nfcont); /* The ECC message size(For 512-byte message, you should set 511)
* 8-bit ECC/512B */
writel((511 << 16) | 0x3, &nand->nfeccconf); writel(readl(&nand->nfstat) | (0x1 << 4) | (0x1 << 5), &nand->nfstat); /* Initialize main area ECC decoder/ encoder */
writel(readl(&nand->nfecccont) | (0x1 << 2), &nand->nfecccont); /* Unlock Main area ECC */
writel(readl(&nand->nfcont) & ~(0x1 << 7), &nand->nfcont);
} /* modied by shl */
static int s5pv210_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
struct s5pv210_nand *nand = (struct s5pv210_nand *)samsung_get_base_nand();
u32 nfeccprgecc0 = 0, nfeccprgecc1 = 0, nfeccprgecc2 = 0, nfeccprgecc3 = 0; /* Lock Main area ECC */
writel(readl(&nand->nfcont) | (1 << 7), &nand->nfcont); /* 读取13 Byte的Ecc Code */
nfeccprgecc0 = readl(&nand->nfeccprgecc0);
nfeccprgecc1 = readl(&nand->nfeccprgecc1);
nfeccprgecc2 = readl(&nand->nfeccprgecc2);
nfeccprgecc3 = readl(&nand->nfeccprgecc3); ecc_code[0] = nfeccprgecc0 & 0xff;
ecc_code[1] = (nfeccprgecc0 >> 8) & 0xff;
ecc_code[2] = (nfeccprgecc0 >> 16) & 0xff;
ecc_code[3] = (nfeccprgecc0 >> 24) & 0xff;
ecc_code[4] = nfeccprgecc1 & 0xff;
ecc_code[5] = (nfeccprgecc1 >> 8) & 0xff;
ecc_code[6] = (nfeccprgecc1 >> 16) & 0xff;
ecc_code[7] = (nfeccprgecc1 >> 24) & 0xff;
ecc_code[8] = nfeccprgecc2 & 0xff;
ecc_code[9] = (nfeccprgecc2 >> 8) & 0xff;
ecc_code[10] = (nfeccprgecc2 >> 16) & 0xff;
ecc_code[11] = (nfeccprgecc2 >> 24) & 0xff;
ecc_code[12] = nfeccprgecc3 & 0xff; debug("s5pv210_nand_calculate_hwecc(%p,):\n"
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
"0x%02x 0x%02x 0x%02x\n", mtd , ecc_code[0], ecc_code[1], ecc_code[2],
ecc_code[3], ecc_code[4], ecc_code[5], ecc_code[6], ecc_code[7],
ecc_code[8], ecc_code[9], ecc_code[10], ecc_code[11], ecc_code[12]); return 0;
} /* add by shl */
#define NF8_ReadPage_Adv(a,b,c) (((int(*)(u32, u32, u8*))(*((u32 *)0xD0037F90)))(a,b,c))
static int s5pv210_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
/* tiny210使用的NAND FLASH一个块64页 */
return NF8_ReadPage_Adv(page / 64, page % 64, buf);
} static int s5pv210_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
if (read_ecc[0] == calc_ecc[0] &&
read_ecc[1] == calc_ecc[1] &&
read_ecc[2] == calc_ecc[2])
return 0; printf("s5pv210_nand_correct_data: not implemented\n");
return -1;
}
#endif /*
* add by shl
* nand_select_chip
* @mtd: MTD device structure
* @ctl: 0 to select, -1 for deselect
*
* Default select function for 1 chip devices.
*/
static void s5pv210_nand_select_chip(struct mtd_info *mtd, int ctl)
{
struct nand_chip *chip = mtd->priv; switch (ctl) {
case -1: /* deselect the chip */
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
break;
case 0: /* Select the chip */
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
break; default:
BUG();
}
} /* add by shl */
static struct nand_ecclayout nand_oob_64 = {
.eccbytes = 52, /* 2048 / 512 * 13 */
.eccpos = { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
62, 63},
/* 0和1用于保存坏块标记,12~63保存ecc,剩余2~11为free */
.oobfree = {
{.offset = 2,
.length = 10}
}
}; /* modied by shl */
int board_nand_init(struct nand_chip *nand)
{
u32 cfg = 0;
struct s5pv210_nand *nand_reg = (struct s5pv210_nand *)(struct s5pv210_nand *)samsung_get_base_nand(); debug("board_nand_init()\n"); /* initialize hardware */
/* HCLK_PSYS=133MHz(7.5ns) */
cfg = (0x1 << 23) | /* Disable 1-bit and 4-bit ECC */
/* 以下3个时间參数略微比计算出的值大些(我这里依次加1),否则读写不稳定 */
(0x3 << 12) | /* 7.5ns * 2 > 12ns tALS tCLS */
(0x2 << 8) | /* (1+1) * 7.5ns > 12ns (tWP) */
(0x1 << 4) | /* (0+1) * 7.5 > 5ns (tCLH/tALH) */
(0x0 << 3) | /* SLC NAND Flash */
(0x0 << 2) | /* 2KBytes/Page */
(0x1 << 1); /* 5 address cycle */ writel(cfg, &nand_reg->nfconf); writel((0x1 << 1) | (0x1 << 0), &nand_reg->nfcont);
/* Disable chip select and Enable NAND Flash Controller */ /* Config GPIO */
MP0_1CON &= ~(0xFFFF << 8);
MP0_1CON |= (0x3333 << 8);
MP0_3CON = 0x22222222;
MP0_6CON = 0x22222222; /* initialize nand_chip data structure */
nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
nand->IO_ADDR_W = (void *)&nand_reg->nfdata; nand->select_chip = s5pv210_nand_select_chip; /* read_buf and write_buf are default */
/* read_byte and write_byte are default */ /* hwcontrol always must be implemented */
nand->cmd_ctrl = s5pv210_hwcontrol; nand->dev_ready = s5pv210_dev_ready; #ifdef CONFIG_S5PV210_NAND_HWECC
nand->ecc.hwctl = s5pv210_nand_enable_hwecc;
nand->ecc.calculate = s5pv210_nand_calculate_ecc;
nand->ecc.correct = s5pv210_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
nand->ecc.strength = 1;
/* add by shl */
nand->ecc.layout = &nand_oob_64;
nand->ecc.read_page = s5pv210_nand_read_page_hwecc;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif #ifdef CONFIG_S3C2410_NAND_BBT
nand->bbt_options |= NAND_BBT_USE_FLASH;
#endif debug("end of nand_init\n"); return 0;
}

又一次编译,成功生成 u-boot.bin,将它烧写到 SD 卡的扇区 32,从 SD 卡启动开发板:

以下进行 NAND 启动试验,将之前的led程序烧写到 NAND。然后从 NAND 启动,可以看到 LED 全亮的效果。

首先我们先编译
led.c。生成 led.bin。然后 加入 16B 的头信息生成 210.bin,然后将 210.bin 复制到 tftp server文件夹。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2loYWlsaW4xOTkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

然后使用最新的 u-boot 将 210.bin 烧写到 NAND 的第 0 页,然后从 NAND 启动

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2loYWlsaW4xOTkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

从 NAND 启动能够看到 4 个 LED 全亮。

tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 8位硬件ECC的更多相关文章

  1. tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动

    我们知道 s5pv210启动方式有非常多种,sd卡和nand flash 启动就是当中的两种,前面我们实现的都是基于sd卡启动,这节我们開始实现从nand flash 启动: 从 NAND 启动 u- ...

  2. tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——移植u-boot.bin(打印串口控制台)

    在之前我们移植的代码中,都没看到明显的效果,这节我们实现控制台的信息打印. 在上节.我们看到调用 relocate_code 重定位.在 u-boot 的帮助文档 doc/README.arm-rel ...

  3. [学习资料] Tiny210(S5PV210) u-boot移植

    Tiny210(S5PV210) u-boot移植http://www.microoh.com/bbs/forum.php?mod=viewthread&tid=254&fromuid ...

  4. Spring boot 基于Spring MVC的Web应用和REST服务开发

    Spring Boot利用JavaConfig配置模式以及"约定优于配置"理念,极大简化了基于Spring MVC的Web应用和REST服务开发. Servlet: package ...

  5. 分布式事务、多数据源、分库分表中间件之spring boot基于Atomikos+XADataSource分布式事务配置(100%纯动态)

    本文描述spring boot基于Atomikos+DruidXADataSource分布式事务配置(100%纯动态),也就是增加.减少数据源只需要修改application.properties文件 ...

  6. 【spring boot】【redis】spring boot基于redis的LUA脚本 实现分布式锁

    spring boot基于redis的LUA脚本 实现分布式锁[都是基于redis单点下] 一.spring boot 1.5.X 基于redis 的 lua脚本实现分布式锁 1.pom.xml &l ...

  7. Spring boot 基于注解方式配置datasource

    Spring boot 基于注解方式配置datasource 编辑 ​ Xml配置 我们先来回顾下,使用xml配置数据源. 步骤: 先加载数据库相关配置文件; 配置数据源; 配置sqlSessionF ...

  8. STM32下FatFs的移植,实现了坏块管理,硬件ECC,ECC纠错,并进行擦写均衡分析

    最近因项目需要,做一个数据采集的单片机平台.需要移植 FatFs .现在把最后成果贴上来. 1.摘要 在 STM32 单片机上,成功移植 FatFs 0.12b,使用的 Nand Flash 芯片为 ...

  9. 阅读基于sketch的软件定义网络测量数据平面硬件模型

    概要 硬件实现 基于sketch 功能:采集包数.流长数据,恢复五元组 重点:高速条件下性能较好,节省硬件资源 摘要: 提出一种基于sketch 数据结构的软件定义测量数据平面硬件模型,并在以现场可编 ...

随机推荐

  1. mapbox-gl 开发包dev生成

    mapbox-gl简介 mapbox-gl采用webgl,提供在线地图实时渲染功能,具有以下特点: 1.多图层显示 2.图层元素显示样式在颜色.字体.大小范围等.是否显示等可实时更改 3.定位抓取选择 ...

  2. angualr4 路由 总结笔记

    使用cli命令创建根路由模块 ng g cl app.router 或自己建一个路由配置文件 如:app/app.router.ts // app/app.router.ts // 将文件修改为 im ...

  3. SUID,SGID,SBIT这些到底是什么

    SUID,SGID,SBIT这些都是文件的特殊权限. SUID(Set UID)文件执行过程中,用户拥有文件的root权限. SGID(Set GID)文件执行过程中,执行者拥有该文件的用户组的权限. ...

  4. jstree 获取选中节点的所有子子点

    //加载功能树 function initTree() { $.jstree.destroy(); $.ajax({ type: "Get", url: "/Depart ...

  5. 一款基于vue2.0的分页组件---写在页面内

    通过 Vue2.0 实现的分页 可自由设置分页显示的多少.上一页.下一页.省略号等,也可直接输入跳转到的页码进行跳转,分页的样式可自由调整 // 1.页面的 head 部分,需要设计好页面的样式 .p ...

  6. javascript 的继承

    我们的JavaScript比较特别了,主要通过原型链实现继承的. 下面介绍各种实现继承的方式:原型链继承,借用构造函数,组合继承,原型式继承,寄生式继承,寄生组合式继承. 二.实现继承方式 1.原型链 ...

  7. 翻译连载 | 附录 A:Transducing(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  8. 关于HTML5新手应该知道的几点知识

    随着移动互联网的快速发展,HTML5迅速崛起,我们的生活的方方面面都被HTML5渗透着.HTML5在PC端.移动端上均应用广泛,被称为Web的未来.而随着Google正式停止支持Swiffy,HTML ...

  9. JavaEE中的MVC(三)定制Struts——命令模式

    注:本文并不讲解Struts框架,只研究这种思想的使用 JavaEE中的MVC(五)定制Struts--Action跳转Jsp 在讲这个之前,先给你们看一下我服务器1.0版本的截图,是不是很可笑,看起 ...

  10. yii2 邮件发送

    修改配置文件mail-local.php 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', 'useFileTransport' =&g ...