哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处
http://blog.csdn.net/woshixingaaa/archive/2011/02/12/6181489.aspx
分析了一下Uboot中Nandflash的驱动,u-boot-2009.08使用的是和Linux内核一样的MTD(内存技术设备)架构。在Uboot下对Nand的支持体现在命令行下实现对nand flash的操作,为:nand info,nand device,nand read,nand write,nand erease,nand bad。用到的主要数据结构有:struct nand_flash_dev,struct nand_chip。前者包括主要的芯片型号,存储容量,设备ID,I/O总线宽度等信息;后者是具体对nand flash进行操作时用到的信息。
对Nandflash驱动代码的分析:
1)lib_arm/board.c中start_armboot()函数中调用了nand_init()。
2)nand_init()函数定义在drivers/mtd/nand/Nand.c文件中,调用了同文件下的nand_init_chip()函数和board_nand_select_device()函数,并累加Nandflash的总大小。
3)nand_init_chip()函数初始化了IO_ADDR_R和IO_ADDR_W,调用board_nand_init()和nand_scan()。(在drivers/mtd/nand/S3c2410_nand.c中)
4)board_nand_init()函数在drivers/mtd/nand/S3c2410_nand.c中,初始化NFCONF配置寄存器。主要对struct nand_chip结构体的函数指针赋值,让他们指向自己为nand驱动编写的一些函数,该数据结构在include/linux/mtd/nand.h中定义。
5)nand_scan()函数在drivers/mtd/nand/Nand_base.c文件中定义,并调用了nand_scan_ident()和nand_scan_tail()函数。
6)nand_scan_ident()调用了同文件下的nand_set_defaults()和nand_get_flash_type(),nand_set_defaults()函数对struct nand_chip结构体的函数指针进行了赋值。在此函数中cmdfunc映射到了nand_command,nand_get_flash_type()读取了厂商和设备ID,并对struct nand_chip结构体的变量和mtd_info进行初始化操作。
7)nand_scan_tail()进行了ECC的设置和剩下的MTD驱动函数的初始化。
8)nand_select_device()函数用来打开或关闭nand芯片,-1是打开,0是关闭。chip->cmd_ctrl映射到hwcontrol(在drivers/mtd/nand/S3c2410_nand.c的board_nand_init()函数中)。
9)返回nand_init(),这样nand的初始化就完成了。
移植Nandflash驱动,主要是修改S3c2410_nand.c。
看一个Read操作的例子:
以common/env_nand.c里读取Nandflash的环境变量为例,
env_nand.c中调用了nand_read(&nand_info[0], offset, &len, char_ptr);
nand_read在include/nand.h中定义。
static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
{
return info->read(info, ofs, *len, (size_t *)len, buf);
}
nand_read又调用info->read,即mtd_info的read,mtd_info与nand_info_t同名。
mtd_info的read函数在drivers/nand/nand_base.c中的nand_scan_tail函数中被映射到nand_read(),在nand_read()中调用nand_do_read_ops()。这是最后一层,通过调用nand_chip中的函数完成带ECC的读操作。
现在进行移植:
修改include/configs/TE2440II.h如下
/*
* Command line configuration.
*/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING
#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMLETE
#endif
/*
* NAND flash setting
*/
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE 0x4e000000
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define NAND_SAMSUNG_LP_OPTIONS 1
#define CONFIG_NAND_S3C2440 1
#endif
环境变量那部分修改:
//#define CONFIG_ENV_IS_IN_FLASH 1
#define CONFIG_ENV_IS_IN_NAND 1 /*环境变量的保存位置*/
在drivers/mtd/nand/Makefile文件中添加:
COBJS-y += s3c2440_nand.o
COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
我们最重要的是修改s3c2410_nand.c,把它复制重命名为s3c2440_nand.c,因为s3c2410和s3c2440在nand控制器方面有很多不同,所以要进行移植。
修改s3c2440_nand.c为:
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCONT __REGi(NF_BASE + 0x4)
#define NFCMD __REGb(NF_BASE + 0x8)
#define NFADDR __REGb(NF_BASE + 0xc)
#define NFDATA __REGb(NF_BASE + 0x10)
#define NFMECCD0 __REGi(NF_BASE + 0x14)
#define NFMECCD1 __REGi(NF_BASE + 0x18)
#define NFSECCD __REGi(NF_BASE + 0x1C)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT0 __REGi(NF_BASE + 0x24)
#define NFSTAT1 __REGi(NF_BASE + 0x28)
#define NFMECC0 __REGi(NF_BASE + 0x2C)
#define NFMECC1 __REGi(NF_BASE + 0x30)
#define NFSECC __REGi(NF_BASE + 0x34)
#define NFSBLK __REGi(NF_BASE + 0x38)
#define NFEBLK __REGi(NF_BASE + 0x3c)
#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x0c
#define S3C2440_ADDR_NCLE 0x08
ulong IO_ADDR_W = NF_BASE;
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
IO_ADDR_W = NF_BASE;
if (!(ctrl & NAND_CLE)) //要写的是地址
{
IO_ADDR_W |= S3C2440_ADDR_NALE;}
if (!(ctrl & NAND_ALE)) //要写的是命令
{
IO_ADDR_W |= S3C2440_ADDR_NCLE;}
if (ctrl & NAND_NCE)
{NFCONT &= ~S3C2440_NFCONT_nCE; //使能nand flash
//DEBUGN("NFCONT is 0x%x ",NFCONT);
//DEBUGN("nand Enable ");
}
else
{NFCONT |= S3C2440_NFCONT_nCE; //禁止nand flash
//DEBUGN("nand disable ");
}
}
if (cmd != NAND_CMD_NONE)
writeb(cmd,(void *)IO_ADDR_W);
}
static int s3c2440_dev_ready(struct mtd_info *mtd)
{
DEBUGN("dev_ready\n");
return (NFSTAT & 0x01);
}
/******************************************************************************************/
int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
DEBUGN("board_nand_init()\n");
clk_power->CLKCON |= (1 << 4);
DEBUGN("CONFIG_S3C2440\n");
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
//DEBUGN("cfg is %x\n",cfg);
//DEBUGN("NFCONF is %lx\n",NFCONF);
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;
//DEBUGN("cfg is %lx\n",cfg);
//DEBUGN("NFCONT is %x\n",NFCONT);
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
/* read_buf and write_buf are default */
/* read_byte and write_byte are default */
/* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c2440_hwcontrol;
nand->dev_ready = s3c2440_dev_ready;
return 0;
}
s3c2440_hwcontrol函数主要控制是写命令还是写地址。
我遇到的问题,由于board_nand_init()函数我没有添加return 0,导致后面的判断没法进行,结果读出的NAND为0MiB,所以移植一定要仔细阅读源码,还有个问题就是uboot的打印信息中出现NAND_ECC_NONE selected by board driver. This is not recommended!!,这根ECC的校验模式有关,有人说“据说vivi或uboot通过软件算法产生的ecc校验码于S3C2410 NAND Flash 控制器产生的ecc校验码不一致”,所以我就没改什么,我把那个打印信息注释掉了。
分享到:
相关推荐
在本文中,我们将深入探讨如何将u-boot-2012.04.01版本移植到TQ2440开发板上。这个过程对于理解嵌入式系统的引导加载程序(bootloader)以及硬件平台的初始化至关重要。u-boot是一个广泛应用的开源引导加载程序,而...
《深入解析u-boot-2440-nandflash:打造2440开发板的核心启动技术》 在嵌入式系统领域,u-boot是一个至关重要的组成部分,它扮演着引导加载程序的角色,负责初始化硬件,加载操作系统到内存,并进行必要的设备配置...
【描述】中的"支持sd卡启动"指的是这个U-Boot版本包含了对SD卡启动机制的专门适配,使得开发板或嵌入式设备可以将操作系统镜像存储在SD卡上,并通过SD卡来启动系统。"修改u-boot-mini6410-20101106.tar.gz而来"意味...
《移植好的u-boot2009.08在mini2440/micro2440平台的应用详解》 u-boot作为嵌入式系统的重要组成部分,是设备启动时执行的第一段代码,它负责加载操作系统内核,进行硬件初始化,以及提供用户交互界面。本文将深入...
在本文中,我们将深入探讨如何将u-boot-2010.06版本移植到Mini2440开发板上,这是一个基于S3C2440处理器的嵌入式平台。移植工作涉及到多个关键组件,包括对不同类型的闪存(如NOR Flash和NAND Flash)的支持以及网络...
本手册详细介绍了如何为基于S3C2440芯片的开发板移植u-boot 2009.11版本, 包括环境搭建、调试方法的选择、移植步骤的具体操作等。通过遵循这些步骤, 初学者可以顺利地完成u-boot的移植, 并掌握相关的嵌入式系统开发...
标题中的"arm-linux-gnueabihf-gcc-linaro-7.5.0-x86_64.tar.xz.zip"是一个针对ARM架构的Linux交叉编译工具链的压缩包,它由Linaro组织提供。Linaro是一个非营利组织,专注于优化和维护开源软件在ARM处理器上的性能...
u-boot移植过程是指将u-boot移植到特定的开发板上,使其能够正确地运行和启动。这个过程需要对u-boot的源码进行修改,以适应特定的硬件平台。 整个移植过程可以分为以下几个步骤: 1. 准备u-boot的源码:首先需要...
第二步:查看当前系统是否支持arm-linux-gcc 如果不存在 则继续如下步骤: 第三步:在/usr/local创建一个文件夹为arm mkdir /usr/local/arm 第四步:将arm-linux-gcc-4.3.2.bz2解压到/usr/local/arm目录下 sudo tar ...
u-boot.bin_tekkaman_2009.11.bz2 参考网站:Tekkaman Ninja github.com/tekkamanninja 直接可用于mini2440开发板 当然在这之前首先必须保证你的开发板上已经有了U-boot。如果没有,就请先烧入一个 已经编译好...
【u-boot 2011.12 移植】涉及的知识点主要集中在嵌入式Linux系统的引导加载器u-boot的移植过程,特别是针对S3C2440处理器的移植。下面将详细介绍这些内容: 1. **配置编译环境**: - 首先,你需要从指定FTP服务器...
### U-Boot 2010.03 在 S3C2410 开发板上的移植与 NAND Flash 启动配置详解 U-Boot(Universal Boot Loader)是一款开源的引导加载程序,广泛应用于嵌入式系统中。本文将详细介绍如何在S3C2410开发板上移植U-Boot ...
到友善之臂mini2440_himrce_mini2440_U-Boot_dull3lc_”表明这是一个关于将U-Boot 2010.03版本移植到友善之臂( FriendlyARM)Mini2440开发板上的过程。在这个过程中,我们可能会涉及到多个关键知识点,包括U-Boot的...
6. **多平台兼容**:U-Boot支持广泛的处理器架构,如ARM、PowerPC、MIPS、X86等,以及众多嵌入式开发板。 7. **源代码开放**:作为开源项目,U-Boot的源代码可供开发者研究、定制和改进,促进社区的持续发展。 在...
最后,通过JTAG、UART或NAND Flash等方法将u-boot烧录到mini2440的存储器中。 5. **u-boot命令行操作** u-boot提供了一套丰富的命令行工具,允许用户执行如加载内核、挂载文件系统、查看硬件信息、网络操作等任务...
个人移植并可以正常使用的uboot,适用于飞凌ok335xd开发板,米尔科技c335x开发板,基于u-boot官方u-boot-2018.05源码移植,并有git记录。 配置文件am335x_ok335xd_defconfig am335x_myd_defconfig
对于mini2440平台,U-Boot的配置可能还包括对NAND Flash的支持,因为S3C2440处理器通常使用NAND Flash存储操作系统映像。在U-Boot中,会有专门的驱动来处理NAND Flash的读写操作,确保数据传输的正确性。 总的来说...
这个名为“u-boot-2011.09-forlinx”的压缩包,显然是为Linux平台定制的一个u-boot版本,发布于2011年9月。 一、u-boot概述 u-boot的诞生是为了满足嵌入式设备的多样性和灵活性需求。它支持多种处理器架构,包括ARM...