项目开源地址:https://github.com/Mculover666/uboot-jz2440

0. 教程完整目录

  • 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理
  • 01 - 下载uboot源码并使用VSCode远程查看源码、编译uboot(2012.04.01版本)
  • 02 - 详细探索uboot启动过程(基于S3C2410处理器)
  • 03 - 初步移植uboot 2012.04到JZ2440(修改时钟,配置串口)
  • 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)
  • 05 - 移植uboot 2012.04到JZ2440(支持Nand Flash读写)
  • 06 - 移植uboot 2012.04到JZ2440(支持DM9000C网卡)
  • 07 - 移植uboot 2012.04到JZ2440(裁剪uboot大小)
  • 08 - 移植uboot 2012.04到JZ2440(设置mtd分区表)
  • 09 - 移植uboot 2012.04到JZ2440(设置默认环境变量参数)
  • 10 - 移植uboot 2012.04到JZ2440(烧写Linux内核、烧写yaffs2文件系统)
  • 11 - 移植uboot 2012.04到JZ2440(移植完成,制作uboot补丁)

在支持Nand Flash操作之前,首先要对Nand Flash的读写方法有一定的了解,参考文章:

  • S3C2440-裸机篇-10 | 使用S3C2440操作Nand Flash

1. 去除nand flash屏蔽

在之前初步移植uboot时,发现开启nand flash之后编译不通过,所以屏蔽了nand flash的使用,在单板配置文件include/configs/smdk2440.h中开启:

然后编译,改正编译错误。

2. 定位编译出错问题所在

首先来修复第一个问题:

查看s3c2410_nand.c文件的72行:

这个指针有问题的话,就是nand这个结构体变量的定义问题,找到nand变量的定义:

struct s3c2410_nand *nand = s3c2410_get_base_nand();

接下来问题就变为struct s3c2410_nand这个结构体定义有问题,继续寻找该定义,果然,在文件arch/arm/include/asm/arch-s3c24x0/s3c24x0.h中,我们定义的是CONFIG_S3C2440,所以有struct s3c2440_nand的定义,没有struct s3c2410_nand的定义:

3. 修复编译错误 — 添加s3c2440_nand.c文件

3.1. 添加文件到工程中

这里涉及到将所有定义全部改变,所以复制一份s3c2410_nand.c文件,重命名为s3c2440_nand.c:

修改该目录下的makefile文件,将s3c2440_nand.c文件加入编译:

再去单板配置文件include/configs/smdk2440.h中配置宏定义CONFIG_NAND_S3C2440:

3.2. 修改文件

修改宏定义

首先借助VS Code文件替换全部内容的功能,将宏定义替换为2440的:

宏定义全部替换之后,如下:

再对照数据手册中,修改NFCONF寄存器和NFCONT寄存器中这些位的值:

全局替换

借助VS Code文件替换全部内容的功能,将涉及到2410的变量和函数都替换为2440的,如下图(替换之后的结果之一):

4. uboot中的nand flash操作框架

在uboot中,这些对于nand_flash的操作是基于一套操作框架的,类似于Linux中的设备驱动,所以首先分析一下这套框架,然后修改代码。

4.1. nand_init函数

故事要从uboot的第二阶段说起,在 board_init_r 函数中(文件arch/arm/lib/board.c)调用了 nand_iint 初始化函数:

接下来从该函数入手,分析nand flash的操作框架,该函数的源码在drivers/mtd/nand/nand.c文件中,定义如下:

nand_init_chip函数同样在该文件中,定义如下:

在此处定义了 nand_chip 结构体和 mtd_info 结构体,并分别将指针传递传参给 board_nand_init 函数和 nand_scan 函数,接下来分别分析这两个函数。

4.2. board_nand_init函数

board_nand_init 函数定义在上面我们自己添加的文件drivers/mtd/nand/s3c2440_nand.c中,该函数中主要使能了nand flash内存控制器,初始化nand flash控制器中的时序参数,最重要的是:

初始化传入的nand_chip结构体中的成员

struct nand_chip结构体在include/linux/mtd/nand.h文件中定义,这个结构体中的成员非常多,其中有非常多的函数指针,这些函数指针在初始化时被设置为指向底层实现的函数,在调用时拉起底层函数。

在board_nand_init 中初始化该结构体时,别的函数指针都被传入了相应的值,只有 select_chip 函数未被传入具体实现,而是NULL:

接下来继续分析这套框架,看一下 select_chip 函数的调用情况。

4.3. nand_scan 函数

该函数定义在drivers/mtd/nand/nand_base.c文件中,其定义代码如下:

这个函数将mtd结构体指针继续传给了nand_scan_ident函数,接着分析,这个函数同样在该文件中定义,根据函数注释可知,nand_scan_ident 函数会读取Flash ID,并根据读出的ID设置MTD信息,存入mtd结构体中。

进而查看该函数源码:

至此,是不是对nand_flash的整套操作框架有所了解了?可以画出这样一个调用关系图,帮助理解:

接下来分析nand_scan_ident函数中调用的两个函数:

  • nand_set_defaults
  • nand_get_flash_type

4.4. nand_set_defaults函数

该函数同样定义在文件drivers/mtd/nand/nand_base.c中,主要作用是设置 nand_chip结构体中的默认调用的函数,设置方法如下:

如果nand_chip结构体中的函数指针已经有值了,则不进行任何操作;

如果nand_chip结构体中的函数指针为NULL,则赋予默认值。

经过4.2节的分析,select_chip 指针被设置为NULL,所以在该函数中会被设置默认值:

默认函数 nand_select_chip 也同样定义在该文件中,定义如下:

从该函数中可以找到问题,片选函数被调用时,什么都不干,导致nand Flash芯片根本不工作。

解决方法就是:自己重新实现一个正常工作的 nand_select_chip 函数并将函数指针传给nand_flash结构体中的对应成员

4.5. nand_get_flash_type函数

该函数主要是读取ID值,根据根据读取到的ID值分析出nand flash类型,存储到 mtd_info 结构体中,该函数同样定义drivers/mtd/nand/nand_base.c文件中:

在该函数中,调用select_chip时传入的第二个参数为0,进一步验证了默认的片选函数什么都不干的分析结果。

6. 解决问题 — 自己实现select_chip函数

drivers/mtd/nand/s3c2440_nand.c文件中自定义片选函数,函数原型如下:

static void nand_select_chip(struct mtd_info *mtd, int chipnr);

实现如下:

static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chipnr)
{struct s3c2440_nand *nand = s3c2440_get_base_nand();switch (chipnr){case -1:/* 取消片选 */ writel(readl(&nand->nfcont) | (1 << 1), &nand->nfcont);break;case 0:/* 开启片选 */writel(readl(&nand->nfcont) & (~(1 << 1)), &nand->nfcont);break;default:BUG();}
}

然后在 board_nand_init 函数中使用该函数指针初始化nand_chip结构体成员,这样就避免它使用不能正常工作的默认值:

7. 修改底层实现代码

7.1. board_nand_init函数

这部分代码是重中之重,根据之前的文章来修改这段代码:

  • S3C2440-裸机篇-10 | 使用S3C2440操作Nand Flash

首先设置nand flash控制器时序参数:

接下来修改寄存器设置代码:

7.2. s3c2440_hwcontrol函数

该函数是所有发命令、发地址、发数据都会回调的函数,修改实现如下:

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{struct s3c2440_nand *nand = s3c2440_get_base_nand();debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);if(ctrl & NAND_CLE){//发命令writeb(cmd, &(nand->nfcmd));}else if(ctrl & NAND_ALE){//发地址writeb(cmd, &(nand->nfaddr));}
}

8. 关掉硬件ECC,使用软件ECC

这部分代码是使用宏定义CONFIG_S3C2440_NAND_HWECC来控制的:

所以在单板文件中去掉该宏定义:

至此,添加对Nand Flash的支持完成,编译,下载到开发板,在串口查看结果,成功检测出了Nand Flash,并分析出大小为256MB:

接收更多精彩文章及资源推送,欢迎订阅我的微信公众号:『mculover666』

uboot研读笔记 | 05 - 移植uboot 2012.04到JZ2440(支持Nand Flash读写)相关推荐

  1. uboot研读笔记 | 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)

    项目开源地址:https://github.com/Mculover666/uboot-jz2440 0. 教程完整目录 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理 01 ...

  2. T2080 U-BOOT与OS内核移植 u-boot移植篇(一)——创建新目标板的u-boot工程

    T2080 U-BOOT与OS内核移植 u-boot移植篇(一)--创建新目标板的u-boot工程 一.创建新目标板文件夹并修改相应文件 1.创建新目标板文件夹 2.修改t2080tpm文件夹中的相应 ...

  3. jz2440开发板修改UBOOT支持NAND FLASH

    很多天没有看嵌入式的东西了,今天来看一下,继续之前移植uboot到jz2440开发板.今天我们来实现Uboot支持NAND FLASH. 在之前的文章里(点击连接查看之前的记录),我们为了编译通过把N ...

  4. uboot研读笔记 | 12 - uboot目录结构分析(2016.03版本)

    整个目录结构分析的思维导图:[腾讯文档]uboot 2016.03目录结构分析 背景说明 我使用的是已经移植到atk-imx6ull开发板上的uboot,基于NXP原厂提供的uboot,版本为2016 ...

  5. uboot和linux内核移植,Uboot与kernel移植总结

    设置uimage入口:由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接 ...

  6. uboot下nand flash读写方法_鸿蒙HarmonyOS烧录方法总结

    1.烧录工具 理解HarmonyOS驱动框架,用户态APP和内核态驱动之间的通信机制. HarmonyOS烧录使用的海思自研的烧录工具Hitool,使用起来相对来说比较简单.整体界面如图所示: 2.  ...

  7. u-boot 2016.03支持nand flash boot

    工作背景: 目标板:imx6ul SOC+底板    u-boot:uboot2016.03 nand flash: Micron MT29F8G08ABABAWP 1G kernel启动过程中关于n ...

  8. uboot研读笔记 | 13 - uboot编译构建Makefile分析研读(2016.03版本)

    一.uboot的编译 首先来回顾一下uboot如何编译. (1)设置临时环境变量 export ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (2)指定板级配 ...

  9. 移植u-boot.2012.04.01

    /*************************************************** *u-boot版本:u-boot2012.04.01 *gcc版本:arm-linux-gcc ...

最新文章

  1. 使用OpenCV执行图像算法(加法和减法)以提亮图像或者使图像变暗
  2. JAVA操作Hadoop
  3. QT的QModbusResponse类的使用
  4. SAP Fiori Launchpad tile点击之后的跳转链接是如何解析出来的
  5. 学习Nutch不错的系列文章
  6. .NET 源代码库指南
  7. 高并发下秒杀商品,必须知道的9个细节
  8. Vuejs 插值操作
  9. 拖放获取文件信息的bat代码
  10. mysql json类型存储list_list存储json字符串
  11. 141.3. 单机安装 CentOS 5 + hadoop-0.20.0
  12. MinGW gcc下载链接及sjlj、dwarf、seh异同以及gcc安装
  13. 软件项目版本管理规范总结
  14. 数据库用户名和密码加密
  15. 计算机忘记网络,忘记密码后如何查看电脑无线网络密码
  16. 《涛声依旧》填词改编《测试依旧》
  17. ch9200 usb网卡驱动_21包邮的PCMCIA无线网卡开箱+对比测评
  18. 数据科学入门三个月的一些随想
  19. win10系统无法加载操作系统且自动恢复失败的解决方案
  20. 蓝牙规范-Vol 6:低功耗控制器 Part A 物理层规范

热门文章

  1. 为什么那么多的企业选择上云,上云有哪些优势?
  2. 2014-10-22威睿电通面试总结
  3. 为什么Windows电脑开机速度会变得越来越慢?由原先的几秒到了几十秒。了解这些方法将会助你杜绝卡顿(推荐适合电脑小白使用的杀毒软件)
  4. Leetcode学习笔记(974. 和可被 K 整除的子数组)
  5. 相位干涉仪测向的基础理论
  6. 主生产计划(MPS)及物料需求计划(MRP)
  7. SpringBoot集成阿里云支付
  8. 统一自己的mac和linux环境的终端使用(alacritty+tmux代替iterm2)
  9. 【​观察】重新定义销售 销售推的底气与微盟的梦想
  10. 赛道持续降温!又一家自动驾驶公司裁员,市值曾超50亿美元