<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > NAND FLASH驅動(dòng)程序

NAND FLASH驅動(dòng)程序

作者: 時(shí)間:2016-11-21 來(lái)源:網(wǎng)絡(luò ) 收藏
// 參考
* driversmtdnands3c2410.c
* driversmtdnandat91_nand.c
//
#include "linux/module.h"
#include "linux/types.h"
#include "linux/init.h"
#include "linux/kernel.h"
#include "linux/string.h"
#include "linux/ioport.h"
#include "linux/platform_device.h
#include "linux/delay.h"
#include "linux/err.h"
#include "linux/slab.h"
#include "linux/clk.h"
#include "linux/mtd/mtd.h"
#include "linux/mtd/nand.h"
#include "linux/mtd/nand_ecc.h"
#include "linux/mtd/partitions.h"
#include "asm/io.h"
#include "asm/arch/regs-nand.h"
#include "asm/arch/nand.h"
struct s3c_nand_regs {
unsigned long nfconf ;
unsigned long nfcont ;
unsigned long nfcmd ;
unsigned long nfaddr ;
unsigned long nfdata ;
unsigned long nfeccd0 ;
unsigned long nfeccd1 ;
unsigned long nfeccd ;
unsigned long nfstat ;
unsigned long nfestat0;
unsigned long nfestat1;
unsigned long nfmecc0 ;
unsigned long nfmecc1 ;
unsigned long nfsecc ;
unsigned long nfsblk ;
unsigned long nfeblk ;
};
static struct nand_chip *s3c_nand;
static struct mtd_info *s3c_mtd;
static struct s3c_nand_regs *s3c_nand_regs;
static struct mtd_partition s3c_nand_parts[] = {
[0] = {
.name = "bootloader",
.size = 0x00040000,
.offset = 0,
},
[1] = {
.name = "params",
.offset = MTDPART_OFS_APPEND, //緊跟著(zhù)上一個(gè)分區
.size = 0x00020000,
},
[2] = {
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = 0x00200000,
},
[3] = {
.name = "root",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL, //剩下的所有空間都是"root"分區
}
};
static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
if (chipnr == -1)
{
//取消選中: NFCONT[1]設為1
s3c_nand_regs->nfcont |= (1<<1);
}
else
{
// 選中: NFCONT[1]設為0
s3c_nand_regs->nfcont &= ~(1<<1);
}
}
static void s3c2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
if (ctrl & NAND_CLE)
{
// 發(fā)命令: NFCMMD=dat
s3c_nand_regs->nfcmd = dat;
}
else
{
// 發(fā)地址: NFADDR=dat
s3c_nand_regs->nfaddr = dat;
}
}
static int s3c2440_dev_ready(struct mtd_info *mtd)
{
return (s3c_nand_regs->nfstat & (1<<0));
}
static int s3c_nand_init(void)
{
struct clk *clk;
// 1. 分配一個(gè)nand_chip結構體
s3c_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
// 2. 設置nand_chip */
/ 設置nand_chip是給nand_scan函數使用的, 如果不知道怎么設置, 先看nand_scan怎么使用
/ 它應該提供:選中,發(fā)命令,發(fā)地址,發(fā)數據,讀數據,判斷狀態(tài)的功能
//
s3c_nand->select_chip = s3c2440_select_chip;
s3c_nand->cmd_ctrl = s3c2440_cmd_ctrl;
s3c_nand->IO_ADDR_R = &s3c_nand_regs->nfdata;
s3c_nand->IO_ADDR_W = &s3c_nand_regs->nfdata;
s3c_nand->dev_ready = s3c2440_dev_ready;
s3c_nand->ecc.mode = NAND_ECC_SOFT;
// 3. 硬件相關(guān)的設置: 根據NAND FLASH的手冊設置時(shí)間參數
// 使能NAND FLASH控制器的時(shí)鐘
clk = clk_get(NULL, "nand");
clk_enable(clk);
// HCLK=100MHz
* TACLS: 發(fā)出CLE/ALE之后多長(cháng)時(shí)間才發(fā)出nWE信號, 從NAND手冊可知CLE/ALE與nWE可以同時(shí)發(fā)出,所以TACLS=0
* TWRPH0: nWE的脈沖寬度, HCLK x ( TWRPH0 + 1 ), 從NAND手冊可知它要>=12ns, 所以TWRPH0>=1
* TWRPH1: nWE變?yōu)楦唠娖胶蠖嚅L(cháng)時(shí)間CLE/ALE才能變?yōu)榈碗娖? 從NAND手冊可知它要>=5ns, 所以TWRPH1>=0
//
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
s3c_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
// NFCONT:
* BIT1-設為1, 取消片選
* BIT0-設為1, 使能NAND FLASH控制器
//
s3c_nand_regs->nfcont = (1<<1) | (1<<0);
// 4. 使用: nand_scan
s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
s3c_mtd->owner = THIS_MODULE;
s3c_mtd->priv = s3c_nand;
nand_scan(s3c_mtd, 1); // 識別NAND FLASH, 構造mtd_info ,最大芯片個(gè)數1
// 5. add_mtd_partitions
add_mtd_partitions(s3c_mtd, s3c_nand_parts, 4); //分區數4
//add_mtd_device(s3c_mtd); //整個(gè)nand flash 作為一個(gè)分區使用
return 0;
}
static void s3c_nand_exit(void)
{
del_mtd_partitions(s3c_mtd);
kfree(s3c_mtd);
iounmap(s3c_nand_regs);
kfree(s3c_nand);
}
module_init(s3c_nand_init);
module_exit(s3c_nand_exit);
MODULE_LICENSE("GPL");
=================================================================
NAND FLASH是一個(gè)存儲芯片
那么: 這樣的操作很合理"讀地址A的數據,把數據B寫(xiě)到地址A"
問(wèn)1. 原理圖上NAND FLASH和S3C2440之間只有數據線(xiàn),
怎么傳輸地址?
答1.在DATA0~DATA7上既傳輸數據,又傳輸地址
當ALE為高電平時(shí)傳輸的是地址,
問(wèn)2. 從NAND FLASH芯片手冊可知,要操作NAND FLASH需要先發(fā)出命令
怎么傳入命令?
答2.在DATA0~DATA7上既傳輸數據,又傳輸地址,也傳輸命令
當ALE為高電平時(shí)傳輸的是地址,
當CLE為高電平時(shí)傳輸的是命令
當ALE和CLE都為低電平時(shí)傳輸的是數據
問(wèn)3. 數據線(xiàn)既接到NAND FLASH,也接到NOR FLASH,還接到SDRAM、DM9000等等
那么怎么避免干擾?
答3. 這些設備,要訪(fǎng)問(wèn)之必須"選中",
沒(méi)有選中的芯片不會(huì )工作,相當于沒(méi)接一樣
問(wèn)4. 假設燒寫(xiě)NAND FLASH,把命令、地址、數據發(fā)給它之后,
NAND FLASH肯定不可能瞬間完成燒寫(xiě)的,
怎么判斷燒寫(xiě)完成?
答4. 通過(guò)狀態(tài)引腳RnB來(lái)判斷:它為高電平表示就緒,它為低電平表示正忙
問(wèn)5. 怎么操作NAND FLASH呢?
答5. 根據NAND FLASH的芯片手冊,一般的過(guò)程是:
發(fā)出命令
發(fā)出地址
發(fā)出數據/讀數據
NAND FLASH S3C2440
發(fā)命令 選中芯片
CLE設為高電平 NFCMMD=命令值
在DATA0~DATA7上輸出命令值
發(fā)出一個(gè)寫(xiě)脈沖
發(fā)地址 選中芯片 NFADDR=地址值
ALE設為高電平
在DATA0~DATA7上輸出地址值
發(fā)出一個(gè)寫(xiě)脈沖
發(fā)數據 選中芯片 NFDATA=數據值
ALE,CLE設為低電平
在DATA0~DATA7上輸出數據值
發(fā)出一個(gè)寫(xiě)脈沖
讀數據 選中芯片 val=NFDATA
發(fā)出讀脈沖
讀DATA0~DATA7的數據
用UBOOT來(lái)體驗NAND FLASH的操作:
1. 讀ID
S3C2440 u-boot
選中 NFCONT的bit1設為0 md.l 0x4E000004 1; mw.l 0x4E000004 1
發(fā)出命令0x90 NFCMMD=0x90 mw.b 0x4E000008 0x90
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
讀數據得到0xEC val=NFDATA md.b 0x4E000010 1
讀數據得到device code val=NFDATA md.b 0x4E000010 1
0xda
退出讀ID的狀態(tài) NFCMMD=0xff mw.b 0x4E000008 0xff
2. 讀內容: 讀0地址的數據
使用UBOOT命令:
nand dump 0
Page 00000000 dump:
17 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5
S3C2440 u-boot
選中 NFCONT的bit1設為0 md.l 0x4E000004 1; mw.l 0x4E000004 1
發(fā)出命令0x00 NFCMMD=0x00 mw.b 0x4E000008 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
發(fā)出命令0x30 NFCMMD=0x30 mw.b 0x4E000008 0x30
讀數據得到0x17 val=NFDATA md.b 0x4E000010 1
讀數據得到0x00 val=NFDATA md.b 0x4E000010 1
讀數據得到0x00 val=NFDATA md.b 0x4E000010 1
讀數據得到0xea val=NFDATA md.b 0x4E000010 1
退出讀狀態(tài) NFCMMD=0xff mw.b 0x4E000008 0xff
NAND FLASH驅動(dòng)程序層次
看內核啟動(dòng)信息
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2440-nand s3c2440-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=3 30ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 256 at 0x02000000
Bad eraseblock 257 at 0x02020000
Bad eraseblock 319 at 0x027e0000
Bad eraseblock 606 at 0x04bc0000
Bad eraseblock 608 at 0x04c00000
Creating 4 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"
搜"S3C24XX NAND Driver"
S3c2410.c (driversmtdnand)
s3c2410_nand_inithw
s3c2410_nand_init_chip
nand_scan // drivers/mtd/nand/nand_base.c 根據nand_chip的底層操作函數識別NAND FLASH,構造mtd_info
nand_scan_ident
nand_set_defaults
if (!chip->select_chip)
chip->select_chip = nand_select_chip; // 默認值不適用
if (chip->cmdfunc == NULL)
chip->cmdfunc = nand_command;
chip->cmd_ctrl(mtd, command, ctrl);
if (!chip->read_byte)
chip->read_byte = nand_read_byte;
readb(chip->IO_ADDR_R);
if (chip->waitfunc == NULL)
chip->waitfunc = nand_wait;
chip->dev_ready
nand_get_flash_type
chip->select_chip(mtd, 0);
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
nand_scan_tail
mtd->erase = nand_erase;
mtd->read = nand_read;
mtd->write = nand_write;
s3c2410_nand_add_partition
add_mtd_partitions
add_mtd_device
list_for_each(this, &mtd_notifiers) { // 問(wèn). mtd_notifiers在哪設置
// 答. drivers/mtd/mtdchar.c,mtd_blkdev.c調用register_mtd_user
struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);
not->add(mtd);
// mtd_notify_add 和 blktrans_notify_add
先看字符設備的mtd_notify_add
class_device_create
class_device_create
再看塊設備的blktrans_notify_add
list_for_each(this, &blktrans_majors) { // 問(wèn). blktrans_majors在哪設置
// 答. driversmtdmdblock.c或mtdblock_ro.c register_mtd_blktrans
struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
tr->add_mtd(tr, mtd);
mtdblock_add_mtd (driversmtdmdblock.c)
add_mtd_blktrans_dev
alloc_disk
gd->queue = tr->blkcore_priv->rq; // tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock);
add_disk
測試4th:
1. make menuconfig去掉內核自帶的NAND FLASH驅動(dòng)
-> Device Drivers
-> Memory Technology Device (MTD) support
-> NAND Device Support
< > NAND Flash support for S3C2410/S3C2440 SoC
2. make uImage
使用新內核啟動(dòng), 并且使用NFS作為根文件系統,因為之前根文件系統在nand flash上面,現在內核去除了nand flash的驅動(dòng),內核就無(wú)法訪(fǎng)問(wèn)根文件系統了。
3. insmod s3c_nand.ko
4. 格式化 (參考下面編譯工具)
flash_eraseall /dev/mtd3 //擦除后本身就格式化成 yaffs文件系統,所以不用再格式化了
5. 掛接
mount -t yaffs /dev/mtdblock3 /mnt
6. 在/mnt目錄下建文件
編譯工具:
1. tar xjf mtd-utils-05.07.23.tar.bz2
2. cd mtd-utils-05.07.23/util
修改Makefile:
#CROSS=arm-linux-
改為
CROSS=arm-linux-
3. make
4. cp flash_erase flash_eraseall /work/nfs_root/first_fs/bin/
flash_erase:只擦除一個(gè)扇區
flash_eraseall:整個(gè)分區都擦除掉



關(guān)鍵詞: NANDFLASH驅動(dòng)程

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>