nand flash驱动调试学习
nand flash基础知识
nand flash上为什么只有地址线。如何传输数据和命令:
地址,数据,命令是复用的。使用ALE,CLE来进行区分的
通过RnB引脚来区分数据操作是否完成
nand flash驱动分析
从入口函数开始看:
865 static struct platform_driver s3c2412_nand_driver = {
866 .probe = s3c2412_nand_probe,
867 .remove = s3c2410_nand_remove,
868 .suspend = s3c24xx_nand_suspend,
869 .resume = s3c24xx_nand_resume,
870 .driver = {
871 .name = "s3c2412-nand",
872 .owner = THIS_MODULE,
873 },
874 };
struct mtd_info *s3c_mtd;
设备和驱动匹配上之后,会调用 s3c2412_nand_probe
s3c2412_nand_probe
1.分配
struct mtd_info mtd;
struct nand_chip chip;
这个两个关键的结构体:
代码:
struct s3c2410_nand_info *info;
info = kmalloc(sizeof(*info), GFP_KERNEL);
其中的数据结构定义为:
92 struct s3c2410_nand_mtd {93 struct mtd_info mtd;94 struct nand_chip chip;95 struct s3c2410_nand_set *set;96 struct s3c2410_nand_info *info;97 int scan_res;98 };108 struct s3c2410_nand_info {
109 /* mtd info */
110 struct nand_hw_control controller;
111 struct s3c2410_nand_mtd *mtds;
112 struct s3c2410_platform_nand *platform;
113
114 /* device info */
115 struct device *device;
116 struct resource *area;
117 struct clk *clk;
118 void __iomem *regs;
119 void __iomem *sel_reg;
120 int sel_bit;
121 int mtd_count;
122
123 enum s3c_cpu_type cpu_type;
124 };
可见非配的内存,包含了两个重要的结构体。
其中struct s3c2410_nand_set *set;为设备信息
[0] = {.name = "NAND",.nr_chips = 1,.nr_partitions = ARRAY_SIZE(smdk_default_nand_part),.partitions = smdk_default_nand_part,},
};/* choose a set of timings which should suit most 512Mbit* chips and beyond.
*/static struct s3c2410_platform_nand smdk_nand_info = {.tacls = 20,.twrph0 = 60,.twrph1 = 20,.nr_sets = ARRAY_SIZE(smdk_nand_sets),.sets = smdk_nand_sets,
};
- 设置nand chip结构体,根据设备信息,映射寄存器地址
667 static int s3c24xx_nand_probe(struct platform_device *pdev,
668 enum s3c_cpu_type cpu_type)
{
...
struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
720 info->device = &pdev->dev;
721 info->platform = plat;
722 info->regs = ioremap(res->start, size);
723 info->cpu_type = cpu_type;
...
}
这里struct s3c2410_platform_nand *plat = to_nand_plat(pdev); 这一句为什么可以这样赋值
16 struct platform_device { 17 const char * name; 18 u32 id; 19 struct device dev; 20 u32 num_resources; 21 struct resource * resource; 22 };32 struct s3c2410_platform_nand { 33 /* timing information for controller, all times in nanoseconds */34 35 int tacls; /* time for active CLE/ALE to nWE/nOE */ 36 int twrph0; /* active time for nWE/nOE */ 37 int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */ 38 39 int nr_sets; 40 struct s3c2410_nand_set *sets; 41 42 void (*select_chip)(struct s3c2410_nand_set *, 43 int chip); 44 };
因为两个结构体前面是一样的。
common-smdk.c和devs.c里面的所有信息,可以得到platform_device的所有配置信息
static struct resource s3c_nand_resource[] = {[0] = {.start = S3C2410_PA_NAND,.end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,.flags = IORESOURCE_MEM,}
};
struct platform_device s3c_device_nand = {.name = "s3c2410-nand",.id = -1,.num_resources = ARRAY_SIZE(s3c_nand_resource),.resource = s3c_nand_resource,
};EXPORT_SYMBOL(s3c_device_nand);static struct mtd_partition smdk_default_nand_part[] = {[0] = {.name = "bootloader",.size = 0x00040000,.offset = 0,},[1] = {.name = "params",.offset = MTDPART_OFS_APPEND,.size = 0x00020000,},[2] = {.name = "kernel",.offset = MTDPART_OFS_APPEND,.size = 0x00200000,},[3] = {.name = "root",.offset = MTDPART_OFS_APPEND,.size = MTDPART_SIZ_FULL,}
};static struct s3c2410_nand_set smdk_nand_sets[] = {[0] = {.name = "NAND",.nr_chips = 1,.nr_partitions = ARRAY_SIZE(smdk_default_nand_part),.partitions = smdk_default_nand_part,},
};
static struct s3c2410_platform_nand smdk_nand_info = {.tacls = 20,.twrph0 = 60,.twrph1 = 20,.nr_sets = ARRAY_SIZE(smdk_nand_sets),.sets = smdk_nand_sets,
};static struct platform_device __initdata *smdk_devs[] = {&s3c_device_nand,&led_dev,
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)&s3c_device_dm9k,
#endif
#ifdef CONFIG_SERIAL_EXTEND_S3C24xx&s3c_device_8250,
#endif
#ifdef CONFIG_TOUCHSCREEN_S3C2410&s3c_device_ts,
#endif
};
s3c_device_nand.dev.platform_data = &smdk_nand_info;
- 设置时钟和电平时间
err = s3c2410_nand_inithw(info, pdev);
- 填充mtd,和chip部分成员
s3c2410_nand_init_chip(info, nmtd, sets); 577 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
578 struct s3c2410_nand_mtd *nmtd,
579 struct s3c2410_nand_set *set)
580 { ...
84 chip->write_buf = s3c2410_nand_write_buf;
585 chip->read_buf = s3c2410_nand_read_buf;
586 chip->select_chip = s3c2410_nand_select_chip;
587 chip->chip_delay = 50;
588 chip->priv = nmtd;
589 chip->options = 0;
590 chip->controller = &info->controller;
...
622 chip->IO_ADDR_R = chip->IO_ADDR_W;
623
624 nmtd->info = info;
625 nmtd->mtd.priv = chip;
626 nmtd->mtd.owner = THIS_MODULE;
627 nmtd->set = set;
...
chip的成员函数,mtd层有默认操作函数,这里需要用户编写的只有部分和硬件操作相关的函数,dev_ready,select_chip,cmd_ctrl需要重新编写。
可以追查函数
cmd_ctrl 调用
nand_scan_ident 调用
nand_set_defaults(chip, busw);
2191 if (!chip->select_chip)
2192 chip->select_chip = nand_select_chip;
2193 if (!chip->read_byte)
2194 chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2195 if (!chip->read_word)
2196 chip->read_word = nand_read_word;
2197 if (!chip->block_bad)
2198 chip->block_bad = nand_block_bad;
2199 if (!chip->block_markbad)
2200 chip->block_markbad = nand_default_block_markbad;
2201 if (!chip->write_buf)
2202 chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2203 if (!chip->read_buf)
2204 chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2205 if (!chip->verify_buf)
2206 chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2207 if (!chip->scan_bbt)
2208 chip->scan_bbt = nand_default_bbt;
默认的select_chip函数
162 static void nand_select_chip(struct mtd_info *mtd, int chipnr)
163 {
164 struct nand_chip *chip = mtd->priv;
165
166 switch (chipnr) {
167 case -1:
168 chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
169 break;
170 case 0:
171 break;
172
173 default:
174 BUG();
175 }
176 }
可见select_chip在输入为0时,没有操作,需要用户自己构造这个函数
而默认的函数里面没有,dev_ready,cmd_ctrl这两个函数也需要用户进行编写。
nand_scan调用
这个函数会调用nand_get_flash_type,最终打印nand flash初始化的相关信息。设置mtd分区
550 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
551 struct s3c2410_nand_mtd *mtd,
552 struct s3c2410_nand_set *set)
553 {
554 if (set == NULL)
555 return add_mtd_device(&mtd->mtd);
556
557 if (set->nr_partitions > 0 && set->partitions != NULL) {
558 return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
559 }
560
561 return add_mtd_device(&mtd->mtd);
562 }
这里最终也会调用,add_mtd_device
参考的知识博客
nand flash学习
linux flash操作
linux flash 驱动调试
修改mtd分区
nand flash驱动调试学习相关推荐
- NAND FLASH学习笔记之MTD下nand flash驱动(一)
转载请注明:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础,我们就可以研究MTD下的nand驱动了,我这里用的 ...
- NAND FLASH学习笔记之MTD下nand flash驱动(四)
转载请注明出处:http://blog.csdn.net/wang_zheng_kai 四.Register到MTD子系统 两种注册方式:(我们需要完成的) 1)直接注册整个flash设备(MTD D ...
- NAND FLASH学习笔记之MTD下nand flash驱动(六)
六.驱动层之Flash读操作 MTD对NAND芯片的读写 主要分三部分: A.struct mtd_info中的读写函数,如read,write_oob等,这是MTD原始设备层与FLASH硬件层之间的 ...
- linux下nand flash驱动工作原理,Linux下Nand Flash 驱动代码分析
随着越来越多的平台支持从Nand Flash 中启动,掌握Nand Flash 的驱动编写有着重要的现实意义,由于内核已经完成了大部分的工作,实际工作中大部分工程师对Nand Flash 驱动只是简单 ...
- linux驱动编写(nand flash驱动)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很长一段时间,nand flash都是嵌入式的标配产品.nand flash价格便宜,存储量大, ...
- Linux MTD架构下的nand flash驱动详解
转载自:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础(Nandflash详解:https://blog.cs ...
- nand flash 经典 全面 ------如何编写Linux下Nand Flash驱动
Crifan Li 摘要 本文先解释了Nand Flash相关的一些名词,再从Flash硬件机制开始,介绍到Nand Flash的常见的物理特性,且深入介绍了Nand Flash的一些高级功能,然后开 ...
- 基于VXWORKS的NAND FLASH驱动程序设计
基于VXWORKS的NAND FLASH驱动程序设计 3162412793@qq.com 技术交流QQ群: 691976956 目前,随着电子技术的不断发展,计算机技术也得到飞速的发展,产生了很多新技 ...
- linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...
原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...
最新文章
- 小白巷分享 -- Laravel5的新特性之异常处理
- FFmpeg音视频入门-使用FFmpeg读取多媒体文件的信息C++代码实现+详解
- TOTP 介绍及基于 C# 的简单实现
- xxl-job架构源码解析
- 幻想三国android官方版,幻想三国ol官方版下载
- matlab shapley函数,合作博弈shapley值讲解.ppt
- Python爬虫,4567电影网电影信息爬取,二级页面处理方案
- 教你如何修复硬盘及恢复硬盘丢失数据
- HarmonyOS:Preferences的封装使用与避坑
- Python批量识别PDF文件格式发票信息并生成Excel表格
- 视觉SLAM十四讲slambook2/ch3/examples/plotTrajectory.cpp程序报错解决
- [前端系列]vue3修改模板变量间隔符
- 最新php面试题及答案
- #XDOJ 172 构造表达式
- 5G主要技术场景与六大关键技术
- 学微服务必经之路——Nacos新手入门(下)
- python 使用input函数输入两个数字,比较两个数字的大小,并输出较大的数
- DSP芯片F2803x系列之PWM模块及高精度PWM使用
- 文正机械电子工程专业课_机械电子工程课程编排
- MySQL驱动下载,JaveIDEA2022 如何导入mysql数据库驱动